← Writing

Multi-Agent Coding: Orchestration Patterns From Production

Multi-agent coding gets sold as a swarm: dozens of tireless engineers, a virtual company on a laptop, an org chart of AIs with job titles. I run agents in production every day — my companies' operations lean on them — and what I actually run looks nothing like a swarm. It looks like plumbing.

That's not a complaint. Plumbing is the interesting part. Once you've delegated real work to more than one agent, the hard questions stop being about the agents and start being about the seams between them — who hands off to whom, who checks whom, and what happens when a link in the chain degrades quietly. Those are orchestration questions, and the patterns that answer them are older than AI. We just get to rediscover them with new failure modes.

This post is the set of patterns that have survived contact with daily production use in my own systems. Not a framework tour, not a benchmark — the shapes I keep rebuilding because they keep earning it.

One agent is the default. Multi-agent has to earn it.

Start with the deflationary rule, because it saves the most money and the most debugging: if one agent with a well-written task can do the job, one agent should. A single agent holds the whole task in one context — intent, constraints, and half-decisions all live in the same place. The moment you split work across agents, that shared skull disappears, and everything the agents need to agree on has to be written down and passed explicitly.

That's expensive. So the question is never "how many agents can I use?" It's "what does a second agent buy me that a better prompt doesn't?" In my experience there are exactly three honest answers, and they map to the three patterns below:

  1. Independence. A checker that shares no context with the maker.
  2. Parallelism. Genuinely separable work that doesn't share state.
  3. Specialization over time. Stages with different jobs, different tools, different blast radii.

If your reason isn't one of those, you're adding coordination cost for vibes. What delegating to even one agent does to the day-to-day job is its own post; everything here assumes you've made that move already and are deciding whether to make the next one.

Pattern one: the pipeline

The most load-bearing multi-agent system I run is a content pipeline, and its shape is the oldest one in computing: stages. One agent drafts. A different agent reviews. A third ships what survived review, on its scheduled date. Each stage runs separately, has its own narrow permissions, and leaves a written record the next stage reads.

The design rule that makes pipelines work: each stage should be small enough to verify and dumb enough to restart. The drafter doesn't publish. The publisher doesn't edit. When a stage fails, you rerun that stage — not the world. If you've built CI/CD, none of this is news; the novelty is only that the stages now exercise judgment, which means each handoff needs more than an exit code. My stages hand off documents with their reasoning attached — what was done, what was skipped, and why — because the next stage (or me, auditing later) can't re-derive intent from a diff.

The mistake I made early was letting stages share too much. If the reviewer stage can see the drafter's reasoning, it starts reviewing the intent instead of the artifact — "I see what it was going for" is the beginning of a rubber stamp. Which brings up the pattern that matters most.

Pattern two: adversarial review

Here's the strongest claim in this post, and the one I'd defend hardest: an agent must not review its own work, and "another agent" only counts if it shares no authoring context.

An agent re-reading its own output confirms it. Not because models are vain — because the reviewer is reasoning from the same context that produced the mistake. Same session, same assumptions, same blind spot. You don't get a second opinion by asking the first opinion to look again.

So the review gate in my pipeline is built on independence, in descending order of preference:

  • A different model family entirely. Cross-model review is the real thing: different training, different failure modes, no shared context. When my gate can get a second model, it takes it.
  • A fresh agent with amnesia. Same model, but spawned clean: it gets the artifact and the rubric, and nothing else. No chat history, no knowledge of what the author was trying to do.
  • A later session. Time is a weak form of independence, but it's not nothing.

The reviewer's instructions matter as much as its independence: its job is to fail the work, not to summarize it. A rubric it tries to break the draft against, with a binary verdict at the end. A reviewer asked "any thoughts?" produces thoughts. A reviewer asked "find the reason this doesn't ship" produces the reason, or a meaningful pass.

One production lesson that took me a while to respect: check that your reviewer is actually alive. A gate that silently degrades — the second model is unreachable, the checker times out, and the pipeline shrugs and records a pass anyway — is worse than no gate, because the pass still gets written down and you trust it later. My gates now verify the reviewer is ready before the run, and log which reviewer actually ran. Presence is not readiness.

This is the successor to a bottleneck I've written about before: once generation is delegated, your judgment is what stops scaling. Adversarial review is what you build when even that runs out — it doesn't remove your judgment, it moves it up a level, from reading every diff to auditing the gate that reads them.

Pattern three: fan-out

Some work is the same operation across many independent targets. When I standardized eleven repositories in a day, the work had exactly this shape: one standard, eleven bounded targets, audit everything first, change nothing until approved. That day ran through a single agent working down the list. Fan-out is what the shape becomes when you parallelize it — one spec, many workers — and the reason I sequence it carefully is that the parallel version is only safe under one hard rule.

That rule: workers must not share a writable surface. Two agents editing the same file is not collaboration, it's a race condition with opinions. Partition the work along boundaries that already exist — one repo per worker, one module per worker, one file per worker — and give each worker its own isolated copy if there's any chance of overlap. Worktrees are cheap. Merge conflicts between agents are not, because neither side of the conflict can tell you what it meant.

The other half of fan-out is the merge: results come back as claims, and claims from N workers need the same skepticism as claims from one, times N. My rule is that fan-out output funnels into exactly the review pattern above before any of it lands. Parallelism multiplies throughput; it multiplies unreviewed mistakes at the same rate.

Pattern four: the scheduler is the orchestrator

The multi-agent system nobody talks about is the one where the agents never meet: a roster of scheduled jobs, each a single agent with one job, running on a clock. That roster is my operations' back office — triage, briefings, syncs, and the content pipeline's stages all run this way. No message bus, no agent-to-agent chatter. The orchestrator is cron, and the shared memory is a git repository of plain files.

This sounds primitive next to agent-communication frameworks, and that's exactly why I recommend it. Files are inspectable, diffable, and survive restarts. When a job misbehaves, the entire conversation between agents is sitting in version control with timestamps. The context engineering post already covers how each job's context gets assembled before it wakes, and the rules unattended agents need precisely because nobody's watching — it deferred the orchestration story to its own piece, which is the one you're reading. What belongs here is the claim about the clock itself:

The failure mode to design against here is the seam. Two jobs that each cover a window of time will both miss the event that lands exactly on the boundary — and each will report a clean run, because each is telling the truth about its own window. Overlap the windows. Idempotent jobs plus overlapping coverage beats elegant non-overlapping schedules every time, because the seam failure is silent and the duplicate-handling failure is loud.

The escalation rule: know what reaches a human

Every pattern above ends somewhere, and in my systems the ending is explicit: anything an agent can't decide gets written to a decision queue a human actually reads, once, with the options attached — not re-asked daily, not buried in a log. The precise autonomy dial is a business decision, not an architecture one. But the mechanism is architecture: if your multi-agent system doesn't have a designed path for "I shouldn't decide this," it has an undesigned one, and you'll discover it in production.

What I'd build first

If you're starting from one agent and tempted by ten: build the two-agent version of the review pattern. A maker and an independent checker with a rubric. It's the smallest multi-agent system that produces something a single agent can't — a verdict that doesn't share assumptions with the work it judges — and every bigger pattern here is that idea wearing more infrastructure. Session habits for the single-agent loop are their own post; the pipeline, the fan-out, and the scheduler can all wait until volume forces them.

They will, eventually. Volume always wins. When it does, you'll be gluing together stages, gates, and clocks — and you'll find, a little deflatingly, that the state of the art in multi-agent coding is mostly the state of the art in distributed systems, 1979 edition, with better copywriting.

FAQ

Do I need a multi-agent framework?

I don't use one in production. Files, git, a scheduler, and a CLI agent cover the four patterns above with tools you already debug fluently. Frameworks earn their place when you need real-time agent-to-agent interaction — most coding work doesn't. Start with the boring substrate; adopt a framework when a specific pattern hurts without it.

How many agents should a task get?

One, until you can name which of the three justifications — independence, parallelism, or staged specialization — you're buying. Then the smallest number that buys it. My production answer is usually one agent per job, two where a gate matters, N only for fan-out across targets that don't share state.

How do agents share context without stepping on each other?

In my systems: through files, with ownership. Each surface has one writer; everyone else reads. State lives in version control so every handoff is auditable after the fact. Shared live context between concurrently running agents is the thing I avoid entirely — it reintroduces the race conditions the partitioning existed to prevent.

Is multi-agent coding the same as an "agent swarm"?

The swarm framing implies emergent coordination — many agents negotiating amongst themselves. Production multi-agent coding, at least as I practice it, is the opposite: coordination is explicit, written down, and boring on purpose. The value isn't in agents talking to each other. It's in agents that provably don't need to.