Just-in-time checkpoints
Checkpoints are declarative gates inside activities that halt the workflow until an external condition is met — usually your explicit confirmation. The agent cannot skip past one: the server records the active checkpoint in session state and refuses to advance until it is resolved.
Canonical source: docs/checkpoint.md.
Where you stay in control
A checkpoint is a step where the workflow deliberately stops until you decide something: approve a design, pick an option, confirm a commit.
Single-agent flow
Your choice can set workflow variables — picking "skip the audit" or "include migration" changes which activities and steps run afterwards. Some checkpoints define a default option and can auto-advance after a timeout; the server still enforces the timer.
Multi-agent bubble-up
Background workers cannot ask you questions directly, so a checkpoint bubbles up the agent hierarchy to the user-facing agent, and the resolution travels back down.
<checkpoint_yield> block that travels up through the orchestrator (2–3); the meta orchestrator reads the open checkpoint from the session (4), you decide (5), and it submits your choice (6); effects travel back down (7) and the worker calls resume_checkpoint (8) before continuing.Yielding
When a worker reaches a checkpoint step it calls yield_checkpoint. The server records the checkpoint as activeCheckpoint in session.json. The worker emits an empty <checkpoint_yield> block in its final output and stops; the orchestrator relays the block upward, and the user-facing agent reads the open checkpoint from the session with present_checkpoint. A new checkpoint cannot be yielded while one is already active — nested yields are a hard error.
Resolving
The meta orchestrator calls present_checkpoint to fetch the human-readable message, options, and effects, presents the decision through the host UI, then finalizes with respond_checkpoint in exactly one of three modes:
| Mode | Meaning | Server enforcement |
|---|---|---|
option_id | You selected an option | Option validated against the definition; minimum response time (default 3s) blocks instant self-resolution |
auto_advance | Timer elapsed, use the default option | Only for checkpoints with autoAdvanceMs; the full timer must have elapsed since the yield |
condition_not_met | Conditional checkpoint's prerequisite is false | Only valid when the checkpoint defines a condition |
The server clears activeCheckpoint, records the decision and any variable effects (e.g. setVariable: { is_monorepo: true }) in the session state, and returns the effects to the caller.
Resuming
Agents wake in reverse order using the host's resume mechanism, with effects passed down as plain instructions. The worker then calls resume_checkpoint, which verifies the checkpoint was resolved and returns the checkpoint answered, the option chosen, the variables that option set, and the exit it selected, if any; an exit carrying ends_activity ended the activity at the checkpoint, so the worker runs none of the remaining steps. Called while the checkpoint is still active, it is a hard error. In inline (single-agent) execution the wake is a no-op persona switch; the server-side gates are identical.
A checkpoint used at several sites
A checkpoint reused at several sites is a routine: the gate is declared once under the owning workflow's routines/, and each site is a kind:routine step that refers to it. A gate that is not part of a larger run is a one-step routine. The routine declares what it takes and what it produces, and its body is held against that signature; the reference prefixes every identifier the run contributes, so two sites cannot collide on a step id or a replay key. The loader materializes the reference before delivery, so yield, present, respond and every downstream consumer see an ordinary full checkpoint. The check:duplicate-bodies guard reports a checkpoint body authored inline at two sites.
Why this design
- Pause and presentation are separate — the worker records the pause with
yield_checkpointand steps aside; the user-facing agent later presents and responds. Nothing advances past an unresolved checkpoint, wherever it was raised. - Clean UI boundaries — hidden background agents never prompt you directly, so nothing freezes waiting on an invisible question.
- Stateless hand-offs — the session's
activeCheckpointlinks the pause to its answer; intermediate agents relay an empty block and hold no checkpoint details. - Timing enforcement — minimum response times and server-enforced auto-advance timers prevent an agent from "answering" its own checkpoint instantly.
- Effects as data — your choice mutates workflow variables through declared effects, which is what makes deterministic transitions possible.