I run seven agents over the same domain. They have never once sent each other a message.
That was not the plan. The plan was the thing everybody builds first: a coordinator that hands work between specialists, agents that call each other, a shared conversation they all append to. It worked in the demo and it fell apart the moment the work got real.
What replaced it is boring and it has held up: every agent writes claims to one shared record, and nothing else. No agent reads another agent's reasoning. No agent can call another agent. The record is the only channel.
Here is why, and what it cost.
What breaks in the group-chat design
Three things, roughly in the order they hurt.
Context grows without bound. If agents converse, every agent needs everyone else's output in its window to participate. Six specialists means each one is reading five other monologues. Your token spend goes quadratic in the number of agents and the marginal agent makes the others measurably worse.
Errors laminate. Agent B reads agent A's output as input. If A was confidently wrong, B does not treat it as a claim to be weighed — it treats it as context, which is to say, as true. By the time it reaches F you have a well-reasoned conclusion resting on a hallucinated premise, and nothing in the transcript flags where the floor gave way.
You cannot answer "why." Six weeks later someone asks why the system concluded X. The honest answer is "there was a conversation." That is not an answer you can act on, and it is not an answer that survives an auditor.
Agents as authors, not as callers
The reframe that fixed it: an agent is not a function other agents invoke. An agent is an author with a domain of authority.
Each of mine owns a slice of the problem and may only make claims inside it:
| Agent | Domain | Claims it may make |
|---|---|---|
| Verification | What is true about the thing today | Observed facts, source records, reconciled geometry |
| Design | What it should become | Plan gaps, code compliance, takeoffs |
| Recovery | What can be salvaged | Bill of materials, tonnage, routing |
| Capital | How it gets funded | Financing lanes, underwriting inputs |
| Execution | How it gets built | Sequence, milestones, per-phase pricing |
| Market | What the outside world says | Comparables, pricing signals |
Notice the columns are not capabilities. Everyone can read a document and call a model. They are jurisdictions. That distinction is the whole design.
An agent's output is a row:
{
field: "roof-form",
value: "gable",
author: "verification",
evidence: "MEASURED",
code: "DES:roof-form"
}
It goes into the shared record. It does not go to another agent.
Disagreement is a data problem, not a conversation
When two agents disagree — and they do, constantly — nobody argues. The record resolves it, with rules you can read:
- Authority is scoped per domain, not per agent. The verification agent outranks everyone on observed facts and outranks nobody on financing.
- Inside a domain, evidence grade decides:
MEASURED > STATED > RECORD > MODELED. - A standoff is gated on evidence grade, not rank. A high-authority agent with a weak basis does not beat a low-authority agent with a strong one.
- Genuine standoffs resolve to
conflictand get surfaced. They are not averaged, and they are not silently decided.
I wrote up that reconciliation model in more detail in a companion post on the claims ledger — the short version is that losing claims are demoted, never deleted, so the disagreement stays inspectable.
The practical effect: adding a seventh agent costs one more author writing rows. It does not cost every other agent a longer context window. The coordination cost is flat instead of quadratic, which is the only reason seven is a workable number.
Freeze the agent definitions
One thing I did not expect to need.
Once agents are authors and their claims carry authority, an agent's identity is a privilege. If something can emit a row that says author: "verification", it inherits the verification agent's authority over observed facts. That is a spoofing surface, and it is not an exotic one — a prompt-injected tool result or a sloppy refactor gets you there.
So the definitions are frozen at their definition site and carry an origin fingerprint. A card cannot silently claim to be a mind it isn't. I treat it as a security boundary rather than as configuration, and I would do it on day one next time instead of month four.
The honest costs
You lose emergent behavior. Agents that converse sometimes surprise you productively. Mine never will. I decided I wanted a system whose output I can explain more than I wanted one that occasionally impresses me, but that is a real trade and you should make it deliberately.
Someone has to write the jurisdiction table. The domain map is design work a human does, up front, with actual knowledge of the problem. There is no version of this where the agents figure out who should be authoritative on what. If you don't understand your domain well enough to carve it, this architecture will tell you so immediately — which I would argue is a feature.
Reads get more expensive. Resolving a view over competing claims is more work than selecting a row, so anything hot needs a materialized projection and now you own a cache invalidation problem.
Where this runs
This is the agent layer inside ML Systems, a construction technology company I run in Rhode Island. Seven agents — plus a human reviewer who sits among them rather than above them, with the same claim-and-stamp mechanics everyone else has — read and write one record per home. It is shipped, in the app on both app stores.
They also have small animal familiars, which is not load-bearing but does make the system much easier to talk about with people who do not write software.
To be straight about what is and isn't proven: the agent layer and the record are working. The construction loop they feed is modeled, not measured. Every claim in our public repo is labeled MEASURED, MODELED or ASPIRATIONAL for that reason.
The design docs are open, including the ontology that governs how the claims compose: github.com/MLSystemsRI/ml-systems-public
The system these agents actually run is ML Systems — precision house deconstruction and circular construction in Rhode Island. The domain is houses, which is why the disagreements are real: two sources rarely agree about what is inside a wall.
If you are running a multi-agent system in production and you kept the message passing — I would like to know what made it work, because I could not make it hold.
Top comments (5)
"Errors laminate" is the cleanest name I've seen for this failure, and it matches what we saw exactly: once agent B ingests agent A's output as context rather than as a claim to be weighed, a confident hallucination becomes load-bearing and nothing downstream flags where the floor gave way. Moving to a shared record where agents are authors, not callers, fixed the same class of bug for us — and the quadratic context blowup you mention is the other half of why group-chat designs don't survive contact with real work. The distinction between jurisdictions and capabilities is the part I'd underline for anyone reading: everyone can read a doc and call a model, so scoping by capability buys you nothing; scoping by authority is what makes the audit trail answerable six weeks later. The question I'm still chewing on: what happens when two authors write conflicting claims into overlapping territory — say Verification and Recovery disagree on the same field? Do you resolve by jurisdiction precedence, by a reconciliation pass, or do you let both rows stand with provenance and push the conflict to whoever reads next? That resolution policy feels like where the real design lives.
The freeze guards the wrong field. Authority is scoped per domain, but standoffs are decided on evidence grade and explicitly not on rank, so the cheapest way to win a row is not to claim
author: "verification". It is to be the design agent you already are and writeevidence: "MEASURED"on something you modeled. That path needs no identity spoofing at all, and by your own rule it beats the verification agent holdingMODELED.The asymmetry that makes it worse:
authoris a property of the definition, so freezing it at the definition site actually works, whileevidenceis a judgment made per row at write time and there is nothing there to freeze. It would have to be attested by whatever produced the observation, which pushes the grade toward being derived from the source record rather than asserted in the same row the agent writes.The evidence grade over rank rule is the part most multi agent setups skip, and it is the one that actually matters once the work gets real. I have watched pipelines treat a confidently wrong claim as context for every later step, so the final answer looks coherent while the premise was already gone. Freezing author identity as a security boundary instead of loose config is also the detail I wish more designs put in on day one. Curious how often genuine conflict rows surface in practice versus how often one agent's MEASURED claim just quietly wins.
The channel change alone won't save you from lamination, the record's shape is what does. If your shared record is just prose entries appended over time, a downstream agent re-absorbs that prose as context exactly like a message, and six weeks later the audit shows only the surviving state, never the claim that lost.
We hit this building ours. The fix was making entries append-only and typed: author, grade, timestamp, stable claim id. When a claim gets superseded, the original stays visible with a pointer to what replaced it. Nothing gets overwritten or deleted, so the floor that gave way is always findable.
The rule that saved us was that superseded work gets its status flipped and a pointer added, then the file gets moved to an archive rather than tombstoned in place. The losing claim is never erased, just relocated. That distinction mattered more than anything else we tried.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.