Agents
Programs that write code write plans too, and left alone they scatter TODO files in formats of their own devising. The answer is a schema, and tools that enforce it.
Over MCP
cairn mcp --config
That prints the snippet for .mcp.json, .cursor/mcp.json or wherever your
client keeps its configuration. cairn mcp then serves the backlog over the
Model Context Protocol on standard input and output, with tools covering
get_schema, next_items, list_items, search_items, show_item,
claim_item, create_item, update_item, add_note, tick_criteria,
propose_change, release_item, close_item and check.
The CLI and MCP validate changes against the same project schema. Choose the interface the agent works with well. Generated instructions explain the project; validated writes enforce its structure. These are cooperative workflow rules, not a security boundary against a process that can edit the files directly.
A rejected write teaches
Failures come back in the result rather than as protocol errors, so the model can read what went wrong and correct itself.
update_item {"id": 3, "fields": {"status": "in progress"}}
unknown status `in progress`
known: backlog, planned, doing, blocked, done, droppedThe most common mistake, and the reason for it is worth knowing: a status has a name and a label. Tables show the label; every write takes the name.
The loop an agent follows
get_schema— statuses, fields and milestones are declared per project and are not fixed. Ask first.next_items— work that is genuinely startable. Anything waiting on unfinished work is excluded, and what is already under way comes first.claim_item— take it before starting, so two workers do not duplicate each other. Called with no id it takes the top-ranked unclaimed item and returns its body, so work can begin in one call.add_note— record why something was decided. Distinct fromupdate_item’s body, which replaces: a caller writing down its reasoning must not be able to erase what came before.close_item, thencheckbefore reporting done.
Item responses carry blocked, ready and blockers by default,
because dependency state is what an agent most needs and cannot work out from a
single item.
Dependency readiness is not an approval to implement every open idea. Scope
next_items and claim_item with the project’s approved-work filter, such as
status=planned. Search with all=true before proposing a change so completed
and dropped decisions are part of the context.
Work is recorded under the caller’s name
Identity comes from CAIRN_USER if set, then the name the client gave in its
MCP handshake, then the login.
Without MCP
cairn agent --write AGENTS.md
For a client that speaks no protocol, this writes an instruction block generated from your live schema — the real statuses, the real fields, the real milestones — between markers, so re-running it updates the block and leaves the rest of the file alone.
Because it is generated, it cannot describe a workflow the project does not
have. Agents then read with cairn list --json and cairn show <id> --json,
and write with cairn new, cairn set and cairn note.
Two agents at once
Mutating commands take a lock; reads never do, so listing never queues behind somebody’s write. Forty processes creating items simultaneously produce forty distinct identifiers, and twelve agents racing for one item produce exactly one owner and eleven refusals that name the holder.
This exclusion holds within one item directory. Across the worktrees of one
repository on one machine, cairn reads what each other worktree has claimed:
next leaves it out, claim refuses it without --force, and cairn worktrees lists it. Separate clones can still claim the same item
independently. Agree on assignments before splitting work across clones, and
review the item changes when merging.
Identifiers can also collide across branches. cairn init --git installs merge
support once per working copy; validation and review still matter after a merge.