[BUG] Subagents execute independent tool calls sequentially even when explicitly instructed to batch — including fork mode with identical system prompt
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
When a subagent (spawned via the Agent/Task tool) is given multiple independent, non-dependent tool calls — e.g. reading 3 unrelated files — it always executes them sequentially: one tool_use, wait for its tool_result, then the next tool_use. It never batches them into a single assistant turn the way the main/orchestrator conversation does.
This holds regardless of:
- Model (tested Sonnet 5, Opus, and Haiku as subagent model overrides — identical sequential pattern for all three)
- Prompting strength (tested no special prompting, weak prose prompting, and Anthropic's own documented strong
<use_parallel_tool_calls>system-prompt snippet from https://platform.claude.com/docs/en/agents-and-tools/tool-use/parallel-tool-use) - Subagent kind: built-in
general-purpose, a custom subagent defined in.claude/agents/with the parallel-call instructions baked directly into its own frontmatter system prompt, and aforksubagent (CLAUDE_CODE_FORK_SUBAGENT=1) — which per the docs inherits the exact same system prompt, tools, and model as the main session — all produced the same sequential pattern.
This has a real token-cost impact, not just a latency one. Each sequential tool call is a separate API round trip, and each round trip resends the entire accumulated conversation so far as input (served from cache when caching works, but still billed and still latency). Batching N independent reads into one turn costs roughly one round trip's worth of input tokens; doing them sequentially costs N round trips, each re-sending a slightly larger context than the last — so total input/cache-read token consumption scales much worse than linearly with file count.
Separately, and possibly worth its own report: subagents' self-reported summaries of "did you batch the calls" are unreliable. Several subagents, including the fork, explicitly claimed to have issued all tool calls "in parallel, in one batch" when the raw transcript JSONL clearly showed sequential, alternating execution (tool_use → tool_result → tool_use → tool_result → ...). This makes the underlying behavior easy to miss without inspecting the transcript file directly.
By contrast, the main/orchestrator conversation reliably batches independent tool calls in the same session: multiple Read calls issued in one response appear as multiple tool_use blocks sharing the same message.id, followed by their tool_results together. No subagent variant tested reproduces this, including the fork, which should behave identically to the main conversation per its documented inheritance of the exact same system prompt/tools/model.
What Should Happen?
Subagents should be able to batch independent, parallelizable tool calls into a single assistant turn, the same way the main conversation does — at minimum when explicitly instructed via the documented <use_parallel_tool_calls> system-prompt pattern.
A fork subagent in particular should exhibit the same tool-call-batching behavior as the main session, since it is documented to inherit the identical system prompt, tools, and model — it currently does not.
Additionally, a subagent's final report should not claim it batched tool calls in parallel when the execution transcript shows it did not.
Error Messages/Logs
Steps to Reproduce
- In a Claude Code session, ask the main conversation to read 3 independent files directly. Confirm in
~/.claude/projects/<project>/<session>.jsonlthat the 3Readtool_use blocks share onemessage.idand appear consecutively before theirtool_results (the parallel signature).
- Spawn a subagent (Agent tool,
subagent_type: general-purpose) and ask it to read the same 3 files, explicitly instructing it to issue all 3 Read calls together in its first response, e.g.:
"Read these three files: a.md, b.md, c.md. Issue all three Read tool calls together in your very first response, before waiting for any tool result to come back."
- Inspect that subagent's transcript at
~/.claude/projects/<project>/<session>/subagents/agent-<agentId>.jsonl. Result:tool_use → tool_result → tool_use → tool_result → tool_use → tool_result, strictly alternating — sequential, not parallel.
- Repeat step 2-3 with the model overridden to
haikuand toopus. Identical sequential pattern in both.
- Repeat with a custom subagent defined in
.claude/agents/my-agent.mdwith this frontmatter body instead of a task-level instruction:
<use_parallel_tool_calls>
For maximum efficiency, whenever you perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially. Prioritize calling tools in parallel whenever possible...
</use_parallel_tool_calls>
```
Still sequential.
- Set CLAUDE_CODE_FORK_SUBAGENT=1 (e.g. in .claude/settings.local.json under "env"), restart, then spawn subagent_type: "fork" with the same 3-file task. The fork's own final report claims it batched all 3 calls — but its transcript at agent-<agentId>.jsonl still shows the same alternating sequential pattern, contradicting its self-report.
Note: the bug is about execution structure, not the reported result — the files are read correctly and all output is correct, only the batching behavior is wrong.
Claude Model
Not sure / Multiple models
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.220
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
WSL (Windows Subsystem for Linux)
Additional Information
_No response_
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗