Three tool calls are ready: a browser audit, a page screenshot, and an API crawl. None depends on another. The dependency graph says all three may run in parallel.
The runtime still should not launch the whole batch.
Together, the calls need more memory and API quota than the system has available. The plan is logically valid but physically unsafe. Treating those as the same decision turns a latency optimization into an avoidable capacity failure.
The distinction is simple:
The graph grants eligibility. The budget grants admission.
Agent runtimes need both.
Parallel tool use contains two decisions
A dependency graph answers a logical question: which calls must wait for another call's output, and which may overlap?
Resource scheduling answers a physical question: which eligible calls can share finite infrastructure right now?
PeakBench, an August 2026 arXiv v1 preprint, separates these questions in a benchmark for resource-aware tool invocation. Its authors built 300 executable multi-tool workflows and derived prerequisite structures through sandbox execution. They also measured CPU, memory, GPU, network, and disk-I/O profiles for tool calls.
The benchmark evaluates logical planning with Graph Edit Distance and Edge F1. It evaluates physical scheduling with Scheduling Latency, Capacity Violation Area, and strict mean resource utilization. This separation matters because, within PeakBench, better dependency planning did not reliably predict a safer or more efficient schedule on the same cases.
That result does not prove every production agent needs the same scheduler or resource model. It does establish a useful diagnostic boundary: when a tool workflow fails, ask whether the graph was wrong, the schedule was unsafe, or both.
A DAG cannot answer the second question by itself. It does not know that the browser pool has two open slots, the process has six gigabytes of available memory, or the upstream service has four quota units left in the current window.
Give each call a demand vector
A single concurrency limit hides the bottleneck.
Suppose a runtime permits five concurrent calls. That limit says nothing about whether those five calls each need a browser, whether one consumes most of the memory budget, or whether three hit the same constrained API. A batch can stay under the call-count limit and still overflow a shared resource.
For a production runtime, attach an estimated demand vector to each eligible call. The dimensions should match the resources that actually constrain the system. Depending on the tools, that might include:
- browser slots
- memory
- CPU
- worker or connection-pool slots
- API quota
- accelerator capacity
PeakBench uses a measured five-dimensional resource vector in its benchmark. These production dimensions are a practical extension of the benchmark, not part of its measured model.
Here is a small illustrative budget:
| Call | Browser slots | Memory | API quota units |
|---|---|---|---|
| A: browser audit | 1 | 2.5 GB | 1 |
| B: page screenshot | 1 | 2.0 GB | 1 |
| C: API crawl | 0 | 2.0 GB | 3 |
| Available | 2 | 6.0 GB | 4 |
The graph makes A, B, and C eligible together. Their combined demand is two browser slots, 6.5 GB of memory, and five quota units. The batch fits the browser pool but exceeds memory by 0.5 GB and API quota by one unit.
No dependency edge can reveal that conflict. The scheduler needs a resource ledger.
These declarations are estimates, not physical enforcement, a distinction also made in Ray's resource model. Inputs vary. Tool versions change. Other work creates contention. A runtime should compare estimated demand with observed use and recalibrate rather than treating yesterday's profile as permanent truth.
Admit what fits; defer what does not
Let E be the set of dependency-eligible calls, B the currently available resource budget, and d(i) the estimated demand vector for call i.
Choose an admitted subset A such that:
A is a subset of E
sum(d(i) for i in A) <= B, component by component
That rule defines feasibility. It does not prescribe one universal selection policy. A runtime may choose among fitting subsets based on priority, latency, fairness, cost, or another explicit objective. The Kubernetes scheduler uses a related filter-then-score structure; that is a supporting example, not the source of this controller.
For the example above, the controller can run this loop:
- Validate that A, B, and C have no blocking prerequisite edges.
- Read the current available budget.
- Test aggregate demand against that budget.
- Admit A and B, whose combined demand is two browser slots, 4.5 GB of memory, and two quota units.
- Account for that capacity while A and B run.
- Defer C without marking it failed.
- When A finishes, release its accounted capacity.
- Reconsider C. Running B and C together now requires one browser slot, 4 GB of memory, and four quota units, so the pair fits.
Deferral is not failure. It is how the runtime preserves useful parallelism without pretending capacity is infinite.
The accounting operation also needs to be atomic enough that two schedulers cannot both admit work against the same remaining budget. But accounting is not isolation: a call can consume more than declared. The runtime still needs hard limits where overruns would be dangerous, plus telemetry that records estimate error.
This loop follows from the planning-versus-scheduling distinction. PeakBench does not validate this exact production controller or show that it is globally optimal.
Score the graph and the schedule separately
If planning and scheduling are different decisions, they need different scorecards.
| Logical validity | Physical safety and efficiency |
|---|---|
| Were prerequisite edges correct? | Did actual demand exceed capacity? |
| Did any call start before its inputs existed? | How often was a start denied or deferred? |
| Did the plan serialize calls that could overlap? | How far did estimates differ from observed use? |
| Was the proposed overlap dependency-safe? | What utilization and latency did the schedule produce? |
A green logical score cannot erase a red physical score. A dependency-correct plan can still overflow memory or quota.
The reverse matters too. A schedule can avoid overflow by serializing everything. That may be safe, but it can hide a timid or incorrect plan and discard the latency benefit that parallel execution was supposed to create.
PeakBench reports a similar benchmark-level tension. Its Resource-Aware Scheduling Context gives models per-invocation profiles and machine capacity while holding the verified workflow structure fixed. The added resource information usually improved schedules in the benchmark, but not uniformly: some evaluated models worsened on capacity violation or strict utilization. Resource visibility creates the opportunity for a better schedule; it does not guarantee one.
For operators, the useful outcome is attribution. When latency rises, capacity overflows, or utilization falls, separate the cause:
- The dependency model was wrong.
- The demand estimate was wrong.
- The admission policy made a poor choice.
- Available capacity changed after the decision.
- The tool consumed more than its declaration.
Without that separation, every incident gets flattened into “parallel calls are unreliable,” which is too vague to fix.
What the preprint supports—and what it does not
PeakBench supports treating dependency planning and finite-capacity scheduling as separate evaluation dimensions. Within its benchmark, resource-aware context usually improved scheduling tradeoffs, but results remained model-dependent, and the workflows were designed to stress these capabilities rather than reproduce real-user traffic.
The production model here goes beyond that evidence. Estimates can go stale, deferred work can starve, and capacity can change between admission and launch. A real controller needs explicit policies for those cases and must earn confidence under its own workload.
The operator rule
The graph says what may overlap.
The budget says what starts now.
Telemetry updates what the runtime believes next time.
Parallel tool calling is not a boolean feature. It is a controlled admission loop.