Skip to main content
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:
SystemFileWriterPurpose
Hook-based detectionstatus.jsonHook scripts (auto-generated)Tracks Claude Code lifecycle events — session start, tool use, session end
Agent-driven reportingreport.jsonThe agent itselfSelf-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.
StateLabelRing ColorHexTrigger
idleReadyGreen#4ADE80Session started, turn finished, or agent resumed
activeActiveYellow (pulsing)#FBBF24Tool call in progress or heartbeat fired
waitingInputNeeds InputGreen#4ADE80Agent finished its turn, waiting for the next prompt
dormantDormantGray#6B7280User paused the agent
errorErrorRed#F87171Process 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.
SignalSourceDescription
sessionStartedHook scriptClaude Code session has started
stopRequestedHook scriptAgent has been asked to stop
sessionEndedHook scriptClaude Code session has ended
heartbeatFiredHeartbeatSchedulerHeartbeat triggered a restart or wake
toolUsedHook scriptA tool call started or finished
errorOccurredProcess monitorThe Claude Code process exited with an error
userPausedUI actionUser paused the agent from the context menu
userResumedUI actionUser 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 EventScriptSignal
SessionStartsession-start.shsessionStarted
Stopagent-stop.shstopRequested
PreToolUse (sync)tool-activity.shtoolUsed
PostToolUse (async)post-tool.shtoolUsed
SessionEndsession-end.shsessionEnded
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 StateSignalNext StateDescription
idletoolUsedactiveAgent started a tool call
idleheartbeatFiredactiveHeartbeat woke the agent
activestopRequestedidleAgent finished its turn
activesessionEndedidleSession ended normally
activeuserPauseddormantUser paused during active work
activeerrorOccurrederrorProcess crashed or timed out
dormantuserResumedidleUser resumed the agent
dormantheartbeatFiredactiveHeartbeat restarted a dormant agent
waitingInputsessionStartedactiveNew session started
waitingInputtoolUsedactiveAgent began working again
errorsessionStartedactiveAgent recovered via restart
erroruserResumedidleUser 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).

status.json Format

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"
}
FieldTypeDescription
statusStringRaw status from the hook event
sinceISO 8601Timestamp of the event
eventStringThe hook event that triggered the write
activeToolString?Tool name, present only for PreToolUse and PostToolUse events

report.json Format

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"
}
FieldTypeDescription
summaryStringBrief description of current work
taskStringThe specific task being worked on
progressStringFreeform progress indicator

Visual Mapping

The StatusEngine state maps directly to the visual representation on each agent’s canvas desk.
StateRing ColorAnimationMeaning
idleGreen (#4ADE80)StaticReady for input
activeYellow (#FBBF24)PulsingWorking
waitingInputGreen (#4ADE80)StaticFinished turn, awaiting follow-up
dormantGray (#6B7280)StaticPaused
errorRed (#F87171)StaticNeeds 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.
  • 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