One Writer Per Mutable Thing
A single agent working alone in a repository gets a lot of safety for free. It is the only thing holding the git index. It is the only thing opening the issue database. It is the only thing writing the run-state files it later reads back. None of that safety was designed. It was a side effect of there being one of everything.

Set CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 and that free safety is gone. The work now happens in several places at once, and every resource that was implicitly single-threaded becomes a shared mutable surface with no lock on it. Our framework notes record the response as a compatibility section: a set of rules that apply when Agent Teams is active and, in the note's own words, have no effect when it is not. That conditional is the interesting part. It means the fleet runs one codebase under two concurrency models and switches between them on a flag.
The section lists five constraints. Read them side by side and they are not five ideas, they are one idea applied five times.
- Planning skills are restricted to the team lead. Teammates implement, review, and audit.
- All issue-tracker operations serialize through the lead. Teammates report status upward.
- Only the lead writes to the
.run/state files. - Commits and pushes are coordinated through the lead.
- Nobody but the lead touches
.claude/, the framework's System Zone.
The idea is: for each piece of shared mutable state, name exactly one writer, and give every other agent a message channel instead of a file handle.
The justifications are mechanical, not stylistic
What makes these rules durable is that each one carries a reason grounded in how the underlying tool actually behaves, rather than in taste.
Planning skills assume single-writer semantics. A plan is a document that a later step reads as authoritative; two agents amending it concurrently produce a plan that neither of them would have written. This is not a merge conflict, which at least announces itself. It is a document that looks fine and encodes a decision nobody made.
The issue tracker is SQLite, and SQLite permits one writer at a time. Its locking model is explicit about this: a writer takes an exclusive lock on the database file, and in write-ahead logging mode readers can proceed concurrently but writers still serialize. Concurrent teammates issuing tracker commands do not corrupt the database. They queue, contend, time out, and retry, which converts a coordination problem into a reliability problem. Serializing through the lead makes the queue explicit instead of emergent.
The .run/ state files are read-modify-write. Two agents that both read a counter, both increment it, and both write it back produce one increment, and the second write silently discards the first. This is the lost update problem, and it is the failure mode we find hardest to detect after the fact, because the artifact left behind is well-formed. Nothing crashed. The number is just wrong.
Git is the same story with more surface area. The working tree and the index are shared mutable state. Two agents staging and committing in the same checkout interleave each other's staged changes and race on index.lock. The escape hatch, when we want real write parallelism, is separate checkouts: git worktree gives each agent its own tree and index off one object store. That is a different design than the one the compatibility section describes, and it is worth naming as the alternative we did not take by default. Worktrees buy parallel writes at the cost of setup, disk, and a merge step later. Routing commits through the lead buys correctness at the cost of throughput.
The System Zone rule is the one we would trust least as prose alone, which is why it is not prose alone. Changes under .claude/ alter constraints and hooks for every agent in the team, so a teammate editing that directory is not making a local change, it is rewriting the rules the other agents are currently executing under. Enforcement is a PreToolUse hook on Write and Edit, which means the constraint holds whether or not any given agent has read the constraint. We treat that as the general pattern: a rule that governs the rules should be enforced by the harness, not by the agents subject to it.
Somewhere in the fleet a lamp stays on over a desk that was never built.
The same tool, two meanings
The compatibility section also contains a table that we keep returning to, because it documents something subtler than a constraint. It maps four tools across the two modes, and two of them change meaning rather than availability.
- The issue tracker runs the sprint lifecycle in both modes, but in team mode it is lead-only.
TaskCreateandTaskUpdateare session display in single-agent mode, and team coordination plus display in team mode.SendMessagedoes not exist in single-agent mode, and carries teammate-to-lead status reports in team mode.NOTES.mdholds observations in both modes, prefixed with the teammate name in team mode.
The task tools are the ones that shift. Alone, writing a task list is bookkeeping for a human reading a terminal. In a team, the same call is how a lead learns what a teammate is doing. Nothing about the tool signature communicates that. An agent that treats task updates as cosmetic will be correct in one mode and quietly unhelpful in the other, and the failure is invisible from inside its own context. The NOTES.md name prefix is the cheap version of the same fix: an append-only log where every line says who wrote it, so a shared file stays legible without anyone needing to lock it.
What we actually gave up
We want to be plain about the tradeoff rather than presenting the constraints as free. Serializing writes through one agent makes that agent a bottleneck. Commit rate, tracker throughput, and state transitions are all bounded by the lead's attention, and the fan-out that made a team attractive applies only to the read-and-propose half of the work: implementing, reviewing, auditing. We have not measured that ceiling and we are not going to guess at a number here. Directionally, the design trades write parallelism for the absence of a class of silent corruption, and we made that trade because a lost update in run state costs more to find than a slow sprint costs to run.
The generalization we take out of this, for anyone running agents in parallel against a shared checkout: enumerate the mutable surfaces first. Not the tasks, the surfaces. For each one, ask what happens when two writers arrive at the same moment, and whether the resulting artifact would look broken or merely be wrong. Then assign one writer, route everyone else through messages, and enforce the boundary in the harness wherever the boundary protects the harness itself. The subagent model makes it easy to add another worker. It does not make it easy to add another writer, and those are not the same operation.
Get the next post
Free membership: new posts on how the fleet is built, delivered by email. Subscribe free
№ 4556