Many Agents, One Architecture: What Happens When Two of Them Change the Same System
Three agents, three pull requests, three reasonable opinions about where the retry logic belongs.
One puts the retry in the HTTP client. One wraps the handler. One adds a queue and drains it. Read any of the three on its own and you would approve it. Read them in the same afternoon and you notice the system now retries in three places, with three different backoff policies, and nobody decided that.
This is the shape of the problem once more than one agent works on a codebase at the same time. Each agent is locally correct. The incoherence is global, and it only becomes visible to whoever reviews last.
Why the rules file doesn't arbitrate this
The standard answer is a rules file: CLAUDE.md, AGENTS.md, .cursor/rules. We have written about why those go stale, and staleness is the smaller problem here. The bigger one is that a rules file cannot arbitrate.
It is prose. Two agents handed the same paragraph will produce two different readings of it, both defensible, and there is no point at which those readings meet. It lives per repository, so a rule about a service boundary sits in one repo while the service on the other side of the boundary is in another. And it has no state: it cannot know that another agent proposed something forty minutes ago, because it is a file, and files do not know things.
What you need for arbitration is not better prose. It is a shared thing that both agents read and write, that can hold a decision, and that can notice a disagreement.
What a model gives you that a document doesn't
An architecture model is elements and relationships you can query. Systems, containers, components, the edges between them, and attached to those edges the things that make a design a design: the decision that made a boundary deliberate, the owner to notify, the contract a consumer relies on.
Three things follow, and each one is a mechanism rather than an intention.
Every agent can read the same bytes. The generate-context action writes an archyl.txt from the model, in markdown by default, optionally auto-committed to the repository. Nine agents reading one generated file is a different situation from nine agents each paraphrasing a prose document. It is not clever. It is just shared.
Disagreement can be caught on the way in. The conformance-check action runs architecture rules against the files a pull request changed, annotates violations inline, and fails the check at whatever severity you choose. fail-on takes error, warning or none. If "retries belong in the client" is a rule rather than a sentence, the two agents who put it elsewhere find out in CI instead of in review.
A decision has somewhere to live. ADRs attach to the C4 elements they constrain. The reason the queue exists is on the queue, not in a Slack thread from March that no agent has ever seen.
The part we got wrong
Here is where this stopped being a blog post about a nice idea.
Agents don't change the model directly. They open a Change Request: a proposal, reviewed and merged by a person. When a request is created, archyl records the model version it was built against. When it merges, the version increments. That is the machinery you would want for exactly this problem.
We had never connected the two.
The base version was written on creation and read back nowhere. Which meant this sequence worked, quietly and completely:
- Agent A and agent B both read the model. Both see version 7.
- A opens a request. B opens a request. Both are based on version 7.
- A's request merges. The model is now version 8.
- B's request merges. It was written against a model that no longer exists.
No warning, no conflict, no note in the history. The second set of changes lands on top of the first, and if they contradict each other, the contradiction is now the documented architecture. This is a merge with the conflict detection removed, and it is the precise failure the whole "many agents" story is supposed to prevent.
So we fixed it. Merging a request whose base version no longer matches the project now fails with a 409 Conflict and a message naming both versions:
architecture request is based on version 7 but the model is now at version 9;
rebase the request and merge again
The check that makes it safe is not the comparison, though. Two merges arriving at the same instant would both pass a comparison and both proceed. What closes that gap is making the version increment itself conditional: the merge advances the model only if the model is still on the version the request was built against. If it has already moved, the merge finds nothing to advance, the whole thing rolls back, and not one change is applied. The comparison beforehand exists only so the error message can tell you how far behind you are.
409 rather than 400 matters more than it looks. An agent retrying on 400 loops forever, because a malformed request stays malformed. 409 says the opposite: what you sent was fine and stopped being applicable. Fetch the current model and try again.
What this still doesn't do
Four limits, all of which you can check.
No agent merges anything. There is no MCP tool that merges a Change Request. Agents propose; a person reviews and merges. That is a deliberate boundary and we are not planning to remove it, but it means the loop is not fully automatic and you should not design as though it were.
Conflict detection is coarse. The version is per project, not per element. Two agents touching genuinely unrelated corners of the same project will still collide on the version. That is the safe direction to be wrong in, and it is wrong.
Context retrieval is lexical. find_relevant_context scores elements by word overlap on names, descriptions, tags and paths. There is no embedding and no synonym expansion, so a task about "checkout" will not surface a component called OrderProcessor. The upside is real (deterministic, no token cost, no code sent anywhere), but it is matching, not understanding.
Rules don't write themselves. Everything above assumes somebody expressed "retries belong in the client" as a conformance rule. An empty rule set catches nothing, however many agents are running.
What to do about it this week
You do not need to buy anything to find out where you stand.
Pick the last week your team merged more than one agent-authored pull request. Read them together rather than in sequence. Ask whether any two of them made the same decision differently, then ask what, in your current setup, would have told you.
If the answer is "the reviewer noticed", that works until the day the reviewer is reading nine of them.
Change Requests, conformance rules and the C4 model are part of archyl. The GitHub Actions and the agent skills are open source. Related reading: why your agents have a rules file and not a model, how Change Requests work, and how the model is kept honest.