Single Agent vs Multi-Agent: When Adding More Agents Makes the System Worse
When do multiple AI agents help, and when do they make engineering work worse? See a cancellation race, versioned handoffs, and a practical evaluation method.
On this page
- Single agent and multi-agent are not the same as serial and parallel
- The cancellation race all four agents missed
- Split the investigation before splitting the implementation
- More agents only shorten the part that is actually parallel
- What happens when the shared contract changes mid-run?
- The final test must run on the merged revision
- The work changes when investigations really are independent
- What published evaluations say about the trade-off
- Run two evaluations, because they answer different questions
- My decision for these two workloads
- Primary references
Four coding agents are given a feature to build. One changes an API, another modifies a background worker, a third updates the frontend, and the fourth writes tests. They work in separate branches and finish faster than one agent could have edited all four areas.
A customer then cancels a report export while its worker is publishing the result. The API accepts the cancellation and the UI says the job was cancelled. Seconds later, the file appears in the customer's downloads. All four patches passed their own tests, but the behavior of the finished system is wrong.
This is a hypothetical failure, not an observed benchmark. A single coding agent or a human team could make the same mistake. What makes the multi-agent design interesting is how the mistake can survive. Each model has its own context and can settle on an interpretation that is internally reasonable. Unless those interpretations meet at an explicit contract, nothing forces them to agree.
More agents can explore independent problems faster. They can also create more decisions that someone has to reconcile. For production engineering, the relevant comparison is not how quickly four agents finish four patches. It is how reliably and cheaply the system produces one accepted change.
Single agent and multi-agent are not the same as serial and parallel#
A single agent has one model-driven loop responsible for the task. It can still search repositories concurrently, run tests in the background, use a compiler, and launch several ordinary tool calls at once. Those tools do not each make open-ended decisions about the user's goal.
A multi-agent system has at least two model-driven loops with separate working contexts and some discretion over how to achieve their assigned objectives. One model may delegate research to others and integrate the evidence, or agents may collaborate as peers. Those topologies carry different costs and failure modes.
| Design | What becomes parallel | When it helps | What you must pay for |
|---|---|---|---|
| One agent with tools | Tool execution, not independent planning | Tightly dependent work | Larger working context |
| One agent with concurrent tools | Search, builds, and other independent I/O | Tools are the bottleneck | Shared rate limits and result aggregation |
| Lead agent with subagents | Independent reasoning and exploration | Work can be bounded by stable contracts | Handoffs, verification, stale results |
| Peer agents | Multiple independent decision-makers | Work genuinely requires interaction or diverse exploration | Conflicting state, convergence, unclear ownership |
For dependent engineering changes, one owner and concurrent tools is often a strong starting point. Multiple agents become attractive when independent investigations need their own working contexts or when branches can implement an already settled contract. The number of services or files involved is not a measure of that independence.
The cancellation race all four agents missed#
Our reporting service has an HTTP API, background workers, PostgreSQL, and object storage. An export can run for twenty minutes. A worker writes the output to a private staging object, then publishes a reference that the download API can expose.
The request was simply, "Allow users to cancel an export." Here is what each agent could reasonably have inferred from its limited assignment.
| Agent | Its private understanding of cancellation | Why its local test can pass |
|---|---|---|
| API agent | Setting the cancellation flag means the request succeeded | The database update returns success |
| Worker agent | Check the flag between batches and stop if it is set | A test cancels before the next batch |
| Frontend agent | HTTP success means the export has stopped | A mocked response changes the button state |
| Test agent | Test the API and worker behaviors separately | Neither mock exercises the publication race |
No one has defined what should happen when cancellation and final publication overlap. Separate contexts did not cause that missing requirement, but they allowed four incompatible answers to survive until integration. Even a conflict-free Git merge tells you nothing about their agreement.
I would settle the behavior before delegating implementation. For this service, accepting cancellation means the result must never subsequently become downloadable. If publication commits first, the API reports that the export has already succeeded and does not claim to have cancelled it. An accepted cancellation does not imply the worker process has stopped immediately. It means that publication is forbidden and cleanup must eventually finish.
A small state machine makes the boundary explicit:
QUEUED -> RUNNING -> SUCCEEDED
| |
+---------+----> CANCEL_REQUESTED -> CANCELLED
The important race is between CANCEL_REQUESTED and SUCCEEDED. Both transitions must compete on the same authoritative job record. An illustrative PostgreSQL cancellation attempt looks like this:
UPDATE export_jobs
SET state = 'CANCEL_REQUESTED', version = version + 1
WHERE id = :job_id
AND tenant_id = :tenant_id
AND state IN ('QUEUED', 'RUNNING')
RETURNING version
The worker uploads to a private staging key but must win a separate state transition before the result becomes visible:
UPDATE export_jobs
SET state = 'SUCCEEDED',
result_object_key = :staged_key,
version = version + 1
WHERE id = :job_id
AND state = 'RUNNING'
AND worker_epoch = :epoch
RETURNING version
These queries show the decision point, not a complete export-service implementation. The API authenticates the caller and authorizes access to the tenant and job before reporting a result. The worker claim and reclaim paths issue and advance worker_epoch, so a previous owner cannot publish after a replacement has taken over. The object remains private until the committed SUCCEEDED state authorizes a download. A presigned URL issued earlier would bypass that protection.
PostgreSQL's READ COMMITTED behavior makes the conditional race workable. If one update locks the row, the other waits and rechecks its WHERE condition after the first transaction commits. The cancellation and success transitions therefore cannot both win from RUNNING. The API must wait for commit before claiming cancellation was accepted. PostgreSQL's transaction isolation documentation describes this recheck behavior.
There is a less obvious retry. The cancellation transaction commits, but the HTTP response disappears. The client retries, and the conditional update now returns zero rows because the job is already CANCEL_REQUESTED. Zero rows must not automatically be interpreted as a rejection. After rechecking authorization, the API can read the current state and report that cancellation was already accepted, or that cleanup has completed if it is CANCELLED. If the row is SUCCEEDED, the API reports that publication won. An unknown or inaccessible job gets the established not-found behavior. If cancellation triggers notifications or other side effects, a stable request identity and an idempotent outbox prevent those effects from being duplicated by retries.
A queued job that accepted cancellation must never be claimed for new work. A worker that dies after cancellation needs a reconciler to finish cleanup, and an orphaned staging object must not become public. These are separate production concerns, but they all follow the same behavioral contract. The actual multi-agent lesson is that this contract has to exist before the API, worker, UI, and tests are developed independently.
Split the investigation before splitting the implementation#
The API, worker, and UI code may be far apart in a large repository. Independent agents can inspect those areas before anyone starts editing. One traces the API state transitions, another follows the worker through its final publication, and a third finds UI assumptions and existing tests. Each works against the same repository revision and returns source locations and concrete findings.
An integration owner then establishes the cancellation contract. Only after that is it useful to consider parallel patches. The UI and worker can implement different parts of a fixed interface, while the final integration gate checks the merged behavior against the same acceptance tests.
This is a useful distinction between separate model contexts and concurrent tool calls. If the bottleneck is three slow searches, one agent can dispatch them concurrently. If the bottleneck is independent reasoning over large bodies of evidence, subagents may be worthwhile because each can retain a focused working context. The extra coordination should buy something that simpler concurrency does not.
More agents only shorten the part that is actually parallel#
A rough critical-path model helps before reaching for another framework. Let S be shared discovery and contract work, I be integration and acceptance testing, and P1, P2, P3 be genuinely independent branches. H is additional coordination time, and R is extra repair caused by the separated work.
Single-agent wall time:
T1 = S + P1 + P2 + P3 + I
Parallel branches with coordination:
Tm = S + max(P1, P2, P3) + I + H + R
The model is deliberately simple. Some work can overlap, and queueing or retries belong in the measured terms. It also assumes the branches can be executed independently after the shared work has finished.
Suppose shared planning and integration take 50 minutes together, while the three branches need 30, 25, and 20 minutes. The single-agent path is 125 minutes. With 22 minutes of additional handoff overhead, the parallel path is 102 minutes, about 18 percent faster. If incompatible patches require 35 minutes of repair, it reaches 137 minutes and loses to the single-agent path. These are hypothetical timings, not measurements of any agent model.
The coordinator also waits for its slowest required branch. A model-rate-limit queue, stuck tool call, or repeated test failure can dominate the tail, even if the other agents finish quickly. I would measure time to an accepted merged result, including clarification and repair, rather than time until the last subagent announces that it is done.
What happens when the shared contract changes mid-run?#
Once implementation branches are admitted, the coordinator needs more than an instruction saying "handle the worker". The agent should receive the code revision it is working against, the exact contract version, permitted areas of change, the tests it must satisfy, and a place to return its artifact.
subtask_id: export-worker-cancellation
base_commit: 4f81c9a
contract_version: cancel-v2
contract_digest: sha256:example-redacted
allowed_paths:
- worker/export/
- worker/tests/
required_checks:
- cancellation_wins_before_publish
- publication_wins_before_cancel
- stale_worker_cannot_publish
output:
patch_ref: artifact://run-42/worker.patch
test_report_ref: artifact://run-42/worker-tests.json
This is an application-defined handoff, not a standard protocol schema. The digest represents the exact canonical contract bytes in a real system, and the base commit identifies the code that the patch assumes. A useful coordinator checks these values rather than trusting the subagent's prose description of its work.
Now imagine the worker agent is halfway through implementing cancel-v2 when an investigator finds a scheduled reprocessor that can republish an export from staged storage after a crash. The contract changes to cancel-v3. It now requires the reprocessor to respect CANCEL_REQUESTED before ever exposing a result. The frontend agent happens to finish against v3, while the worker agent returns a locally passing patch based on v2.
Both reports say completed. Their changes are not compatible.
The coordinator needs to treat the contract update as a revision of the work, not just another chat message. When v3 becomes current, affected v2 subtasks are marked stale and prevented from being accepted into the integration revision. An already-running agent can be cancelled, or asked for a bounded rebase that includes the new acceptance tests. An old patch may still contain useful code, but it needs explicit review against v3 before reuse. Results must carry the contract and source revision that produced them, and only the current revision can advance the integration state. Even a stale task returning after cancellation must not be able to publish a patch into the approved build.
A separate Git worktree for each agent prevents them from overwriting each other's local edits. It does not protect this higher-level contract. The version change is more revealing than a Git conflict because the two agents can modify different files and still ship incompatible semantics.
The coordinator also crosses a trust boundary when it consumes returned patches, logs, and repository excerpts. Subagent output is evidence and proposed code, not an instruction that can grant itself permissions or change the user's objective. A malicious README or test log can carry instructions that a model might follow. The coordinator should validate artifact identity, allowed paths, symlinks, and base revisions, apply changes in an isolated environment, and run checks against the merged commit. Delegated tools and credentials should stay within the subagent's scope. The broader containment problem is covered separately in Designing Containment for Production AI Agents.
That is the actual cost of adding reasoning loops. The application needs a way to decide whether a subagent result still belongs to the work everyone is trying to finish. If the contract is so fluid that every finding invalidates three other branches, the agents may spend more time renegotiating work than doing it.
The final test must run on the merged revision#
A subagent reporting that its patch passes tests is useful information, but it isn't acceptance evidence for the combined change. The integration gate must test the same behavior that the contract promises, using the actual API, worker, and job-state store.
For the export feature, one test holds the worker at a controlled point before publication, accepts cancellation through the API, then releases the worker. A timing-sensitive sleep is not enough to reliably expose the race.
worker.pause_before_publication(job_id)
result = api.cancel(job_id)
assert result.state == "CANCEL_REQUESTED"
worker.continue_publication(job_id)
assert db.job(job_id).state != "SUCCEEDED"
assert api.download(job_id).status == 404
This is test-harness pseudocode, not a runnable production test. Run the inverse ordering as well, then cover retries after a lost cancellation response, a queued cancellation, a worker replaced during upload, and a stale cancel-v2 patch returned after v3 has been adopted. The retry test should prove that the API does not turn an already accepted cancellation into a false rejection or duplicate an external notification.
Keep the root run's state durable enough to survive a crashed coordinator. It needs to know which contract is current, which task attempts were admitted, which artifacts were validated, and which integrated revision actually passed acceptance. Root cancellation should stop late artifacts from advancing the workflow. None of this requires another language model to certify that PostgreSQL committed a row update. Use deterministic checks for facts the systems themselves can establish.
The work changes when investigations really are independent#
Consider a new library vulnerability. A company has forty services with that dependency, and a scanner finds twelve cases where reachability depends on how the library is called. One service accepts untrusted input over HTTP, another processes fixed internal records, and a third uses a wrapper that may avoid the vulnerable path.
A deterministic inventory can identify the candidate versions. Several agents can then inspect independent codebases in parallel, each against a pinned commit and the same advisory. They can trace entry points, investigate call paths, run bounded tests, and return evidence about reachability. These are genuine separate reasoning tasks. An investigator of service A rarely needs to wait for the detailed findings in service B.
The coordinator should not simply count twelve reassuring messages. Each finding needs a source revision, entry-point evidence, relevant call chain, test result, and a clearly stated limit on the search. "No vulnerable path found" is not proof of absence. The advisory's basic facts should be verified separately so a shared misunderstanding doesn't contaminate every investigation, and a sample of conclusions should receive independent review.
The work is also different from a package-version scan, which ordinary software can do faster and more predictably. Extra agents earn their cost only if each service really needs sustained reasoning over different evidence. Here the benefits of independent contexts and parallel search can outweigh the joining work without forcing the agents to mutate one shared behavior as they proceed.
What published evaluations say about the trade-off#
Anthropic's June 2025 account of its Research system reported a 90.2 percent advantage for an Opus 4 lead with Sonnet 4 subagents over a single Opus 4 agent on an internal research evaluation. It was a breadth-first search setting where separate investigations could cover more ground. Anthropic also reported roughly 15 times the token usage of ordinary chat interactions. That is not a matched cost comparison against the single-agent research baseline, and the article itself cautioned that many coding tasks are less parallelizable than research.
The July 2026 Nature Machine Intelligence paper Capable language models can outgrow the benefits of collaboration compared 260 configurations over six benchmarks and five architectural approaches while matching prompts, tools, and per-system compute ceilings. Centralized coordination improved the Finance Agent benchmark from a 34.9 percent single-agent mean to 63.1 percent, while every tested multi-agent variant degraded performance on the more sequential PlanCraft benchmark, with relative declines from about 39 to 70 percent. SWE-bench Verified showed small declines across the tested architectures, and Terminal-Bench was mixed. These results describe those model families, tasks, and budgets. They do not prove that all multi-agent coding systems are worse.
Anthropic's August 2026 multiagent experiments offer another caution. In a simulated shared-project setting, some model generations opened many pull requests but merged few. Others improved throughput partly by avoiding collaborative edits to the same files, while one tested generation managed both more code sharing and stronger merging. These were simulations rather than production coding-agent measurements.
I would not collapse the three studies into one verdict. Parallel research can profit from extra inference and independent context. A matched-budget comparison can reveal that communication consumes capacity a strong single agent could have used directly. Both are useful findings. They suggest evaluating the dependency structure of the work, not choosing an agent count from a benchmark headline.
Run two evaluations, because they answer different questions#
The baseline should be a strong single agent with the same repository access, retrieval, tool permissions, and acceptance environment available to the alternatives. I would compare it with a single agent using concurrent read-only tools and a coordinator with bounded subagents. Peer-to-peer collaboration deserves its own configuration if the product actually needs it. Without the concurrent-tool baseline, a multi-agent win might only mean you finally parallelized slow I/O.
There are two experiments worth keeping separate.
| Experiment | What stays controlled | What the result tells you |
|---|---|---|
| Architecture comparison | Model pool, initial artifacts, tools, total inference budget, task set, acceptance criteria | Whether coordination adds value independently of extra compute or a different model mix |
| Production economics comparison | Task mix, quality floor, security requirements, realistic shared infrastructure | Which configuration, with its preferred model allocation, offers better accepted quality, cost, and latency |
A production configuration may sensibly use a more expensive lead model and cheaper specialists. That is a business decision, but it changes both architecture and model allocation. Do not interpret the result as the isolated effect of having more agents. Likewise, fix a total system budget for the controlled comparison, rather than accidentally granting every subagent the same budget given to the single agent.
Use paired tasks from the same pinned repository versions, with repeated trials and comparable stochastic settings. Cover tightly dependent changes such as cancellation, independent investigations such as the vulnerability assessment, and work that becomes parallel only after a shared contract is decided. Score the merged outcome, not the subagent reports. Where feasible, blind the reviewers to which architecture produced each patch and report success rates with uncertainty intervals rather than declaring a winner from a few favorable runs. Break the results out by task type because a single average can conceal the reason one design helps or hurts.
For coding changes, the measurements should include accepted-result rate, failed integrations, human repair time, full model and tool spend, wall time to accepted result, and latency distributions. Record contract revisions, stale artifacts, duplicated search, and coordinator retries as diagnostics. A useful economic metric is total cost per accepted change, but it should not hide expensive human remediation or the consequences of a bad change reaching production.
Consider hypothetical outcomes. A $2 attempt with a 70 percent acceptance rate costs about $2.86 per accepted result before repair. A $3 attempt with 95 percent acceptance costs about $3.16. Neither wins without considering task value, human review, and failure consequences. More importantly, do not count an integration test passing against one branch as an accepted result from the merged change.
Finally, run the comparison under realistic load. Parallel agents share model rate limits, CI workers, sandboxes, and search infrastructure. A system that wins in an empty development environment may lose once several teams fan out simultaneously. Keep limits on subagent concurrency, shared spend, and tool admission, and measure queue time instead of assuming extra model loops create extra external capacity.
My decision for these two workloads#
For the cancellation feature, I would use one implementation owner, concurrent investigation, and deterministic integration tests. A large repository may justify bounded subagents after the state contract is fixed. It would not justify four independent interpretations of cancellation or a merge process that accepts stale contract versions.
For the vulnerability assessment, I would run a deterministic inventory first and independent agents for the services that require code-level investigation. The coordinator would own evidence quality and verification, not every local reasoning step. That is parallelism with genuinely separate inputs and outcomes.
The strongest argument for more agents is evidence that the work separates naturally and that the extra reasoning contexts improve accepted results enough to cover their cost. The strongest argument against them is a task in which every next decision depends on a shared, changing state. In that situation another agent may add a handoff precisely where the current context matters most.
ArchCrux already goes deeper into the coding-agent harness and continuous agent evaluation. The Applied AI Engineering Cohort and Interview Prep library cover related design decisions. For this article, the architecture decision is narrower. Before launching a second model loop, show which part of the task becomes independent, who owns the contract between the parts, and what measurement would justify the extra coordination.
Primary references#
- Anthropic, How we built our multi-agent research system, June 2025
- Kim and colleagues, Capable language models can outgrow the benefits of collaboration, July 2026
- MIT Media Lab, When do AI agents benefit from collaboration?
- Anthropic, Patterns and problems in emerging multiagent systems, August 2026
- PostgreSQL 18, transaction isolation
Keep reading
Continue with a guided sequence of free production engineering essays.
Find your next reading pathRelated reading
Continue this path
How Coding Agents Actually Work: Inside the Agent Harness
A technical look inside coding agent harnesses, covering context management, repository search, tools, sandboxes, subagents, durable sessions, recovery, concurrency, completion and evaluation.
Read essayDesigning Continuous Evaluation for Production AI Agents
Production AI agent evaluation needs more than task success. It needs behavioral checks, trajectory analysis, outcome verification, failure lineage, repeated trials, statistical release gates, and production failures feeding new evaluation evidence.
Read essayDesigning Long-Running AI Agents That Survive Failures
Long-running AI agents need durable execution, explicit state, idempotent actions, bounded retries, recovery workflows, and operational control to survive real production failures.
Read essay