All articles

// Knowledge.log — 技術記事

Do parallel coding agents make a team faster? What still breaks at merge

Two agents on the same line conflicted and one decision was dropped; disjoint files merged clean at nearly 2× tokens. Where fan-out pays off.

When delivery stalls, the first move these days is almost a reflex: add agents. One subagent takes the tests, another takes the migration, each gets its own worktree, and /batch slices up the change. Behind the reflex is a simple and persuasive thesis: more agents in parallel means more throughput, ideally in proportion to the number of agents.

That thesis is what this piece puts on trial. The claim here is not that agent parallelism fails. The claim is that the usual question is the wrong one. "How many agents can I start?" is easy to answer and doesn't help much. The question that shapes a team's week is a different one: how much parallelism can this repository take before the merge becomes the bottleneck? You can answer that for your own repository with one criterion and one cheap measurement.

Where the thesis comes from

The thesis didn't come from nowhere. It has receipts, and each one deserves a full read, because each one states its own limit.

The most cited is Anthropic's engineering post How we built our multi-agent research system, published June 13, 2025. The headline number is impressive: "We found that a multi-agent system with Claude Opus 4 as the lead agent and Claude Sonnet 4 subagents outperformed single-agent Claude Opus 4 by 90.2% on our internal research eval." The post also gives the bill: "agents typically use about 4× more tokens than chat interactions, and multi-agent systems use about 15× more tokens than chats."

Scope matters. The work being evaluated was research: broad queries that split cleanly into independent threads. Code merges were not part of it. The same page says so directly: "most coding tasks involve fewer truly parallelizable tasks than research". The 90.2% came from an internal research eval. If you bring that number into a repository, you are quoting the headline and leaving the experiment behind.

The second receipt is the tool itself. The Claude Code subagents documentation describes the official way to delegate: "Each subagent runs in its own context window with a custom system prompt, specific tool access, and independent permissions." A separate context is what lets you slice the work. It is also what lets each slice make its own decisions.

The third receipt is about code specifically. The Claude Code: Best practices page (the page carries no publication date; we read it on September 27, 2026) recommends: "Run multiple Claude sessions in parallel to speed up development..." It describes /batch as well: "/batch <instruction> ... split the change across 5 to 30 subagents. Each subagent works in its own worktree." The same text already carries the correction, since worktrees exist "so edits don't collide". Nobody builds isolation for things that can't collide.

On the other side is Walden Yan's essay for Cognition, Don't Build Multi-Agents, from June 12, 2025. It is an engineering essay, not a controlled measurement, so here it serves as a mechanism and never as a number. The mechanism is precise: "Actions carry implicit decisions, and conflicting decisions carry bad results." When two subagents work apart, "The actions subagent 1 took and the actions subagent 2 took were based on conflicting assumptions not prescribed upfront." His recommendation runs the other way from fan-out: "The simplest way to follow the principles is to just use a single-threaded linear agent."

Read carefully, the receipts disagree less than they first appear to. One measured a gain in research and warned that code parallelizes less. One makes delegation official. One tells you to parallelize and isolate so edits don't collide, and the last explains why they collide anyway. None of them looked at the merge itself.

The experiment: two agents, one repository, four scenarios

The instrument is small on purpose. It ran on September 27, 2026 on a machine with 4 vCPU (AMD EPYC-Rome) and ~7.6 GiB of RAM (7746 MB), without containers, using Claude Code CLI 2.1.282 and git 2.53.0. The agents ran headless with --model claude-sonnet-5, with at most two processes running at the same time. The scratch repository has the files src/a.txt through src/f.txt, with one line each. The edits are mechanical, such as replacing base-b with beta=one. The agent only edits. The harness does staging, commits and merges.

Each agent was invoked like this:

IS_SANDBOX=1 claude -p "$PROMPT" --dangerously-skip-permissions --model claude-sonnet-5 --output-format json > agent-<name>.json

About those flags: the agents ran with IS_SANDBOX=1 and --dangerously-skip-permissions because in this sandbox the process runs as root and the worktrees sat inside .git/. With --permission-mode acceptEdits, the CLI ran but refused to edit, because it treats paths under .git/ as sensitive. The bypass flag alone is rejected when the process runs as root. On a real team, keep worktrees outside .git/ and use a tool allowlist or acceptEdits instead of the bypass flag.

All four scenarios share the same premise. In overlap, two agents edit the same line of src/a.txt, and one wants alpha=one while the other wants alpha=two. In disjoint, two agents edit different files, src/b.txt and src/c.txt. The baseline is a single agent making the same two edits as disjoint, from the same commit, with no fan-out. In scan, two agents only read three files each and report what they contain.

The git side of overlap:

git worktree add -b overlap-1 ../wt-overlap-1 main
git worktree add -b overlap-2 ../wt-overlap-2 main
# agents edit src/a.txt; the harness runs add/commit in each worktree
git merge --no-ff --no-edit overlap-1   # exit 0
git merge --no-ff --no-edit overlap-2   # exit 1
git diff --name-only --diff-filter=U

The second merge returned:

Auto-merging src/a.txt
CONFLICT (content): Merge conflict in src/a.txt
Automatic merge failed; fix conflicts and then commit the result.

git diff --name-only --diff-filter=U then listed a single unresolved file, src/a.txt.

scenarioagentswalltokens per agentcost per agentmergerework
overlap (same file, same line)25 s51,415 / 51,425$0.049 / $0.0491st clean; 2nd CONFLICT in src/a.txt1 file, 4 manual steps; alpha=two discarded
disjoint (disjoint files)25 s51,782 / 51,788$0.043 / $0.043clean / clean0 conflicts; beta=one and gamma=one intact
baseline (1 agent, both edits)16 s52,692$0.048not merged (comparison only)n/a
scan (read-only)25 s34,251 / 34,241$0.040 / $0.040no merge surfacen/a

The comparison that matters holds the work constant: two edits, from the same commit a0299d6. The disjoint fan-out used 103,570 tokens in total, against 52,692 for the baseline. That is 50,878 extra tokens (+96.6%, ≈1.97×). The cost was $0.0865 against $0.0476. The wall clock read 5 s against 6 s, which is effectively a tie at 1 s resolution. At this scale there is no wall-clock gain worth reporting, because the fixed cost of starting each process takes longer than the edit itself.

Tokens and cost come from the CLI's own JSON, in the usage and total_cost_usd fields (list price), with one file per invocation, nothing estimated by hand, and all seven runs exited 0 inside the timeout.

This experiment measures merge behavior, rework and the token overhead of fan-out. It does not measure capacity, productivity or model quality. There is no p95 or p99 because there is no distribution to summarize, only seven invocations making one-line edits. Neither the conflict rate nor the ≈1.97× applies to a real team's repository. What does carry over is the mechanism.

What the numbers say

The conflict is about decisions, not the model

In overlap, both agents did exactly what they were asked. One reported replacing base-a with alpha=one, the other with alpha=two, and neither touched any other file. Each was right about the file and wrong about the other agent. The file after the second merge shows it:

<<<<<<< HEAD
alpha=one
=======
alpha=two
>>>>>>> overlap-2

Two correct edits to the same line still leave only one decision standing. The rework was small: one file and four manual steps. Those were inspecting the markers, git checkout --ours, git add and the reconciliation commit. The harness used a "first one in wins" rule, so alpha=one stayed and alpha=two was discarded. In a real repository someone has to pick that rule case by case, and making that choice is exactly the work parallelism was supposed to remove.

The final graph looks immaculate: one merge, one reconciliation, everything green. The second agent's decision lies buried in a commit called reconcile.

This is still the good case, because a textual conflict at least warns you. This experiment's metric only sees textual conflicts. A semantic conflict passes through the merge without a single marker: two different files, one incompatible decision. For example, one agent changes a field's format while another agent, in another file, still assumes the old one. That is the scenario the Cognition essay describes, and no --diff-filter=U will catch it.

A clean merge isn't a free merge

Disjoint worked end to end: two clean merges, zero conflicts, and both changes intact on main. If the only question were "does the merge break?", the answer here would be no.

But the token bill nearly doubled to deliver the same two edits, and the clock barely moved. Fan-out with disjoint write-sets solves the collision but does nothing for the cost. Every extra agent is a whole extra process, and the JSON shows what that costs.

The per-process context floor

Each headless invocation paid between ~34k and ~53k tokens. Most of that is cache_read_input_tokens, with 43,608 in disjoint-1 alone. Output tokens, which are the agent's reply and contain the edit, ranged between 292 and 557. The useful work is a small fraction of the bill. The rest is fixed context that every process loads again when it starts.

Fan-out multiplies that floor. It can't be compared with the ~15× in Anthropic's post, which measures something else: multi-agent research systems against chat interactions. The number here is smaller and more local: what one extra process costs in this CLI, on this machine, for a trivial task.

The protocol that survives

If "more agents, more throughput" doesn't hold up on its own, what should a team do instead? Treat agent parallelism as what it is, concurrent writes to a shared repository. From there the rules are the usual ones, applied to a new kind of writer.

  1. Partition by write-set. Before the round starts, each agent gets ownership of files or directories that only it may touch. Two agents never edit the same file in the same round. The write-set map is written before the prompts, not reconstructed after the merge.
  2. Cap N, starting at 2. A round starts with two agents, and N only goes up after consecutive rounds with no conflicts and zero rework. The cap is 3 for the first phase. Going from 2 to 3 also requires a measured wall-clock gain, and going beyond 3 requires your own track record to justify it.
  3. Single integrator. Agents deliver raw work in their own worktree. Staging, commits, merges, conflict resolution and verification belong to one integrator, either a script or a person. In the experiment the harness played that role, which is why the conflict turned into four documented steps instead of a fight between two processes.
  4. Per-agent abort criteria. There are three triggers, and none of them leads to a retry loop. The first is a hard timeout (180 s in the experiment). The second is an edit outside the write-set, which the worktree's git status --porcelain shows before the commit. The third is a no-op round, where the harness tries to commit and finds nothing staged. Any one of them gets logged, and the agent stops.
  5. Shared context ends parallelism. If the task needs a shared decision, such as an API contract, renaming a concept or a refactor that cuts across modules, don't parallelize. Use a single linear agent with continuous context. If parallelism is unavoidable, freeze the interfaces and boundaries first, make that decision in one place, and only then send agents out to "fill in this region" inside what has already been decided.

To track this, you need five numbers per round: conflicts, rework (files and manual steps), tokens, cost per invocation (both from --output-format json) and wall clock. If your harness doesn't record them, the team is tuning N blind, however nice the "how many agents fit here?" dashboard looks.

Where the thesis still holds

The thesis is right in one well-defined place: work with no merge surface. The scan scenario shows it. Two agents read three files each and reported what was expected, and the worktrees ended with no changes at all. There was nothing to merge, reconcile or discard. Audits, code search, pattern sweeps and fan-out review all fit this shape. There is still a cost (~34k tokens per invocation here), but it is the only cost. This is also the shape closest to the research case in Anthropic's post.

It also holds for modules with clean boundaries and truly disjoint write-sets. In disjoint, the only cost was tokens. When the slices are large and the boundaries don't hide a shared decision, fan-out delivers.

There are three places where parallelizing just buys you more manual merges. The first is the same file and the same line, which is exactly where overlap broke: a one-line edit that still conflicted. The second is cross-cutting refactors, which by definition touch everyone's write-set. The third is any task that depends on a shared decision, where the conflict may not even surface at merge time.

Recommendation

DevDojo would adopt fan-out without hesitation for reading and sweeping work, such as audits, search and parallel review, because that work has no merge surface.

For writes, we would fan out only with the whole protocol above in place, and only while conflicts per round stay at zero. Tasks that depend on a shared decision stay with one linear agent.

The signals to back off are concrete. A conflict in a round that had separate write-sets means the map is wrong. A reconciliation that discards an agent's decision needs someone to review it. Two more: tokens per delivered change climbing with no wall-clock gain, and an integrator queue growing faster than it drains. Any of these means dropping N by one step and revisiting the partition before trying again.

Next step

Run one round with N=2 and a fixed write-set map written before the prompts. Count conflicts, rework and tokens per invocation from the CLI's JSON before you decide whether N goes up.

ai-agentsgitdevex

// Continue.training — 次のステップ

Knowledge only counts when it becomes practice.

Go back to the article, run the examples, and share what you learned.

Explore more articles