Multi-Agent Workflows in Claude Code
Most of the time, one Claude Code agent in one thread is the right tool. You describe a task, it reads the surrounding code, makes the change, and verifies it. Reaching for "multiple agents" on that kind of work is over-engineering.
But there's a specific class of task where a single agent is structurally weak: the repeatable audit. A broad bug sweep before a risky merge. A dimension-by-dimension code review you want run identically every time. A parallel read of an unfamiliar codebase. For these, you don't want a clever one-off — you want a deterministic orchestration that runs the same shape every time and returns comparable results.
This post explains how that orchestration works in Claude Code: the difference between a subagent and a workflow, the two ways to combine agents (pipeline vs barrier), why a separate verify stage matters, and a concrete example — a bug-hunt that fans out finders and then adversarially verifies what they found. It's conceptual, with a small pseudo-script at the end. By the end you should be able to judge when a workflow earns its cost and when it just burns tokens.
Three primitives: skill, subagent, workflow
Claude Code ships two ways to package behavior — skills and subagents. Orchestration adds a third layer, the workflow, built on top of them.
- A skill is a procedure loaded into your current conversation. It shares your context and tools. Cheap, in-thread, no handoff. Great for "always do X this way" — but it's the same Claude carrying the same assumptions, so it can't give you an independent second opinion.
- A subagent is a fresh Claude instance with its own context window and tool policy. You hand it a bounded task; it works in isolation and returns only a summary. That buys two things a skill can't: independence (it isn't anchored to your thread's conclusions) and isolation (its noisy exploration doesn't pollute your context). The price is a lossy handoff and a full extra context window per run.
- A workflow is a scripted orchestration — usually a fan-out of subagents plus a synthesis step — that you write once and run the same shape every time. It's the conductor; subagents are the players.
The key mental correction: a workflow is not a chat prompt or a slash command. It's a script executed by a runner — for instance, one built on the Claude Agent SDK. That's what makes it deterministic — the number of agents, the dimensions they cover, the order of stages, and the schema each returns are all fixed in code, not decided ad hoc by a model mid-conversation.
Fan-out: parallel breadth
The core move in any multi-agent workflow is fan-out: spawn N subagents at once, each scoped to a different slice of the problem, and run them in parallel.
Why fan out instead of asking one agent to "check everything"? Two reasons.
- Context budget. One agent asked to check correctness, boundaries, contracts, concurrency, and security across a diff has to hold all of that in one window. Attention spreads thin and coverage gets shallow. Give each dimension its own agent with its own full window and each one goes deep.
- Independence. Separate agents don't cross-contaminate. A finder looking only for authorization gaps won't get distracted rationalizing a style nit, and its conclusions aren't colored by another agent's.
Fan-out is embarrassingly parallel, so wall-clock time is roughly the slowest single agent, not the sum. The cost, though, is the sum of the parts — this is the expensive primitive, and the reason you reserve workflows for changes where missing a defect actually hurts.
Pipeline vs barrier
Once you can spawn agents, there are two ways to compose them. Getting this distinction right is most of what "orchestration" means.
Pipeline (sequential): stage B consumes stage A's output. plan → implement → review is a pipeline; you can't review what doesn't exist yet. Pipelines encode a dependency. They're slower — no overlap — but necessary when each step needs the previous one's result.
Barrier (parallel + join): you fan out K independent agents, then wait for all of them before the next stage runs. The barrier is the join point. No agent proceeds past it until every sibling has returned. A bug-hunt's finder stage is a barrier: spawn all the finders, let them run concurrently, and only once every one has reported do you move to verification.
Real workflows nest the two. The overall shape is a pipeline of stages; individual stages are barriers over a fan-out:
pipeline:
stage 1 ── fan-out finders ──┐
├─ barrier (wait for all)
──────────────────────┘
stage 2 ── verify each finding (fan-out) ── barrier
stage 3 ── synthesize + rank (single agent)
The determinism comes from fixing this structure in the script. Same stages, same barriers, same dimensions — so two runs on two branches are actually comparable.
The verify stage: why finders don't get the last word
Here's the part that separates a serious workflow from "spawn some agents and staple their output together."
A finder agent is incentivized toward recall. Told to hunt for bugs, a language model will surface plausible-sounding issues — and some fraction are hallucinated, already handled elsewhere, or true but harmless. If you report raw finder output, you hand the user a wall of maybes and make them do the triage. That destroys the value.
So a good workflow adds an adversarial verify stage. Each candidate finding is handed to a fresh agent whose job is the opposite of the finder's: try to disprove it. Reproduce the exact failure. Trace the actual code path. If it can't construct a concrete input that triggers the bug, the finding is dropped.
This works precisely because of subagent independence. The verifier isn't the finder defending its own claim — it has no stake in the finding being real. It's the same principle behind an adversarial reviewer that assumes a change is wrong until it fails to break it. Recall from the finders, precision from the verifiers. You report only what survived.
An optional refinement is voting: run the finder stage more than once (or with several models) and keep findings that show up independently. Corroboration across runs is a strong signal; a one-off that never reproduces probably isn't real.
A concrete shape: the bug-hunt
Putting it together, here's the shape of a bug-hunt workflow over a diff. This is pseudo-code — a real runner injects an agent(prompt, opts) call plus pipeline, parallel, and barrier helpers — but the structure is the point, not the syntax.
// bug-hunt: fan out finders across dimensions, then adversarially verify.
async function bugHunt(diff, { voters = 1, minSeverity = "should-fix" }) {
const dimensions = [
"correctness", // logic errors, off-by-one, wrong branch
"boundaries", // null/empty/overflow, edge inputs
"contracts", // API shape, error handling, types
"concurrency", // races, non-atomic read-then-write
"security", // authz gaps, IDOR, injection, SSRF
];
// STAGE 1 — fan out finders (barrier: wait for all)
const rounds = [];
for (let v = 0; v < voters; v++) {
rounds.push(parallel(dimensions.map(dim =>
agent(`You hunt only for ${dim} bugs in this diff.
Report concrete findings: file:line, the failing input,
and the wrong result. Do not invent findings.`,
{ input: diff }))));
}
const candidates = dedupe((await barrier(rounds)).flat(2));
// STAGE 2 — adversarially verify each finding (fan-out + barrier)
const verified = await barrier(candidates.map(f =>
agent(`Try to DISPROVE this finding. Reproduce the exact failure
with a concrete input, or trace the path that makes it
unreachable. Return CONFIRMED + repro, or REFUTED + why.`,
{ input: f })));
// STAGE 3 — synthesize: keep survivors, rank by severity
return verified
.filter(v => v.verdict === "CONFIRMED" && atLeast(v.severity, minSeverity))
.sort(bySeverity);
}
Read the stages against the primitives: stage 1 is a fan-out across dimensions under a barrier; stage 2 is the adversarial verify, itself a fan-out; the whole thing is a pipeline because verification depends on candidates and synthesis depends on verdicts. The output is a ranked list of confirmed bugs with reproductions — not a pile of hunches.
When a workflow actually beats one agent
Be honest about the tradeoff. A workflow spends several context windows and real wall-clock latency. That's justified only when specific conditions hold:
- The process is repeatable. You'll run it many times and want comparable results each time — pre-merge review, a scheduled audit, onboarding a new service.
- Breadth matters. The task spans dimensions a single agent would cover shallowly.
- Independence is the point. You need an unbiased second (and third) opinion, not the same thread's self-assessment.
- The stakes are real. The change touches auth, money, data, or concurrency, where a missed defect is expensive.
If none of those hold — a one-line config change, an exploratory question, a task you'll do once — skip the orchestration and just ask Claude directly. Running a five-agent bug-hunt on a two-line diff is pure waste. Match the tool to the stakes.
Where to start
You don't have to build the runner from scratch to internalize the pattern. The free, open-source claude-code-starter includes a bug-hunt workflow, an adversarial-reviewer subagent, a ship skill, and a Next.js/TypeScript CLAUDE.md template — reference implementations you point your own workflow runner at and adapt to your stack. Reading those files alongside this post is the fastest way to see fan-out, barriers, and the verify stage as concrete code rather than diagrams.
The takeaway is smaller than it looks: multi-agent orchestration is just fan-out plus barriers plus an adversarial verify stage, fixed in a script so it runs the same way every time. Use it for the repeatable, high-stakes audits where determinism and independence pay for themselves — and keep using a single agent for everything else.
Related guides
- CLAUDE.md Best Practices (With Examples)
- Getting Started With Claude Code: A First-Day Guide
- What Are Claude Code Skills (and How to Write One)
Set up Claude Code the right way
Start free with the open-source starter — a ship skill, an adversarial-reviewer subagent, a bug-hunt workflow, and a CLAUDE.md template. Want the full kit? The Pro Pack adds 6 skills, 3 subagents, 3 workflows, 4 templates and a handbook.