spawnagent.sh

One Agent or Many? Running AI Agents in Parallel

6 min read

Starting several agents at once takes a minute. Finishing their work well takes planning. Parallel agents multiply throughput only when the pieces of a task are truly independent. When they are not, the same setup multiplies conflicting decisions, duplicated effort and review work, and the time you hoped to save goes into untangling it.

The question that decides it: are the pieces independent?

Anthropic's write-up of its multi-agent research system is a useful reference because it reports both the wins and the limits. The team found the approach works best for "breadth-first queries that involve pursuing multiple independent directions simultaneously." It also names poor fits: tasks that require "all agents to share the same context or involve many dependencies between agents," and it observes that "most coding tasks involve fewer truly parallelizable tasks than research." The same post reports that multi-agent systems used about 15 times more tokens than chats in their data, so the task has to be worth the cost.

A working definition: pieces are independent when each one can be built and checked without waiting on another piece or editing its files. Tasks that usually meet that bar:

  • Migrating many files to a new API when each file changes on its own.
  • Writing tests for modules that do not depend on each other.
  • Triaging a list of unrelated bugs.
  • Researching several candidate libraries and summarizing each.

Tasks that usually do not:

  • A feature that touches the schema, the API and the UI at once.
  • A rename or refactor that ripples through shared code.
  • Anything whose design is still undecided.

Why parallel work backfires

The core problem is decisions nobody coordinated. In a post titled Don't Build Multi-Agents, Walden Yan of Cognition puts it as a principle: "Actions carry implicit decisions, and conflicting decisions carry bad results." His example is a Flappy Bird clone where one subagent builds a background that looks like Super Mario Bros and another builds a bird that neither looks nor moves like the original, leaving a final step to reconcile parts that were never designed to fit.

The costs show up in three places:

  • Coordination. Someone has to write every brief, answer every question and settle every disagreement.
  • Duplication and gaps. Anthropic's team found that without detailed task descriptions, "agents duplicate work, leave gaps, or fail to find necessary information."
  • Review. Five agents produce five diffs, and a person or a reviewing agent still has to understand all of them together.

A useful test before fanning out: if you cannot describe each shard's boundary in one sentence, you are not ready to split the work.

Split the work before you spawn anything

Most parallel failures are decided before the first agent starts, so front-load the planning.

Make the shared decisions first. Interfaces, data shapes, error formats, naming and library choices are exactly the implicit decisions that collide. Settle them in a short contract document that every agent reads, or have one agent write the contract before the others begin.

Split by ownership, not by step. Give each shard a set of files or directories it owns outright. Nobody else edits them. "Write the client" and "write the server" is a clean split. "Write the code" and "write the tests" for the same module is not, because both sides keep changing the same assumptions.

Make each shard verifiable alone. Every shard needs its own check that proves it is done, such as a test file, a build target or a lint pass.

Name the hot files. Lockfiles, route registries, shared config and changelogs attract edits from everyone. Assign each one a single owner, or save those edits for the integration step.

A brief can be as small as a table row:

ShardOwnsMust not touchDone when
api-clientsrc/client/src/server/client tests pass
server-routessrc/server/routes/src/client/route tests pass
api-docsdocs/api/any source fileevery endpoint has a page

Each shard also needs its own checkout, such as a separate worktree or clone, so that agents never edit the same files on disk.

Keep a shared record of who owns what

Agents working in separate checkouts cannot see each other. A shared board fixes that. It is a single file or table that every agent reads at the start and updates as it goes, and it lives outside the shards' branches so updates never conflict with code changes:

shards:
  - id: api-client
    owner: agent-1
    paths: [src/client/]
    status: in_progress
  - id: server-routes
    owner: agent-2
    paths: [src/server/routes/]
    status: blocked
    note: waiting on the error shape from api-client

Three habits make the board work:

  • An agent checks the board before touching any path outside its lane, and asks instead of editing.
  • When an agent discovers something another shard needs, such as a changed interface, it posts it to the board rather than quietly fixing the other shard's code.
  • Status changes go on the board as they happen, so a stuck shard is visible early.

For an open-source example of this pattern, Clerv runs several Claude Code sessions on one codebase with a shared board, a worktree per shard, cross-session messages and verification gates.

Merge conflicts: find them before the merge

When two branches change the same lines differently, Git stops and marks the region with <<<<<<<, ======= and >>>>>>> markers. Its merge documentation covers resolving them, and git merge --abort tries to reconstruct the state from before the merge started. The docs warn that it cannot always restore uncommitted changes, so commit or stash first.

You do not have to wait for the real merge to find out. git merge-tree with --write-tree (Git 2.38 or later) performs a merge without creating commits and without reading or writing the working tree or index. It exits with 0 when the merge is clean and 1 when there are conflicts. With --name-only and --no-messages, its output is the resulting tree ID on the first line, followed by just the conflicted file names. That makes it cheap to check every pair of shard branches while agents are still working. In bash:

branches=(agent/api-client agent/server-routes agent/api-docs)
for ((i = 0; i < ${#branches[@]}; i++)); do
  for ((j = i + 1; j < ${#branches[@]}; j++)); do
    a=${branches[i]} b=${branches[j]}
    if ! out=$(git merge-tree --write-tree --no-messages --name-only "$a" "$b"); then
      echo "conflict: $a vs $b"
      printf '%s\n' "$out" | tail -n +2   # the conflicted files
    fi
  done
done

A branch name that does not exist also makes the check fail, and Git prints the reason on stderr, so read that line before chasing a conflict that is not there.

A pair that conflicts early usually means an ownership boundary is wrong. Fix the boundary on the board, not just the lines in the file.

Text conflicts are the easy kind. The harder kind is a semantic conflict: two changes that merge cleanly but break together, such as one shard renaming a function while another adds a new call to the old name. Git cannot see those. Only a build and a test run on the combined code can.

Merge in dependency order. Land the shard others build on first, rebase the rest onto it, and rerun their checks before merging them.

Verify the combined result, not each piece

Every shard passing its own checks tells you each piece works alone. It does not tell you they work together. After merging everything onto one integration branch:

  1. Run the full build and the full test suite once, on the combined code. Confirm the tests actually ran. A suite that collected zero tests is a failure, not a pass.
  2. Have one reviewer read the whole combined diff against the original request. Give them the request and the diff, not the shard summaries. Look at the seams: duplicated helpers, two implementations of the same idea, an old code path left running beside its replacement, an interface one side changed and the other did not.
  3. Reconcile the counts. If the task was "update every call site," count how many exist, how many changed, and name any that did not.
  4. Give red builds an owner. The integration step owns failures that span shards. No shard is finished while the combined build is failing, even if the break started somewhere else.

Choosing between one and many

Run agents in parallel when the shards are independent, each has a clear owner and its own check, the merge can be tested automatically, and the time saved is worth the extra tokens and review. Stay with one agent when the design is unsettled, the work runs through shared files, or each step depends on the last. A hybrid often wins: one agent writes the contract, several implement against it, and one integrates and verifies.

The real limit on how many agents you can run is rarely compute. It is how many clean boundaries you can draw and how much combined output you can honestly verify.

More from spawnagent.sh