The StatusEngine is Pentagon’s centralized state machine for agent status. Every status change — whether triggered by a hook event, a user action, or a stale sweep — flows through StatusEngine.apply(). This single function is the source of truth for all agent state transitions.
Two Detection Systems
Pentagon tracks agent status through two complementary systems:
| System | File | Writer | Purpose |
|---|
| Hook-based detection | status.json | Hook scripts (auto-generated) | Tracks Claude Code lifecycle events — session start, tool use, session end |
| Agent-driven reporting | report.json | The agent itself | Self-reported progress — what the agent is working on and how far along it is |
Hook-based detection is the primary mechanism. Pentagon watches status.json via DispatchSource and feeds changes into the StatusEngine. Agent-driven reporting is supplementary — it provides context for display but does not drive state transitions.
States
Pentagon defines five agent states, each with a visual representation on the canvas desk.
| State | Label | Ring Color | Hex | Trigger |
|---|
idle | Ready | Green | #4ADE80 | Session started, turn finished, or agent resumed |
active | Active | Yellow (pulsing) | #FBBF24 | Tool call in progress or heartbeat fired |
waitingInput | Needs Input | Green | #4ADE80 | Agent finished its turn, waiting for the next prompt |
dormant | Dormant | Gray | #6B7280 | User paused the agent |
error | Error | Red | #F87171 | Process error or stale agent detected |
The active state uses a pulsing ring animation to indicate ongoing work. All other states use a static ring.
Signals
Signals are the inputs to the StatusEngine. Each signal represents a discrete event that may cause a state transition.
| Signal | Source | Description |
|---|
sessionStarted | Hook script | Claude Code session has started |
stopRequested | Hook script | Agent has been asked to stop |
sessionEnded | Hook script | Claude Code session has ended |
heartbeatFired | HeartbeatScheduler | Heartbeat triggered a restart or wake |
toolUsed | Hook script | A tool call started or finished |
errorOccurred | Process monitor | The Claude Code process exited with an error |
userPaused | UI action | User paused the agent from the context menu |
userResumed | UI action | User resumed the agent from the context menu |
Hook Event to Signal Mapping
When a hook script writes to status.json, Pentagon reads the event field and maps it to a StatusEngine signal.
| Hook Event | Script | Signal |
|---|
SessionStart | session-start.sh | sessionStarted |
Stop | agent-stop.sh | stopRequested |
PreToolUse (sync) | tool-activity.sh | toolUsed |
PostToolUse (async) | post-tool.sh | toolUsed |
SessionEnd | session-end.sh | sessionEnded |
PreToolUse is a synchronous hook — Claude Code waits for it to complete before executing the tool. PostToolUse is asynchronous — it runs after the tool finishes without blocking.
State Transitions
All transitions are handled by StatusEngine.apply(signal:). Given a current state and an incoming signal, the engine produces the next state deterministically.
Key Transitions
| Current State | Signal | Next State | Description |
|---|
idle | toolUsed | active | Agent started a tool call |
idle | heartbeatFired | active | Heartbeat woke the agent |
active | stopRequested | idle | Agent finished its turn |
active | sessionEnded | idle | Session ended normally |
active | userPaused | dormant | User paused during active work |
active | errorOccurred | error | Process crashed or timed out |
dormant | userResumed | idle | User resumed the agent |
dormant | heartbeatFired | active | Heartbeat restarted a dormant agent |
waitingInput | sessionStarted | active | New session started |
waitingInput | toolUsed | active | Agent began working again |
error | sessionStarted | active | Agent recovered via restart |
error | userResumed | idle | User manually cleared the error |
Deterministic Resolution
StatusEngine.apply() is a pure function: the same (currentState, signal) pair always produces the same nextState. There is no hidden state, no race conditions, and no ambiguity. This makes the system predictable and debuggable.
Signals that are not valid for the current state are ignored. For example, a toolUsed signal while already in the active state refreshes the timestamp but does not change the state.
Stale Agent Detection
The StatusEngine runs a periodic sweep to detect agents that appear stuck.
Rule: Any agent in the active state for more than 60 seconds without a new status.json update is swept to the error state.
This catches cases where:
- The Claude Code process crashed without triggering a
SessionEnd hook
- A hook script failed to write
status.json
- The process is hung and not making progress
The 60-second threshold balances responsiveness (detecting stuck agents quickly) with tolerance (allowing long-running tool calls to complete).
Written atomically by hook scripts. This is the primary input to the StatusEngine.
{
"status": "active",
"since": "2025-07-15T14:30:00Z",
"event": "PreToolUse",
"activeTool": "Read"
}
| Field | Type | Description |
|---|
status | String | Raw status from the hook event |
since | ISO 8601 | Timestamp of the event |
event | String | The hook event that triggered the write |
activeTool | String? | Tool name, present only for PreToolUse and PostToolUse events |
Written by the agent to self-report progress. Read-only from Pentagon’s perspective — displayed in the Detail Panel but does not affect state transitions.
{
"summary": "Implementing auth module",
"task": "Add JWT validation",
"progress": "3/5"
}
| Field | Type | Description |
|---|
summary | String | Brief description of current work |
task | String | The specific task being worked on |
progress | String | Freeform progress indicator |
Visual Mapping
The StatusEngine state maps directly to the visual representation on each agent’s canvas desk.
| State | Ring Color | Animation | Meaning |
|---|
idle | Green (#4ADE80) | Static | Ready for input |
active | Yellow (#FBBF24) | Pulsing | Working |
waitingInput | Green (#4ADE80) | Static | Finished turn, awaiting follow-up |
dormant | Gray (#6B7280) | Static | Paused |
error | Red (#F87171) | Static | Needs attention |
The pulsing animation on active desks provides an at-a-glance indicator of which agents are currently working, even when zoomed out on a crowded canvas.
Related Pages
- Architecture — how the StatusEngine fits into Pentagon’s event-driven design
- Agent File System — file format details for status.json and report.json
- Agents — agent lifecycle and status states overview