Skip to content

← Free Guides

How Twenty Agents Stay Out of Each Other's Way

August 11, 2026

Twenty agents working at once have one real failure mode, and it isn't bad code. It's that none of them know what the others just did.

Two agents fix the same bug in the same hour. A third rewrites a file a fourth is mid-way through. Somebody solves a problem that was already solved yesterday, and nobody finds out until the merge.

The fix is one shared file every agent reads and writes. Mine is called DEVSTATE. This is how to build one, and the six rules that keep it useful past the first week.

This assumes you already have something for the agents to work on — an operating system doing real business work, not agents working on agents. If you don't, build that first.

The one thing to hold onto

Every setup is different — your divisions, your agents, your tooling. What transfers is the shape.

The wall is a pointer, not a record. The moment it becomes the place where detail lives, it stops being read, and a channel nobody reads is worse than no channel because everyone believes their message arrived.

Hold onto that and the rest of this is mechanics.

What you need

A repo the agents share. Agents that can run a shell command. A hook system that can inject text at the start of a turn and intercept a tool call — Claude Code gives you both.

That's it. No service, no database, no vendor.

How it works

One markdown file at the root of the repo. Agents append to it through a small script rather than editing it directly. A start hook pastes the newest posts into every agent's context on every turn, so nobody has to remember to look.

mermaid
graph TD
  A[Agent finishes real work] --> P[Posts through the script]
  P --> L{Lock free?}
  L -- no --> W[Wait and retry]
  L -- yes --> G{Grammar valid?}
  G -- no --> R[Rejected, told the shape, tries again]
  G -- yes --> F[Appended to the wall]
  F --> T[Trimmed to the newest posts]
  T --> H[Start hook injects it into every session, every turn]
  H --> B[The next agent begins already knowing]

Six rules make it hold. Each one below is something that broke first.

1. One file, not one inbox each

The instinct is to give every agent its own message queue. Resist it.

A single shared file means an agent reading it sees what everyone did, including work it wasn't addressed on — which is exactly how the duplicate build gets caught. Per-agent inboxes give you privacy nobody asked for and a coordination problem you now have to solve twice.

Starter prompt:

create a single shared markdown file at the repo root called DEVSTATE.md. it is the one
coordination channel for every agent in this repo. give it a short header explaining the
posting rules and a "## Messages" section where posts go, newest first. before you build
anything, ask me how many agents will use it and whether they are grouped into divisions.

2. Injection beats remembering

An agent that has to decide to check the channel will not check the channel. Not out of laziness — it's mid-task, and reading a file it wasn't asked to read is a detour.

So don't ask. A session-start hook pastes the wall into context on every turn. The agent doesn't check it; it simply already knows. This is the single change that made mine work.

Starter prompt:

write a session start hook that reads the newest posts from DEVSTATE.md and injects them
into the session context, every turn, for every agent. it must be cheap and silent — no
model call, no network, just a file read. show me what a session sees on turn one.

3. Give it a grammar and enforce it

Free-form posts turn into a chat log in about four days.

Mine requires two things on every post: a type — SHIPPED, BLOCKED, ASSIGNED, GOTCHA, FACT, FYI — and a routing arrow saying who it's for. A post without them is rejected with a message explaining the shape, and the agent fixes it and posts again.

That rejection is doing more work than it looks. It's the difference between a rule that decays and a rule that holds, because it isn't a rule anybody has to remember.

Starter prompt:

add validation to the posting script: every post needs a TYPE from a fixed list and a
routing arrow naming the recipient. reject anything without both, and make the rejection
message explain the correct shape so the agent can retry without asking a human. show me
the rejection an agent sees when it gets it wrong.

4. Cap the length, then prune

Two limits, and both are load-bearing.

A hard character cap per post — mine is a few hundred — forces the writer to put the detail in a document and link it. And the file trims itself to the newest handful of posts on every write, because a channel that grows forever is a channel that gets skimmed and then skipped.

This is the pointer rule made mechanical. The post says what happened and where to look. It is not the place the thing is explained.

Starter prompt:

add two limits to the posting script. one: reject any post over N characters, with a
message telling the writer to put the detail in a doc and link it. two: after a successful
post, trim the file to the newest N posts. tell me what N should be for a team this size
and why, then let me pick.

5. Never write the wall from a snapshot

This is the rule I broke myself, and it's the one that silently destroys the channel.

An agent that read the file an hour ago, appended its line to that copy, and pushed has just deleted every post made in the meantime. The diff looks like one addition to the agent. To everyone else it's a mass deletion.

Two things fix it. Always re-read the file immediately before appending, never from memory. And put a check in the build that fails any change removing existing posts.

The only correct change to a shared channel is pure addition. If your diff shows a removed line, stop.

Starter prompt:

add a check that fails any proposed change to DEVSTATE.md which removes an existing post
line. additions only. also make the posting script re-read the file from the current state
immediately before appending, never from a copy held earlier in the session. explain how
it behaves when two agents post in the same second.

6. Put the writes through a lock

Two agents posting at the same moment will silently eat each other's messages. This isn't rare at twenty agents. It's a Tuesday.

One lock around the read-modify-write, held for the length of a file append — a few milliseconds — and the problem is gone permanently. It's the cheapest of these six and it prevents the most damaging failure, because a message that vanishes leaves no trace and everyone believes it arrived.

Starter prompt:

make the posting script take an exclusive lock before it reads and holds it until after it
writes, so two agents posting simultaneously cannot overwrite each other. if the lock is
busy, wait and retry rather than failing. prove it: run twenty posts concurrently and show
me that all twenty are in the file.

What pruning throws away, history keeps

The one worry people raise is losing things. You aren't.

The file lives in the repo, so every version of it is in the commit history. The wall holds the newest posts because that's what a working channel needs; everything older is one command away and nobody has to scroll past it every turn.

Short and current in front, complete and searchable behind. That's the whole archive strategy.

Start here

Don't build all six today. Build the file and the injection hook — rules one and two — and use it for a day with whatever agents you already have.

You'll discover the other four in the order I did, because each of them is something that breaks in a way you'll recognise the moment it happens: the chat log, the vanished message, the mass deletion, the post nobody could parse.

Then come back and add the guard for the one that just bit you.

One file. Injected, not remembered. Additions only.

Hit a wall? Book a working session and we'll get it running.