Why adding agents stops making things faster
5 min read
You double the number of agents and the work finishes in the same time. This is the most common disappointment in multi-agent development, and it is not a bug in the tooling. A plan cannot finish faster than its longest chain of dependencies, however many agents you throw at the rest of it.
That chain is the critical path, and it is computable before you dispatch anything.
What it actually is
The longest path through the dependency graph — the minimum time to complete all tasks even with unlimited parallelism. DevPilot computes it with topological-sort-based dynamic programming:
1. Build DAG graph from tasks and edges
2. Run topological sort to get valid ordering
3. Forward pass: compute distanceFromRoot for each task
4. Find terminal node with maximum distance (end of critical path)
5. Backtrack: build path from end to start using predecessor tracking
6. Backward pass: compute distanceToEnd for slack calculation
7. Compute slack: slack = (totalLength - 1) - (distFromRoot + distToEnd)
Two passes and a backtrack. The forward pass answers "how far into the plan is this task at the earliest"; the backward pass answers "how close to the end is it at the latest". Everything useful falls out of the gap between them.
Slack is the number that tells you where to spend
slack = (totalLength - 1) - (distFromRoot + distToEnd)
A task with zero slack is on the critical path. Delay it by a minute and the whole plan finishes a minute later.
A task with slack of three can start three positions later than its earliest opportunity and cost you nothing. Speeding it up buys nothing either — which is the part people get wrong.
This is why "add more agents" so often fails to help. Widening a wave adds capacity to tasks that already had slack. The chain that determines your finish time is untouched, and you have spent tokens and review attention to change a number nobody was waiting on.
The practical rule: only parallelise work that is on the critical path, or work that would otherwise push something onto it.
What to do once you can see it
Three moves, in descending order of leverage.
Shorten the chain. Look at each dependency on the path and ask whether it is real. "B depends on A" is often shorthand for "A creates a file B imports" — which can frequently be resolved by defining the interface first as its own tiny task, letting A and B proceed against the contract rather than against each other. That converts one long chain into two shorter ones.
Make critical-path tasks smaller. A 60-minute task on the path is 60 minutes of floor. Splitting it into three 20-minute tasks does not help if they remain sequential — but it often reveals that only one of the three was truly dependent.
Stop optimising everything else. The most common waste is tuning a task with slack, because it looks slow. It is slow and it does not matter.
Why this needs machine computation
You could trace a five-task graph by hand. At twenty tasks with a dozen edges, the longest path is genuinely non-obvious — and the intuition people reach for, "the chain with the most tasks", is wrong whenever task durations differ.
Which is the argument for writing plans as explicit dependency edges rather than narrative order. Prose hides the path. A graph makes it a calculation.
Note that the implementation returns annotations per task, not just the path itself. That matters more than it sounds: knowing which path is longest tells you the floor, but knowing every task's slack tells you where the floor is soft.
The relationship to waves
Wave planning and the critical path answer different questions. Waves are about coherence — a barrier so there is a reviewable state between batches. The critical path is about the theoretical floor.
They interact in a way worth knowing: a wave barrier can only make the plan slower than its critical path, never faster. If a wave contains one critical-path task and five with slack, everything waits for the long one, and the barrier costs you nothing. If a wave contains two independent critical-path tasks, the barrier is free. Waves become expensive when they force a critical-path task to wait behind unrelated work — which is a scheduling error the plan can be checked for.
A worked example of the counter-intuitive part
Imagine twelve tasks. Eleven are independent one-hour jobs. The twelfth is a four-hour migration that three of the others depend on.
The instinct is that twelve tasks across twelve agents finishes in an hour. The critical path says otherwise: the migration takes four hours, and the three dependents cannot start until it lands, so the floor is five hours. Eleven agents spend four of those five hours idle or working on tasks with slack.
Now change one thing — split the migration into "write the schema change" (30 minutes) and "backfill the data" (3.5 hours), and notice that the three dependents only need the schema, not the backfill. The chain becomes 30 minutes plus one hour. The floor drops from five hours to ninety minutes, and the backfill runs in parallel with everything else because it is now nobody's dependency.
Nothing about capacity changed. One dependency was examined and found to be coarser than it needed to be. That is almost always where the win is, and it is invisible until you can see which chain is actually the long one.
What we have not measured
The argument here is structural rather than empirical: it follows from the algorithm, not from a curve we have plotted. We have not published a study showing how much wall-clock real teams recover by shortening chains rather than widening waves.
The benchmark suite is built to answer exactly that — the same project, decomposed differently, measured — and it is not yet running in CI with committed results. Until it is, treat the guidance above as reasoning from the mechanism and size your concurrency with the same caution.
