# Plan and resume


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](/cairn/get-started/your-first-cairn-session) at least once. This tutorial assumes you know what a task, an observation, and a handoff are; if not, read [Tasks, observations, and handoffs](/cairn/concepts/tasks-observations-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:

```text
task_create(name="ship the export feature")
```

```text
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](/cairn/concepts/the-current-task-pointer) 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:

```text
task_fork(name="design the export schema", from="2026-06-22-ship-the-export-feature")
```

```text
Forked 2026-06-22-design-the-export-schema from 2026-06-22-ship-the-export-feature (phase-of).
```

```text
task_fork(name="implement the writer", from="2026-06-22-ship-the-export-feature")
```

```text
Forked 2026-06-22-implement-the-writer from 2026-06-22-ship-the-export-feature (phase-of).
```

```text
task_fork(name="add the download button", from="2026-06-22-ship-the-export-feature")
```

```text
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:

```text
task_link(task_id="2026-06-22-implement-the-writer", target_id="2026-06-22-design-the-export-schema", edge_type="depends-on")
```

```text
Linked 2026-06-22-implement-the-writer -> 2026-06-22-design-the-export-schema (depends-on).
```

The download button depends on the writer:

```text
task_link(task_id="2026-06-22-add-the-download-button", target_id="2026-06-22-implement-the-writer", edge_type="depends-on")
```

```text
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.

```text
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")`:

```text
task_query(query="(query \"plan-frontier\")")
```

```text
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.

```text
task_update_status(task_id="2026-06-22-design-the-export-schema", status="completed")
```

```text
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:

```text
task_query(query="(query \"plan-frontier\")")
```

```text
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](/cairn/reference/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.

```text
task_bootstrap(task_id="2026-06-22-ship-the-export-feature")
```

```text
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](/cairn/concepts/plans-phases-and-the-frontier) for the readiness rule, and [The cairn-method](/cairn/concepts/the-cairn-method) for the working discipline a real plan runs inside.
