Skip to Content
Runs & ControlLifecycle & Control

Lifecycle & Control

A run is in exactly one of six states. Status is folded from the event log rather than stored beside it, so there is no second source that can disagree with what happened.

The states

StatusMeaningTerminal
runningExecuting nowno
pausedStopped cooperatively at a safe pointno
waiting_answerParked on an interrupt, waiting for inputno
completedFinished, with a resultyes
failedFinished, with an erroryes
cancelledStopped and will not continueyes

There is no queued state. A run is running from the moment it starts.

from agentdeck.core.status import RunStatus RunStatus.RUNNING, RunStatus.PAUSED, RunStatus.WAITING_ANSWER RunStatus.COMPLETED, RunStatus.FAILED, RunStatus.CANCELLED

What moves a run between them

Each lifecycle event sets exactly one status, which is why the log and the status can never disagree.

EventResulting status
run.startedrunning
run.pausedpaused
run.interruptedwaiting_answer
run.resumedrunning
run.completedcompleted
run.failedfailed
run.cancelledcancelled

What you can act on

paused and waiting_answer are the two resumable states. The three terminal states accept nothing: a completed run cannot be paused, and a cancelled run cannot be resumed.

run = await deck.runs.start("Jack", question) await run.pause() # running -> paused, at the next safe point await run.resume() # paused -> running await run.cancel() # -> cancelled await run.answer(value) # waiting_answer -> running status = await run.status() # a coroutine, not a property

pause and cancel are requests, not interrupts. The run records the signal, then acts on it when it next reaches a safe point: between stream items, before dispatching a tool, or at a node boundary. Two events make that visible, control.requested when the signal is recorded and control.observed when the run picks it up, so a control that has not taken effect yet is distinguishable from one that was never seen.

  • Runs - starting a run and getting the handle back
  • Pause / Resume - safe points in more detail
  • Human Input - answering a run parked at an interrupt
  • Events - every event kind and its payload