State Transitions

Complete transition table for the agent state machine defined in agent::state.

Transition Table

From StateEventTo StateSide Effect
InitializingWorktreeReadyBuildingPromptNone
BuildingPromptPromptReady(prompt)SpawningStorePrompt(prompt)
SpawningSessionStarted(seq)Running { session_seq: seq }None (resets consecutive_errors to 0)
SpawningSessionExited(Error)CoolingDown or StoppedNone or LogFatal (if threshold reached)
SpawningSessionExited(Timeout)CoolingDown or StoppedNone or LogFatal (if threshold reached)
RunningSessionExited(Success)SessionCompleteNone (resets consecutive_errors to 0)
RunningSessionExited(Error)CoolingDown or StoppedNone or LogFatal (if threshold reached)
RunningSessionExited(Timeout)CoolingDown or StoppedNone or LogFatal (if threshold reached)
RunningUrgentMessageInterrupting { session_seq }CancelSession
InterruptingSessionExited(*)BuildingPromptNone (no error increment)
InterruptingGraceExceededBuildingPromptForceStopSession
SessionCompleteWorktreeReadyBuildingPromptIncrementSession (bumps session_seq)
CoolingDownBackoffElapsedBuildingPromptNone

Global Transitions

These events are valid from any state:

EventTo StateSide Effect
OperatorStopStoppedCancelSession if currently Running or Interrupting; None otherwise
FatalError(msg)StoppedLogFatal(msg)

Error Counters

The state machine maintains two counters that affect transitions:

CounterIncremented OnReset OnFatal Threshold
consecutive_errorsAny SessionExited(Error|Timeout) from Running or SpawningSessionStarted or SessionExited(Success)Default: 5 (max_consecutive_errors)
total_errorsAny SessionExited(Error|Timeout) from Running or SpawningNeverDefault: 20 (max_total_errors)

When a counter reaches its threshold, the state transitions to Stopped with LogFatal instead of CoolingDown.

Note: SessionExited(*) from Interrupting does not increment error counters — interrupts are intentional, not errors.

Backoff Formula

The CoolingDown duration uses exponential backoff:

duration_ms = min(2000 * 2^(n-1), 60000)

Where n = consecutive_errors after increment.

nDuration
12,000 ms (2s)
24,000 ms (4s)
38,000 ms (8s)
416,000 ms (16s)
532,000 ms (32s)
6+60,000 ms (60s, cap)

State Diagram

Initializing ──WorktreeReady──► BuildingPrompt ◄──BackoffElapsed── CoolingDown
                                     │                                  ▲
                                     │ PromptReady                      │
                                     ▼                                  │
                                  Spawning ──Error/Timeout──────────────┤
                                     │                                  │
                                     │ SessionStarted                   │
                                     ▼                                  │
                                  Running ──Error/Timeout───────────────┘
                                   │   │
                      Success      │   │ UrgentMessage
                         │         │   ▼
                         ▼         │ Interrupting ──SessionExited──► BuildingPrompt
                  SessionComplete  │              ──GraceExceeded──► BuildingPrompt
                         │         │
                         │ WorktreeReady
                         └──────────────────────────────────────────► BuildingPrompt

                  OperatorStop or FatalError from ANY state ──────► Stopped

ExitOutcome

The ExitOutcome enum describes how a backend session ended:

VariantDescription
SuccessSession completed normally
Error(String)Session failed with an error message
TimeoutSession exceeded its timeout