Running one AI agent well is a solved problem. Running five without them colliding, flooding your context, or confidently duplicating each other's work is where it gets interesting — and where most setups quietly fall over.
I run several repos in parallel most days. Here's what actually works, including the two mistakes that cost me the most.
What parallelises and what doesn't
The test is simple and it's about state, not size: can these tasks run without sharing mutable state or waiting on each other?
Genuinely parallel:
- Read-only fan-out. Five agents each searching a different way — by directory, by symbol, by convention, by git history. Each is blind to what the others find, which is the point: one search angle never finds everything.
- Per-item transforms. One agent per file in a migration, per post in an audit, per component in a refactor. No shared state, so no collisions.
- Independent perspectives on one artifact. Three reviewers with different lenses — correctness, security, does-it-reproduce — beats three identical reviewers, because diversity catches failure modes redundancy can't.
Not parallel, however much you want it to be: anything where step two needs step one's output, or where two agents write the same file. Parallelising a dependency chain doesn't make it faster, it makes it non-deterministic.
The barrier tax nobody accounts for
The most common structural mistake: fanning out, waiting for all results, then fanning out again. It reads as clean code and it wastes an enormous amount of wall-clock time.
# BAD — barrier between stages. everything waits for the slowest finder.
found = await all(finders) # slowest: 180s. fastest: 40s.
verified = await all(found.map(verify))
# fast finders sit idle 140s doing nothing
# GOOD — pipeline. each item verifies as soon as ITS finder returns.
await all(finders.map(f => find(f).then(verify)))
# total = slowest single chain, not sum of slowest-per-stage
A barrier is only correct when the next stage genuinely needs cross-item context: deduplicating across the full result set before expensive downstream work, or early-exiting when the total count is zero. "I need to flatten the array first" is not a reason — do that inside a stage.
Default to pipelining. Reach for a barrier deliberately, not out of habit.
Compress before you fan out
This is the single highest-value rule in multi-agent work, and it's about tokens.
Sub-agent output flows back into your main context. Five agents each returning a chatty 800-token narrative is 4,000 tokens of prose in your main window — which then rides along as input on every remaining turn of the session. Five agents returning 150-token structured findings is 750.
So: terse, structured returns. Better still, make the return type explicit — a schema rather than prose — so you get data you can filter instead of paragraphs you have to re-read. The agent's final output is a return value, not a status update for a human.
Second-order benefit that matters more than the money: less context consumed means fewer compactions, and compaction is where long multi-agent runs lose the thread.
Isolation: only when they write
If parallel agents modify files, they will collide. Git worktrees fix this — each agent gets its own checkout, and you merge after.
But it isn't free: setup time plus disk per agent. So the rule is narrow — isolate only when agents actually mutate the same files. Read-only fan-out needs no isolation, and paying for it there is pure overhead.
The related hard rule I learned the expensive way: never let an agent edit a repo another agent is actively working in. Two agents in one working tree means uncommitted work colliding and deploy flows fighting each other. If a fix belongs to someone else's repo, hand it over — don't reach in. And if you already touched a file to diagnose something, revert it and put the fix in the handover instead.
The money pattern: handover as a ticket, never a chat
Agents working different repos need a message bus. Mine is a single dedicated channel, and the format is the whole trick — a vague handover wastes a round-trip and gets actioned by the wrong agent.
1. TARGET + SCOPE which agent/repo this is for, and "others ignore"
2. CONTEXT one line: what you were doing, why this matters
3. ASKS numbered. exact file paths, line refs, values.
if you have a TESTED fix, paste the diff.
4. REPLY-WITH exactly what to send back, and where
5. SIGN-OFF which agent you are
Point 4 is the one everyone skips and it's what closes the loop. "Reply here with the final interface" means the other side knows when it's done and you know what to wait for. Without it you get an acknowledgement and no answer.
Point 3 matters because specificity is what makes a handover actionable. "The types are wrong somewhere" produces a conversation. "Line 47 expects string[], the API returns {id, name}[] — here's the tested patch" produces a fix.
The side benefit: it's a human-readable audit trail. I can read overnight agent traffic in the morning and know exactly what happened without reconstructing five transcripts.
The catch: fan-out multiplies confident wrongness
Two failures, both mine.
Unverified findings, five times over. Five agents produce five times the plausible-but-wrong claims, and they arrive pre-formatted as confident summaries. The fix is an adversarial verify stage: for each finding, spawn a critic whose explicit job is to refute it, defaulting to refuted when uncertain. Kill anything a majority of critics reject. Without that gate, parallelism scales your error rate as efficiently as your throughput.
Runaway agents. I once let a background agent run 138 minutes, co-editing files while I worked. Cap iterations, cap wall-clock, and make an agent report what it couldn't finish rather than grinding. And keep one reusable watcher rather than spawning a fresh poller per wait.
Also: if you bound coverage — top-N, no retries, sampling — say so out loud. Silent truncation reads as "covered everything" when it didn't, and that's the most dangerous output a fan-out can produce.
The verdict
Parallelise on independence, not ambition. Pipeline by default and treat every barrier as a cost you're choosing. Compress returns before fanning out, because sub-agent prose becomes your context tax. Isolate only writers. Hand over as precise tickets with a stated reply. Then put an adversarial verify stage in front of anything you'd act on.
Five agents with no verification gate is just five times the confidence.
Want a multi-agent build process that doesn't collide with itself? That's most of what I get hired for — start a conversation, or see recent projects.