AWS Bedrock never emits parallel tool calls
medium · inference · probed live 2026-07-26 · affects AWS Bedrock (Chat Completions), AWS Bedrock (Responses)
parallel_tool_calls: true is accepted on both Bedrock APIs. Only a single call
ever comes back.
What was sent
The two-lookup prompt, Chat Completions lane (download):
{
"model": "google.gemma-4-31b",
"messages": [
{
"role": "user",
"content": "Fetch the access codes for BOTH Paris and Tokyo using `get_code` — you may call it twice in parallel. Then report them exactly as: Paris=<code>, Tokyo=<code>."
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_code",
"description": "Returns the access code for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string"
}
},
"required": [
"city"
]
}
}
}
],
"parallel_tool_calls": true,
"temperature": 0,
"max_tokens": 300
}
The Responses-lane variant (download):
{
"model": "google.gemma-4-31b",
"input": [
{
"role": "user",
"content": "Fetch the access codes for BOTH Paris and Tokyo using `get_code` — you may call it twice in parallel. Then report them exactly as: Paris=<code>, Tokyo=<code>."
}
],
"store": false,
"tools": [
{
"type": "function",
"name": "get_code",
"description": "Returns the access code for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string"
}
},
"required": [
"city"
]
}
}
],
"parallel_tool_calls": true,
"reasoning": {
"effort": "none"
},
"max_output_tokens": 300
}
What came back
Complete, both lanes:
[
{
"id": "call_0",
"type": "function",
"function": { "name": "get_code", "arguments": "{\"city\":\"Paris\"}" }
}
]
One call. Paris only — Tokyo is silently dropped, with empty content and no error. Every other provider returns two calls for the identical prompt: Lightning 2, SambaNova 2, Cerebras 2, Together AI 2, DeepInfra 2, Novita 2, Google 2, Google (OpenAI-compat) 2 — AWS 1, AWS Responses 1.
How this breaks expectations
Every other provider proves the model emits parallel calls for this prompt; Bedrock suppresses the capability at the serving layer while accepting the knob that requests it.
Why it matters
Fan-out agent loops degrade to serial calling at double the turns and latency — and worse than serial: here the model reported on Paris and never asked about Tokyo, silently.
Run it yourself
curl "$BASE_URL/chat/completions" -H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" -d @parallel-calls.chat.json
Two calls back = fixed; one Paris-only call = this finding. The Responses variant POSTs to
$BASE_URL/responses.