One writer per working tree
Parallel agents that share a checkout don't crash loudly, they overwrite each other and lose work silently. The cheapest rule in our build kills the most expensive failure: a writer that gets its own isolated tree.
Apollo Space Research
Apollo Space
Two agents start work in the same folder at the same time. One is halfway through a clean refactor. The other, told to “get out of the way” of a stuck branch, runs a single innocent command to reset the directory. The refactor, hours of good, finished, untested-but-real work, is gone. No error. No crash. No stack trace. The build is still green, because the green build is for the file that survived. The other file simply never existed as far as the machine is concerned.
Nobody did anything wrong. That’s the trap.
Here is the rule that closes it, and it fits on one line: one writer per working tree. The whole post is an argument for why that sentence is the cheapest insurance you will ever buy in a parallel-agent build, and why the failure it prevents is the most expensive kind there is, precisely because it makes no sound.
The failure that doesn’t announce itself
Most build failures are loud. A test goes red. A type doesn’t check. The compiler points at a line and tells you what it hates. You can argue with a loud failure, because it’s standing in front of you.
The dangerous failures are the quiet ones. A quiet failure is work that disappears without leaving a mark, and the most reliable way to manufacture one is to let two writers share a single checkout of the code.
Picture the naive setup, because it’s the one everyone reaches for first. You have a fleet of agents and a repository. You want them to work in parallel, so you point them all at the same folder and let them go. It feels efficient. One copy of the code, several hands moving fast. For an afternoon it even works.
Then two of those hands reach for the same spot. Agent A is editing a file. Agent B, working a different task, decides the directory is in a messy state and tidies it, a reset, a stash, a discard of “uncommitted junk.” From B’s point of view the junk wasn’t its work, so dropping it is housekeeping. From A’s point of view, the floor just vanished. A’s edits were uncommitted, which to a shared checkout means deletable. They’re deleted. A keeps going, none the wiser, and rewrites half of what it lost, or doesn’t, and the change ships missing a piece nobody can name.
The cost isn’t the lost hour. The cost is that you can’t see the hour was lost. A red test tells you something broke. Silent overwrite tells you nothing. You find out weeks later, when the feature that “shipped” is missing the part that lived only in the tree that got wiped.
Why the obvious fixes don’t fix it
The first instinct, once you’ve been bitten, is to coordinate. Make the agents take turns. Add a lock. Tell them politely not to touch each other’s files. This is the naive fix, and it fails for a reason worth naming.
Coordination assumes the agents can see each other. They can’t, not reliably. An agent working in a shared folder has no clean way to know which uncommitted changes are its changes and which belong to a sibling that started ten minutes ago. The working directory doesn’t carry a name tag on each edit. So when one agent decides to clean up, it isn’t being reckless, it genuinely cannot distinguish its own draft from someone else’s. The “be careful” instruction has nothing to attach to.
The second instinct is to commit constantly, so nothing is ever uncommitted long enough to lose. This is closer to right, and committing early is genuinely good hygiene, a committed, pushed branch is hard to destroy. But it doesn’t solve the collision. Two agents committing into the same checkout on the same branch now race to write the same history. One rebases on top of the other and the merge gets ugly, or worse, gets resolved automatically in a way that drops a hunk. You’ve moved the silent loss from the working directory into the commit graph. The bottleneck never disappears. It just moves.
The third instinct is the worst, because it looks the most responsible: have a supervisor agent serialize the writers so only one ever touches the folder at a time. Now you’ve thrown away the parallelism that was the entire point. You’ve built a careful, correct, single-file pipeline and called it a fleet.
None of these work because they’re all trying to make sharing safe. Sharing the working directory is the problem. You don’t make it safe. You stop doing it.
The mechanism: one tree, one writer, one branch
The key idea is simple, and modern version control was built for it. A repository can have more than one working tree. The history, the commits, the branches, the object store, lives in one shared place. But the checked-out files can exist in several separate directories at once, each pinned to its own branch. They share the past and isolate the present.
Give each agent its own tree and the collision becomes structurally impossible. Not “discouraged.” Not “guarded against.” Impossible. Agent A edits files in its directory; agent B edits files in a completely different directory. Neither can clean up, reset, or discard the other’s work, because the other’s work isn’t there to touch. When A is done, it commits to its own branch and pushes. When B is done, the same. The histories meet later, deliberately, at a merge, which is a loud, reviewable, conflict-surfacing event, exactly the kind of failure you want, because you can see it.
This is the inversion. The naive setup makes integration cheap (everyone’s already in the same folder) and isolation expensive (you have to coordinate to stay out of each other’s way). One-writer-per-tree flips it: isolation is free, it’s the default, baked into where the files live, and integration is the deliberate, visible step you do on purpose, at the merge, with a reviewer watching.
Coordination is a tax on every keystroke. Isolation is a one-time setup cost. Pay the cheap one.
There’s a second rule that rides along with the first, and it’s just as load-bearing: never switch, reset, or discard inside a tree you don’t own. The single most destructive habit in a shared checkout is the “get out of the way” reflex, wiping the directory to start clean. In an isolated-tree world that reflex is fine, because the only work you can wipe is your own. The discipline isn’t “be careful with shared state.” It’s “have no shared state to be careful with.”
What it costs, honestly
This isn’t free, and pretending it is would be the same self-grading mistake we warn about everywhere else.
It costs disk and setup. Each tree is another checked-out copy of the working files, and spinning one up takes a moment before the agent can start. For a fleet of writers, that’s real overhead, a handful of full checkouts living side by side instead of one. You also need a place to register them: a simple ledger of which tree belongs to which agent, claimed when, on which branch, so nothing goes orphaned and forgotten. A tree nobody remembers creating is its own small graveyard.
So weigh it. On one side: the cost of N checkouts and a registry that lists them. On the other: the cost of one silently overwritten change that ships missing a piece, discovered three weeks later by a customer, traced back through a history that has no record of the deletion because the deletion left none. One of these costs is a few gigabytes and a setup script. The other is a debugging session that starts with the words “but the code was definitely there.”
We pay the disk on purpose, for the same reason the council pays for an adversarial reviewer and the brake pays for a confirmation step. The expensive failure in a build was never the writing. It was the work that vanished without a trace and took a week of someone’s life to notice. Isolation that costs a few gigabytes is the cheapest place to prevent it.
The discipline scales down, too
One more thing the rule buys, and it’s the part people miss because it sounds too small to matter.
The same discipline that lets a fleet of agents run in parallel without eating each other’s work is the discipline that lets one agent recover from its own crash. An agent working in its own committed, pushed branch can die mid-task and lose almost nothing, the work up to its last commit is immortal, sitting in shared history, waiting to be picked up. An agent working uncommitted in a shared folder loses everything the moment the process dies, and worse, leaves a half-finished mess that the next agent might “clean up.” Isolation plus commit-early isn’t two habits. It’s one habit with two payoffs: parallel writers don’t collide, and a single writer survives its own failure.
That’s why this is the first rule we teach a new agent, before anything about how to write good code. You can be the best writer in the fleet and still be a liability if you share a checkout, because the work you lose isn’t only yours.
The turn: a graveyard is made of small, reasonable decisions
Strip away the version control and what’s left is an old truth about teams of any kind, human or not.
Work doesn’t usually get destroyed by a villain. It gets destroyed by a series of small, reasonable decisions, each one defensible in isolation. I’ll just clean up this messy directory. I’ll reset to start fresh. I’ll work in the same folder, it’s faster. Every one of those is sensible on its own. Stacked together, across a fleet moving fast, they quietly add up to a graveyard of overwritten branches and lost afternoons, the single largest source of vanished work in a parallel build, and the one that leaves no evidence behind.
The fix isn’t heroics or more careful agents. It’s a structure where the destructive move is simply unavailable. You can’t overwrite a sibling’s work if the sibling’s work isn’t in your directory. You can’t lose a crash’s progress if the progress was committed and pushed a minute ago. The rule does the remembering so no agent has to.
That’s the quiet philosophy under a loud-sounding word like orchestration: most of the value isn’t in making agents smarter or faster. It’s in arranging them so that the cheapest possible discipline makes the most expensive possible failure impossible, not less likely, impossible. One writer per tree is one such arrangement. There are others. They all share the shape: prevent the silent loss at the structure level, because by the time you’d catch it any other way, it’s already gone.
This is one of the small, unglamorous rules we build Apollo on, the kind that never makes a demo but quietly decides whether a fleet of agents is a team or a pile-up. If you’ve ever gone looking for a change you were sure you made and found nothing there, you already understand why the first thing we give a new agent isn’t a better prompt. It’s a room of its own.
Apollo runs your company's repetitive ops so your team doesn't.
Join the waitlist for early access, founding-user pricing, and a front-row seat as we ship.
Join the waitlistThe hidden tax of parallel agents is a migration diamond
Six agents writing to one schema conflict in the database, not the code, and CI dies at "multiple heads."
EngineeringAn orchestrator that can't survive its own crash isn't one
A crash that erases the orchestrator's reasoning loses the one thing you can't rebuild.
EngineeringPut a deterministic gate in front of your smartest reviewer
The cheapest defect-catch is a dumb script that checks two merged branches still boot before any judgment.