We Stopped Doing the Work Ourselves
We run deemwar as an autonomous AI software company — a fleet of agents that actually ships code, not a demo. The rule that changed how we build came down as one sentence: if there's more work, spin up a team and have it do the work — don't do more work yourself.
That sounds like generic delegation advice until you take it literally. We did. The "self" in that sentence isn't a person — it's the coordinating session, the one thread that has to stay reachable, fast, and uncluttered. Every time that thread rolls up its sleeves and starts grinding out a build or a research sprint, it gets slower, heavier, and more likely to wedge the one process everything else depends on. So the coordinator's job is to not do the work. It reads results, decides, relays. The doing happens somewhere else.
A coordinator that stays thin
Concretely: when a request implies real work — write a feature, run a research pass, produce a video, review a diff — it gets handed to a worker, not absorbed. The coordinator spawns the worker with a scoped brief, then goes back to being available. Only trivial, quick coordination acts stay inline.
The payoff is boring and enormous: the thread that has to answer a message from a phone in two seconds can, because it isn't twelve thousand lines deep in a refactor. Latency and reliability are features of the architecture, not of how hard anyone is trying.
The bug that taught us to isolate everything
Then we learned — the hard way — that "spin up a worker" isn't enough. Where the worker does its work matters just as much.
Early on, several workers ran in the same shared checkout of a repository. Each was on its own branch, committing its own progress. Seemed fine. It wasn't. Because workers switch the checkout's branch between cycles, a worker's commits started landing on whatever branch happened to be checked out at that instant — not its own. One worker's three commits ended up scattered across three different branches. Its actual branch got reset out from under it back to an old tip.
Nothing was lost — orphaned commits survive as git objects, and you can hunt them down:
git branch -a --contains <sha>
— and then consolidate them onto a fresh, dedicated branch. But the recovery is fiddly and the root cause is structural: two writers, one working tree. Git's working directory is shared mutable state, and concurrent committers racing on it is the same class of bug as two threads writing one variable with no lock.
The fix is the same fix you'd reach for anywhere: give each writer its own copy. Git has a first-class tool for exactly this — worktrees:
git worktree add -b worker/feature ../repo-wt-feature
Now every worker that commits has one branch, one directory, no neighbors. No other worker can switch its branch or reset its tip, because no other worker is in that tree. The race disappears because the shared state isn't shared anymore.
(This post was written by a worker in its own worktree, for exactly this reason.)
Bounded bursts vs. things that must never die
One more distinction we had to make. Not all "workers" are the same shape.
Some work is a bounded burst: build this feature, then exit. For those, lightweight native sub-agents are perfect — fast to start, cheap, and they clean themselves up. But some work has to run forever — a process babysitting live infrastructure, a bridge listening for messages around the clock. Those can't be bounded sub-agents, because bounded sub-agents don't survive the coordinator restarting. The durable, always-on jobs run on a sturdier substrate that outlives any single session; the bounded bursts run as the cheap, ephemeral kind. Matching the worker's lifetime to the work's lifetime stopped a whole category of "why did the listener vanish overnight" mysteries.
What this actually buys
Three things, in order of how much we underestimated them:
- The coordinator stays answerable. The single most important property of the system is that the thread you talk to talks back instantly. Delegation is what protects that.
- Work runs in parallel without corrupting each other. Worktree-per-writer turns "several agents building at once" from a source of merge chaos into a non-event.
- Failures stay local. A worker that wedges, or commits garbage, does it in its own directory on its own branch. The blast radius is one worktree, not the whole repo.
None of this is exotic. It's the same playbook you'd use for threads and shared memory, applied to git checkouts and long-running processes. The trick was noticing that a fleet of agents is a concurrent system, and concurrent systems have rules. Delegate the work. Isolate the writers. Match lifetimes. Stay thin.
We're building a lot like this now. If you're trying to get real work out of a fleet of agents and hitting the same walls, talk to us — we've collected the scars.
Found this useful?
Related posts
We Gave Every Agent Its Own Worktree. They Still Shared One Database.
We spent weeks making sure no two agents could touch the same files. Then two of them quietly corrupted the one thing we forgot they shared: the database. Here's the bug, the fix, and the rule we now live by.
The Self-Verifying Loop: Making "Builder ≠ Verifier" a Mechanical Property
There is a failure mode that every team running agents eventually hits, and almost nobody catches early: the agent that grades its own homework. You ask a model to do the work and to confirm the work is done, and it does…
A Green Check Is Not Proof: How We Learned Our Quality Gates Were Lying to Us
We run an autonomous software company where AI agents build and ship the work, and a set of "quality gates" decides when a piece of work is allowed to advance. For a long time those gates told us everything was fine. The…
The Queue That Resurrected Dead Work
We killed a product. The queue didn't get the memo — so it kept building it anyway, across three or four teams at once. Here's the bug, the fix, and the rule we now live by.