Plan and resume
On this page
This tutorial turns a single task into a small plan, works one phase, and resumes the plan from cold, so you can see how your agent holds a multi-step plan together across a reset. The agent forks three phases off a root task, orders them with depends-on edges, asks cairn which phase is ready, marks a phase completed, watches the ready set move, then bootstraps back into the plan as a fresh session would. By the end the plan lives in the graph, not in the conversation, so a context reset reloads it instead of losing it.
You need cairn installed and reachable over MCP, and your agent should have run the bootstrap-observe-handoff loop at least once. This tutorial assumes you know what a task, an observation, and a handoff are; if not, read Tasks, observations, and handoffs first. Each call below is shown the way the agent issues it over MCP, and the text after it is what cairn returns.
Create the root task
A plan in cairn is a root task with phases hanging off it, not a markdown file. The agent creates the root first:
task_create(name="ship the export feature")
Created 2026-06-22-ship-the-export-feature.
The slug is date-prefixed and minted from the name. task_create adopts the new task as the current task because none was set, so every following call that omits task_id acts on it.
Fork the phases
A phase is a child task joined to its parent by a phase-of edge. task_fork mints the child, records both task.create and task.fork, and, unlike task_create, always switches the current pointer to the new child.
The parent argument is from. When the agent omits it, task_fork forks from the current task. Here it forks three phases, passing from so each hangs off the root rather than off the previous child:
task_fork(name="design the export schema", from="2026-06-22-ship-the-export-feature")
Forked 2026-06-22-design-the-export-schema from 2026-06-22-ship-the-export-feature (phase-of).
task_fork(name="implement the writer", from="2026-06-22-ship-the-export-feature")
Forked 2026-06-22-implement-the-writer from 2026-06-22-ship-the-export-feature (phase-of).
task_fork(name="add the download button", from="2026-06-22-ship-the-export-feature")
Forked 2026-06-22-add-the-download-button from 2026-06-22-ship-the-export-feature (phase-of).
The default edge_type is phase-of, so it was not passed. A fork with no from and no current task fails with No parent task; pass from or select a task first.
The current pointer now sits on the last child forked. That is fine; the next steps address tasks by slug, which never disturbs the pointer.
Order the phases
The phases are siblings under one parent. Nothing yet says the writer waits on the schema, or that the button waits on the writer. A depends-on edge says exactly that. task_link draws a typed edge from a source task to a target; the agent passes task_id to set the source explicitly rather than rely on wherever the pointer happens to be.
The writer depends on the schema:
task_link(task_id="2026-06-22-implement-the-writer", target_id="2026-06-22-design-the-export-schema", edge_type="depends-on")
Linked 2026-06-22-implement-the-writer -> 2026-06-22-design-the-export-schema (depends-on).
The download button depends on the writer:
task_link(task_id="2026-06-22-add-the-download-button", target_id="2026-06-22-implement-the-writer", edge_type="depends-on")
Linked 2026-06-22-add-the-download-button -> 2026-06-22-implement-the-writer (depends-on).
edge_type is required for task_link and must be one of phase-of, depends-on, or related. phase-of is the structural backbone the forks already built; depends-on is lateral ordering between siblings. The plan is now described: three phases, with a chain of dependencies running schema → writer → button.
Ask what is ready
The frontier is the ready subset of a plan: the phases that are not done and whose dependencies are all settled. cairn computes it; the agent does not work it out by hand. The agent sets the pointer back to the root first, because plan-frontier is current-scoped: it reads the phases of the current task and keeps the ones with no unsettled depends-on target.
task_bootstrap(task_id="2026-06-22-ship-the-export-feature")
That orients on the root and makes it current, which is what the plan and plan-frontier views read from. Now the agent queries the frontier. The query argument is a single TQ form, and a named view is run by wrapping its name as (query "plan-frontier"):
task_query(query="(query \"plan-frontier\")")
1 task:
- 2026-06-22-design-the-export-schema (active) obs=0 edges=2
Only the schema phase comes back. The writer is blocked behind the schema and the button behind the writer, so neither is ready yet. The obs=0 edges=2 suffix is enrichment the plan-frontier view carries: an observation count and an edge count. Here that edge count is the one phase-of link up to the root plus the one incoming depends-on from the writer.
Complete a phase and re-query
Once the schema work is done, the agent marks the phase complete. task_update_status takes a status from the closed set open, active, completed, abandoned, blocked, and is idempotent.
task_update_status(task_id="2026-06-22-design-the-export-schema", status="completed")
2026-06-22-design-the-export-schema is now completed.
The agent asks the frontier again. The root is still current, so no re-orientation is needed:
task_query(query="(query \"plan-frontier\")")
1 task:
- 2026-06-22-implement-the-writer (active) obs=0 edges=3
The frontier moved. The schema dropped out because it is settled, and the writer surfaced because its one dependency is now completed. The button is still held back behind the writer. The writer's edges=3 counts its phase-of link to the root, its outgoing depends-on to the schema, and the incoming depends-on from the button. No plan document was edited; one status changed and the ready set recomputed from the graph. This is how the agent finds the next thing to do without re-reading the whole plan: Views documents the other built-in views, plan, leaf-tasks, and stale-phases, that answer related questions.
Resume the plan in a new session
Now simulate what happens after a context reset, a /clear, or a colleague's agent picking up the work tomorrow. The plan is in the graph; one call reloads it. task_bootstrap returns computed state, neighbors, open handoffs, and recent observations, and records no event, so orienting never mutates the log.
task_bootstrap(task_id="2026-06-22-ship-the-export-feature")
2026-06-22-ship-the-export-feature [active]
children: 2026-06-22-add-the-download-button, 2026-06-22-design-the-export-schema, 2026-06-22-implement-the-writer
The whole plan came back from the slug alone: the root, its status, and the three phases hanging off it as children. The phase-of backbone is what the children: line reports; the lateral depends-on edges live between the phases, so they surface when the agent queries the frontier rather than in the root's neighbor readout. From here the agent re-runs (query "plan-frontier") to find the writer waiting, and the work resumes with no memory of the previous session required.
That is the cairn method end to end: one status change moved the frontier from the schema to the writer, and a single task_bootstrap reloaded the whole plan from the slug. To go deeper, read Plans, phases, and the frontier for the readiness rule, and The cairn-method for the working discipline a real plan runs inside.