claude-agent-sdk returns tool_result blocks in wrong order for parallel tool calls, causing API 400 errors
Bug Description
When an agent makes parallel tool calls (e.g., calling 3 tools simultaneously: Grep, Glob, Glob), the claude-agent-sdk returns tool_result blocks in a different order than the original tool_use blocks. This causes Claude API to reject the request with a 400 error.
Error Message
API Error: 400 Expected toolResult blocks at messages.X.content for the following Ids:
<tool_use_id_1>, but found: <tool_use_id_3>
Environment
- SDK Version: claude-agent-sdk 0.1.25
- Python Version: 3.11
- Platform: macOS (Darwin 25.2.0)
Root Cause
The SDK returns tool results in the order they complete rather than the order they were requested. Claude API strictly requires tool_result blocks to match the exact order of tool_use blocks as specified in the API documentation.
Reproduction Steps
- Create a
ClaudeSDKClientwith a workspace - Send a query that triggers the agent to call 2+ tools in parallel (e.g., "explore the codebase structure")
- Observe the
tool_resultorder in the response messages doesn't matchtool_useorder - API returns 400 error
Example from Logs
Tool Use Order (Correct)
tool_use_id: tooluse_Gb5TE--nToOsbVVYZ6NXDw (Grep - first)
tool_use_id: tooluse_6XF_ZDjJRC-Bc1kb7df3rg (Glob - second)
tool_use_id: tooluse_ObcxhMsfSqqImPWofLkTng (Glob - third)
Tool Result Order (Incorrect)
tool_result: tooluse_ObcxhMsfSqqImPWofLkTng ❌ (third tool, returned first)
tool_result: tooluse_Gb5TE--nToOsbVVYZ6NXDw ✓ (first tool, returned second)
tool_result: tooluse_6XF_ZDjJRC-Bc1kb7df3rg ✓ (second tool, returned third)
API Error
API Error: 400 Expected toolResult blocks at messages.10.content for the following Ids:
tooluse_Gb5TE--nToOsbVVYZ6NXDw, but found: tooluse_ObcxhMsfSqqImPWofLkTng
Complete Error Logs
<details>
<summary>Full server logs showing the issue</summary>
DEBUG:sse_starlette.sse:chunk: b'event: tool_use\r\ndata: {"name": "Grep", ...}, "tool_use_id": "tooluse_Gb5TE--nToOsbVVYZ6NXDw"}\r\n\r\n'
DEBUG:sse_starlette.sse:chunk: b'event: tool_use\r\ndata: {"name": "Glob", ...}, "tool_use_id": "tooluse_6XF_ZDjJRC-Bc1kb7df3rg"}\r\n\r\n'
DEBUG:sse_starlette.sse:chunk: b'event: tool_use\r\ndata: {"name": "Glob", ...}, "tool_use_id": "tooluse_ObcxhMsfSqqImPWofLkTng"}\r\n\r\n'
DEBUG:sse_starlette.sse:chunk: b'event: tool_result\r\ndata: {"tool_use_id": "tooluse_ObcxhMsfSqqImPWofLkTng", ...}\r\n\r\n'
DEBUG:sse_starlette.sse:chunk: b'event: tool_result\r\ndata: {"tool_use_id": "tooluse_Gb5TE--nToOsbVVYZ6NXDw", ...}\r\n\r\n'
DEBUG:sse_starlette.sse:chunk: b'event: tool_result\r\ndata: {"tool_use_id": "tooluse_6XF_ZDjJRC-Bc1kb7df3rg", ...}\r\n\r\n'
DEBUG:sse_starlette.sse:chunk: b'event: text\r\ndata: {"content": "API Error: 400 Expected toolResult blocks at messages.10.content for the following Ids: tooluse_Gb5TE--nToOsbVVYZ6NXDw, but found: tooluse_ObcxhMsfSqqImPWofLkTng"}\r\n\r\n'
</details>
Expected Behavior
The SDK should maintain and return tool_result blocks in the same order as tool_use blocks, regardless of which tools complete first.
Suggested Fix
The SDK should:
- Track the original order of
tool_useblocks when the assistant makes parallel tool calls - Buffer completed
tool_resultblocks as they arrive - Reorder them to match the
tool_useorder before constructing the user message - Send the properly ordered results to the Claude API
Workaround
None currently available. There's no CLI flag or SDK option to:
- Disable parallel tool execution
- Force sequential tool execution
- Manually control tool result ordering
Impact
This bug makes the SDK unusable for any agent workflows that involve parallel tool calls, which is a common pattern in:
- Code exploration tasks
- File search operations
- Multi-source data gathering
The agent fails with API 400 errors whenever it attempts to optimize performance by calling multiple tools in parallel.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗