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_model.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

The checkpoint flow A sequence with three participants: you, the agent, and the server. The agent reaches a checkpoint step and calls yield underscore checkpoint; the server records it. The agent calls present underscore checkpoint and receives the message and options, presents the decision to you, and you choose. The agent submits your choice with respond underscore checkpoint, then calls resume underscore checkpoint and continues working with any variable updates. You Agent Server yield_checkpoint checkpoint recorded, work pauses present_checkpoint message + options presents the decision to you your choice respond_checkpoint → resume_checkpoint work continues with any variable updates from your choice
The checkpoint flow with one agent. The agent yields at the checkpoint, fetches the message and options, presents the decision to you, submits your choice, and resumes.

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 bubble-up and resume The worker yields a checkpoint to the server and passes a handle up to the orchestrator, which relays it to the meta orchestrator. The meta orchestrator fetches the checkpoint details, presents the decision to you, and submits your choice to the server. The resolution then travels back down: the orchestrator wakes the worker, which calls resume underscore checkpoint and continues. Worker (L2) 1. yield_checkpoint 8. resume_checkpoint Orchestrator (L1) relays the yield up, wakes the worker after Meta (L0) 4. present_checkpoint 6. respond_checkpoint You 5. decide 2. checkpoint_yield + handle 3. relayed unchanged presents options your choice 7. effects passed down wake + variable updates top arrows: the pause bubbles up · bottom arrows: the resolution travels back down
Bubble-up and resume. The worker yields (1) and passes an opaque handle up through the orchestrator (2–3); the meta orchestrator fetches the details (4), you decide (5), and it submits your choice (6); effects travel back down (7) and the worker clears the gate with 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 and mints a one-shot, HMAC-signed checkpoint_handle. The worker emits the handle in a <checkpoint_yield> block in its final output and stops; the orchestrator relays the block upward without interpreting it. 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:

ModeMeaningServer enforcement
option_idYou selected an optionOption validated against the definition; minimum response time (default 3s) blocks instant self-resolution
auto_advanceTimer elapsed, use the default optionOnly for checkpoints with autoAdvanceMs; the full timer must have elapsed since the yield
condition_not_metConditional checkpoint's prerequisite is falseOnly 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. Before the worker can touch regular tools again it must call resume_checkpoint — a hard gate that verifies the checkpoint really was resolved and hands back the recorded variable updates. In inline (single-agent) execution the wake is a no-op persona switch; the server-side gates are identical.

Shared checkpoint fragments

A checkpoint reused at several sites is declared once as a checkpoint fragment under fragments.checkpoints in the owning workflow's workflow.yaml. Each use site is a kind:checkpoint step carrying only its site-local id and ref: [workflow::]name — plus a condition when the fragment declares none. The loader materializes the fragment body into the step before delivery, so yield, present, respond, and every downstream consumer see an ordinary full checkpoint. The check:fragments guard rejects an inline body that duplicates a declared fragment.

Why this design