跪拜 Guibai
← All articles
Artificial Intelligence

When an LLM Returns Multiple Tool Calls, Parallel Execution Is Not the Default Answer

By 东风破_ ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Agent frameworks that default to `Promise.all()` for all tool calls will silently corrupt state when tools share resources. The scheduling logic belongs in the runtime, not in the model's natural-language reasoning, and getting it wrong produces bugs that are intermittent and hard to reproduce.

Summary

Models return tool call arrays with no awareness of runtime constraints. Parallel execution with `Promise.all()` cuts latency for independent reads like fetching multiple files or API endpoints, but it breaks when calls modify the same resource or depend on side effects from a previous step. Sequential execution inside a `for...of` loop preserves order for writes, CLI workflows, and browser automation, yet it still cannot solve true logical dependencies where a later call's parameters must be regenerated from an earlier result.

The real distinction is between three execution modes: parallel for independent I/O, sequential within a single round to control side effects, and cross-round loops where the model sees a ToolMessage and re-plans. A runtime that blindly parallelizes everything will produce race conditions on shared files, unpredictable browser states, and corrupted database transactions.

Error handling also differs. Wrapping each tool invocation in try/catch and returning error strings keeps `Promise.all()` from failing fast, giving the model a complete result array with both successes and failures to reason about in the next turn.

Takeaways
`Promise.all()` preserves input order in the result array regardless of which promise resolves first, so index-based mapping back to `tool_call_id` is reliable.
A single rejected promise causes standard `Promise.all()` to immediately reject, but catching errors inside each tool and returning error strings prevents this fail-fast behavior.
Sequential execution with `for...of + await` guarantees side-effect order within one round but does not let the model regenerate parameters for later calls based on earlier results.
Tasks that truly depend on a previous step's output — like clicking an element only visible after a page snapshot — must be split across multiple Agent rounds, not just sequential calls in one round.
Writing to the same file, browser clicks, multi-step CLI commands, and shared database mutations all create race conditions under parallel execution.
Even for independent calls, unbounded `Promise.all()` can exhaust API rate limits or file handles; production systems need a concurrency cap.
The runtime, not the LLM, should decide execution strategy by checking whether calls share resources, depend on return values, or hit external rate limits.
Conclusions

The core confusion in Agent tool execution is conflating two different kinds of 'order': the temporal order of side effects within a single turn, and the logical order of re-planning across turns. Sequential execution only solves the first.

Error handling design changes the entire execution model. Catching errors per-tool and returning strings instead of throwing turns `Promise.all()` from a brittle fail-fast mechanism into a resilient batch processor that surfaces partial failures to the model.

The article's decision table — parallel for independent reads, sequential for shared state, cross-round for true dependencies — is a minimal viable runtime policy that most Agent frameworks still lack.

Concepts & terms
Tool Call
A structured object in an LLM response specifying which tool to invoke and with what arguments, containing an id, name, and args. Multiple tool calls can appear in a single AIMessage.
Agent Loop
A cycle where the model generates tool calls, the runtime executes them, results are fed back as ToolMessages, and the model generates the next response. Multiple loops handle tasks that depend on intermediate results.
Race Condition
A bug where two asynchronous operations access shared state and the final outcome depends on which finishes last. Parallel tool calls writing to the same file or database record are a common source in Agent systems.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗