The plan verb maintains a thread's visible checklist: the structure the user watches while an agent works. A plan is not decoration — its steps organize the run tree, and leaving it unfinished is a debt the system accounts for (Obligations).
Steps
Each step is {id, label, status} with status pending | running | done | failed | skipped. Ids are stable; labels are not — models rewrite them freely as understanding improves, so everything that matters joins on the id.
The checklist is stored on the session (plan_cbor) and rendered fresh into each turn's replay as a <plan_state> block rather than being stored as a Log event. That matters: after children have run and changed the world, the agent sees the current state of the checklist it published, not a stale copy from when it wrote it. The block ends with a standing instruction — update statuses with the plan verb before you finish your reply.
Because step ids and labels are model-authored text handed back to the model inside a frame the model trusts, they get the same escaping treatment as user-action payloads: a label crafted to be the closing tag is neutralized, not censored (Security).
Attachment: steps own their children
A child spawned while a step is running belongs to that step, joined by planStepId. The step row in the UI is the way into its children — expand the step, find the work. A batch step owns an entire parallel fan-out, rendered as uniform peers under one running step.
The join prefers the stable id and falls back to the label only for runs spawned before that field existed — a small compatibility detail that exists precisely because labels drift.
Runtime-derived settlement
A step whose attached children all succeeded is closed by the runtime, stamped resolvedBy: 'runtime', and that settlement is carried forward across later plan edits. Only success is ever derived this way: the runtime never writes a step off, never marks failure on the model's behalf, and never ticks a box the evidence doesn't support.
When a checklist first goes fully terminal, settledAt records the moment — which is when the pinned card leaves its slot and freezes into the log as history (Desktop).
Plans and endings
A run that wants to end while steps sit neither finished nor written off has plan debt. The obligations contract asks it to settle honestly — finish, or explicitly write off — and if the ask budget runs out, the run ends owing the debt visibly rather than having it silently forgiven.
Scripts have plans too
A script child publishes a checklist with ctx.plan(...) and marks units of work with ctx.step(label, fn), which journals a start and end phase around the function. The two surfaces render as one merged checklist on the run card.
Related
The Five Verbs — plan among its peers
Delegation — the children steps own
Obligations — plan debt at the end of a run
Do you like what you are reading? Subscribe to receive updates.
Unsubscribe anytime