A request lands that touches two specialists. The billing agent looks at it and says this is a policy question, routes it to the legal agent. The legal agent looks at the same request and says this is a billing question, routes it back. Both messages are reasonable. Neither one is wrong. And there is no third party in the system whose job it is to notice that the request has now gone in a circle.
If you’ve wired up more than one specialist agent and let them address each other directly, some version of that has probably already happened to you - a request that bounces, a specialist pulled in “just in case” who adds a third voice to a question that had two, a run you can’t point to the exact turn where anyone decided who owned it. Nothing crashed. Nothing errored. The system just never produced an owner.
That’s what a flat agent swarm looks like once it leaves the demo. In the demo it looks like emergent intelligence: independent specialists, no central bottleneck, nobody waiting on a manager. In production the emergence you get is emergent indecision, and the fix is not “make the agents better at agreeing.” It’s routing every request through one node whose only job is to decide who owns it. This post is the arithmetic for why, and the arithmetic is exact enough to check with a pencil.
Check whether you already have this
Section titled “Check whether you already have this”Open your multi-agent setup - subagent definitions, a crew file, a group-chat roster, whatever declares your specialist roles - and count two things: how many distinct specialist agents exist, and whether any two of them can message each other directly without going through a lead agent first.
Three specialists or fewer, and no direct channel between any pair of them: close the tab. You don’t have this problem yet, and adding a hub today wouldn’t save you anything - the math below shows exactly why, and it isn’t close.
Four or more specialists, or any pair that can already talk without a lead in the loop: keep reading. The section below isn’t a hypothetical. It’s your system, with the headcount plugged in.
Why the demo never shows you this
Section titled “Why the demo never shows you this”Here’s the tension the rest of the post turns on. Letting every agent talk to every other agent is the structure that looks flattest and fastest. It’s also the structure whose cost grows the fastest, and the two facts are connected: the same freedom that makes a swarm look emergent is what makes its channel count explode.
Two shapes, and every multi-agent setup is one of them. A full mesh connects every specialist to every other specialist directly - that’s the group chat, the swarm, the peer setup. A hub-and-spoke connects every specialist to exactly one central node and nowhere else - that’s the hierarchy this post is arguing for.
Start with the smallest real case: three specialists - a refund agent, a legal agent, a discount agent. Let every pair talk directly (a full mesh) and you get three channels: refund-legal, refund-discount, legal-discount. Route the same three through one hub instead, and you also get three channels: each specialist to the hub, and nothing else.
Three and three. At three specialists, a full mesh and a hub need exactly the same number of channels. Nothing about that is surprising once you’ve counted it, and it’s why a three-agent demo can’t show you the problem. At that size there’s no problem to show.
Now grow the same team to ten specialist roles - refunds, legal, discounts, shipping, payments, fraud, subscriptions, and so on, the roster any support product accumulates within a year. Full mesh: every pair gets a channel, which is forty-five channels. Hub-and-spoke: every specialist still gets exactly one, which is ten.
Grow the team from three specialists to ten - a little more than tripling the headcount - and the mesh doesn’t grow by even that much. It grows fifteen-fold, from three channels to forty-five. The hub grows from three to ten, a little more than tripling, the same as the headcount. By ten specialists, the mesh is carrying 4.5 times the hub’s channel count, for the same team doing the same work.
That 4.5x is the number this post owes you, and it’s re-derived from nothing but counting, below.
The freedom that makes a swarm look flat is the same freedom that makes its channel count quadratic. You can’t have one without the other.
The toy: draw four specialists and count
Section titled “The toy: draw four specialists and count”Take the smallest team where the mesh has already pulled ahead: four specialists. Call them refund, legal, discount, shipping - one more than the tied demo above, added because the team started covering shipping disputes too.
Draw four dots. Connect every pair with a full mesh, and list what you drew:
refund - legalrefund - discountrefund - shippinglegal - discountlegal - shippingdiscount - shippingSix lines. Count them yourself - there’s no shortcut needed at this size, just six pairs from four names.
Now draw the hub instead: one center, four spokes, one line from each specialist to the center and no lines between specialists.
┌──────┐ refund legal \ / \ / ┌──────┐ │ hub │ └──────┘ / \ / \ discount shippingFour lines.
Six mesh channels against four hub channels, at only four specialists. That’s a ratio of 1.5x. Remember 1.5 - it only grows from here, and it grows in a way you can predict exactly.
The pairwise tax
Section titled “The pairwise tax”Here’s the rule the toy just demonstrated. A full mesh of N specialists needs one channel per pair, which is N × (N − 1) ÷ 2 - the same count as “how many handshakes happen in a room of N people,” because it’s the identical problem. A hub needs one channel per specialist, which is just N.
Divide one by the other and the specialist count itself cancels out of the interesting part: mesh channels ÷ hub channels equals (N − 1) ÷ 2. Call that ratio the pairwise tax - what a mesh costs you per specialist, on top of what a hub costs, purely for letting every pair talk.
At four specialists, the tax is (4 − 1) ÷ 2 = 1.5. That’s the number the toy just drew. At ten specialists, the tax is (10 − 1) ÷ 2 = 4.5 - the exact number from the spoiler above, arrived at the same way, with no new arithmetic invented to get there.
Be exact about what that ratio counts, because it’s easy to read it as a bill. A channel is not a message and it’s not a dollar. Ten specialists who never address each other cost the same as ten who do, and you only pay for a channel on the runs where a request actually uses one. What the count measures is surface: every channel is a route a request can take that nobody planned, and a place a loop can close. The reason the surface matters is that in a mesh you can’t say in advance which routes a request will take. In a hub you can, because there’s only one.
The tax has no ceiling. It isn’t a fixed penalty you pay once for choosing a mesh; it’s a multiplier that climbs with every specialist you add, forever, because every new specialist has to open a channel to every specialist already there. A hub’s cost per new specialist is one more spoke. A mesh’s cost per new specialist is one more spoke to every existing specialist - the marginal cost of the n-th agent is n − 1 new channels, not one.
A hub adds one channel per specialist. A mesh adds one channel per specialist, per specialist already there.
The table, and why row 3 is the trap
Section titled “The table, and why row 3 is the trap”| Specialists | Mesh channels | Hub channels | Pairwise tax |
|---|---|---|---|
| 2 | 1 | 2 | 0.5x |
| 3 | 3 | 3 | 1.0x |
| 4 | 6 | 4 | 1.5x |
| 5 | 10 | 5 | 2.0x |
| 6 | 15 | 6 | 2.5x |
| 10 | 45 | 10 | 4.5x |
| 20 | 190 | 20 | 9.5x |
Keep this table. Every section below is a row of it.
Row 2 is the one nobody mentions. Below three specialists, the hub costs more channels than the mesh does - two spokes against one direct line. If your whole system is two agents, wiring a hub between them is pure overhead. That row is true, and it isn’t the one that matters.
Row 3 is the trap. Mesh and hub tie. A three-specialist proof of concept - the size most demos ship at - genuinely shows zero difference between the two designs, because at that exact size there is none. Anyone who built their intuition about multi-agent systems from a three-agent demo built it on the one team size where hierarchy has no visible payoff yet. That’s not a coincidence to be suspicious of; it’s the same formula producing a tie at exactly the point most people stop testing.
Row 4 is where it turns, and it never turns back. One more specialist than the tied demo, and the mesh is already 1.5x the hub. There is no size above four where the mesh catches back up - the tax only grows.
Row 20 is where “add one more specialist” stops being a small decision. At twenty specialists a mesh needs 190 channels to a hub’s 20. The twenty-first specialist would add 20 new mesh channels by itself - one to each existing agent - against one new spoke for the hub.
Every row after 3 says the same thing louder: the tie was the exception, and it only happens once.
Build the hub, not just count its channels
Section titled “Build the hub, not just count its channels”The counting says why hierarchy wins. Building it is a smaller step than it looks, because the pieces already exist as separate primitives on this site: a subagent for each specialist, a rules file for the handoff contract, and plan mode for the routing decision.
The hub itself needs a name. Call it the orchestrator: the one specialist whose job is reading the request, picking who handles it, and owning the outcome. Every other specialist reports to it and to nothing else.
One router, specialists with no sideways door
Section titled “One router, specialists with no sideways door” ┌─────────────┐ user ───────▶ │ orchestrator│ ◀─────── only this node talks to the user └─────┬───────┘ ┌────────────┼────────────┐ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌──────────┐ │ refund │ │ legal │ │ discount │ specialists never talk │ agent │ │ agent │ │ agent │ to each other └─────────┘ └─────────┘ └──────────┘Declare each specialist as a subagent with a tight description and a restricted toolset. Here’s the refund specialist as a Claude Code subagent definition - the shape carries over to Codex or opencode, only the file location changes:
---name: refund-specialistdescription: Handles refund eligibility, amounts, and processing. Does NOT decide policy exceptions or apply promotional discounts.tools: Read, get_order, issue_refund---
You process refunds. You receive a request from the orchestrator with thefull customer context already attached. Decide the refund outcome and returnit. You do not contact other specialists. If the request requires a policyexception you are not authorized to make, return `ESCALATE: <reason>` to theorchestrator.Two things do the real work here, and only one of them is the prose. The description is the routing signal the orchestrator reads to pick this specialist. The tools line is what actually closes the sideways door: a plain subagent already returns exactly once, to whoever spawned it, and has no built-in way to address a peer - that’s the primitive’s own shape, not a rule someone has to remember to follow. What the instruction adds is scope: the specialist knows it should resolve or escalate, and nothing else.
The specialist isn’t well-behaved. It’s boxed in - the door to its peers was never installed.
The handoff contract goes in the rules file, not in anyone’s memory
Section titled “The handoff contract goes in the rules file, not in anyone’s memory”The reason a mesh loops is that “hand this off” is undefined - every agent invents its own idea of when to pass and what to include, so context drops and nobody owns the result. Write the contract down once, in the rules file every agent reads on every session:
## Multi-agent handoff contract
- All requests enter through the `orchestrator`. Specialists are invoked ONLY by the orchestrator, never by each other.- A specialist has exactly two terminal outputs: - `RESOLVE: <result>` - the task is done. - `ESCALATE: <reason>` - control returns to the orchestrator with a reason.- Every handoff carries full context: the original request, every prior specialist's output, and the customer record. No agent re-fetches what an earlier agent already has.- Turn cap: 6 specialist invocations per request. On the 6th with no RESOLVE, the orchestrator stops and applies the default.- Default on no resolution: escalate to a human queue with the full transcript attached. Never loop, never guess a refund amount.The turn cap is the one number in this contract that isn’t derived from the channel count - it’s a policy choice, the same way a timeout value is a choice. Six is just a round number small enough to bite. What matters structurally is that it exists at all: a mesh has no equivalent, because no single node in a mesh owns deciding when to stop. The hub has one node whose job includes stopping.
A mesh can loop forever because nobody in it is responsible for noticing. A hub can’t, because somebody always is.
The router decides before it spends a specialist call
Section titled “The router decides before it spends a specialist call”The orchestrator should pick who handles a request before it invokes anyone, not discover the right specialist by trial and error. Plan mode is built for exactly this: it makes an agent produce a plan you or a gate can inspect before any action runs.
---name: orchestratordescription: Front door for all support requests. Routes to specialists, enforces the handoff contract, owns the outcome.---
For every incoming request, FIRST produce a routing plan before invoking anyspecialist:
1. Classify the request (refund / policy / discount / mixed).2. Name the ONE specialist to handle it first, and why.3. State the expected terminal output and the default if it escalates.
Only after the plan is set do you invoke the named specialist. If aspecialist returns ESCALATE, you re-plan - you do not blind-forward toanother agent. Enforce the 6-invocation turn cap from the rules file.Faced with “customer wants a refund the policy might not allow,” the plan now reads: mixed request, legal decides the exception first, refund executes if approved, default is human escalation. One decision, made once, by the only node that sees the whole request. The specialists execute a sequence instead of negotiating one.
The mesh negotiates an order at runtime. The hub decides one before any specialist has spent a token.
This already has three names
Section titled “This already has three names”None of the pieces above are new primitives. The arithmetic just tells you which existing shape to reach for.
The substrate is the subagent you already have. Subagents return once, to their caller, by default - across every tool this site covers, none of them ships peer-to-peer messaging as the default subagent behavior. Peer coordination is a separate, named primitive: Claude Code calls it agent teams and marks it experimental; other stacks reach it through their own multi-agent SDK layer. Choosing “specialists that only report to a hub” isn’t a workaround - it’s the primitive’s resting shape. Choosing a mesh means reaching past it for something else.
The calling convention is “agents as tools.” When the orchestrator invokes a specialist and gets a return value back, with the specialist never initiating contact on its own, that’s the same shape a function call has: caller invokes, callee returns, caller decides what happens next. Some frameworks describe this explicitly as treating each specialist as a callable tool of the orchestrator rather than as an independent peer. It’s worth knowing the phrase, because it’s the same hub-and-spoke shape wearing different words.
Frameworks are converging on naming both modes. Several multi-agent frameworks now document something they call a supervisor or hierarchical topology as a distinct option from their original free-for-all group chat. Exactly which framework ships which default, and how the two modes differ under the hood, changes often enough that it isn’t worth pinning to this post - check your framework’s own docs for a supervisor or hierarchical mode before assuming you have to hand-roll one. If it has one, this post is the arithmetic for why to pick it.
So doesn’t the hub just become the bottleneck the swarm was avoiding? Yes - and that’s the point, not a flaw. A bottleneck is a place where decisions serialize, and a serialized decision is the only kind you can cap, trace, and test. The orchestrator stays cheap because it doesn’t do the specialist work itself; it classifies, routes, and stops. What the mesh was avoiding was never overhead. It was a single place accountable for the outcome - which turns out to be the thing you wanted the whole time.
None of this is a new primitive. It’s the arithmetic telling you which of your existing primitives to wire together, and which one not to reach for.
When the mesh is the right call
Section titled “When the mesh is the right call”Hierarchy earns its cost when work has to converge: one request, one owner, one answer. It’s dead weight when work fans out and never has to agree. Spin up ten agents to summarize ten unrelated files and there’s no ownership question to settle - no handoff to drop, no order to negotiate, no channel where a request can get stuck arguing with itself. Parallel fan-out with a single join at the end doesn’t need a router in the middle; forcing all ten through a hub only adds a hop nobody needed.
The rule isn’t “always route through a hub.” It’s narrower: route through a hub the moment two agents could disagree about who owns the result.
Independent work doesn’t need a boss. Contested work does.
What you can test now that you couldn’t before
Section titled “What you can test now that you couldn’t before”A mesh has no testable surface for this failure. “Did the agents agree?” isn’t an assertion - there’s no defined path for a request to take, so there’s nothing to check it against.
The hub gives you three seams to pin:
- Routing is deterministic enough to assert. Feed the orchestrator a pure refund request and assert the plan names
refund-specialistfirst. Feed it a mixed request and assert it sequences legal before refund. - The turn cap is a guarantee, not a hope. Hand the system a deliberately unresolvable request and assert it stops at six invocations with a human escalation - not at some open-ended count with nobody watching.
- Handoffs are inspectable. Because context travels as a defined payload, you can assert the legal specialist received the customer record the refund specialist already fetched, instead of re-fetching it.
Cutting the paths from forty-five to ten is what makes the remaining ten worth writing a test against.
What hierarchy doesn’t fix
Section titled “What hierarchy doesn’t fix”A 4.5x cut in channel count at ten specialists is a real number, and it is not the whole story. The hub removes the channel-count problem specifically. It doesn’t remove every problem a mesh has, and it’s worth saying which ones survive.
The hub is a single point of failure for availability, not just for decisions. If the orchestrator’s process stalls or its own context gets corrupted, the whole system stops - every specialist is idle, waiting on a router that isn’t answering. A mesh degrades messier but doesn’t have one node whose failure halts everyone; a hub trades that gradual messiness for a hard stop at one place. Retries and a fallback path for the orchestrator itself are a separate piece of work this post doesn’t cover.
A hub with a bad routing prompt is not an improvement. Cutting the channel count doesn’t cut the need for the orchestrator’s classification step to actually be right. A hub that misroutes confidently is a mesh’s confusion delivered faster and by one voice instead of three - the arithmetic caps how many places a bad decision can travel, it doesn’t cap how bad the decision can be.
Fewer channels is not the same claim as fewer mistakes. This post only argued the first one.
The line worth keeping
Section titled “The line worth keeping”A three-agent demo can’t show you this, because at three agents there’s nothing to show - mesh and hub cost the same. Add a fourth specialist and the tie breaks for good: 1.5x at four, 2.5x at six, 4.5x at ten, and no size above three where the mesh catches back up. Route every request through one node that decides who owns it, and the count that was about to run away from you stays linear instead.
That leaves the hub’s own arithmetic as the next open question this post didn’t answer. Channel count on a hub grows linearly, which is the whole win - but the orchestrator’s own prompt, its routing rules, and its turn-cap logic all have to live somewhere, and that somewhere is one context window carrying more of the system’s judgment as the specialist roster grows. A hub that scales past the channel-count problem still has to answer what happens to that one window at fifty specialists instead of ten. This post counted the edges. It didn’t count what’s sitting on the node in the middle.
About the numbers. Every count in this post - mesh channels, hub channels, the pairwise tax, the master table - is combinatorics derived from one declared rule (mesh connects every pair, hub connects every node to one center) and re-checked against an independent script before publishing. None of it is a measurement: there’s no real transcript, no observed token count, and no dollar figure anywhere in this post, because none was needed or available to verify. The turn cap of six specialist invocations is a policy choice, not a derived number, stated once and used consistently. One thing the table doesn’t charge the hub for: the hub is an extra agent, so ten specialists behind a router is eleven agents against the mesh’s ten. That’s one node, and it doesn’t change the shape of either curve. Swap in your own specialist count and the shape doesn’t change: mesh grows as the square of the headcount, hub grows linearly, and the two are tied exactly at three.
For the per-tool mechanics, see Subagents for the orchestrator-and-specialist split, Rules for the handoff contract every agent reads, and Plan mode for the routing decision before any specialist call.


