Confirm this is an issue with the Python library and not an underlying OpenAI API
Describe the bug
accumulate_delta (https://github.com/openai/openai-python/blob/main/src/openai/lib/streaming/_deltas.py#L6) appears to assume that an indexed list entry’s "index" field matches its physical position in the Python list, and ignore the index entry.
This breaks when the first streamed chunk contains multiple tool_calls entries with the same index.
Example first chunk:
{
"delta": {
"tool_calls": [
{
"index": 0,
"id": "functions.list_files:0",
"function": { "name": "list_files" },
"type": "function"
},
{
"index": 0,
"function": { "arguments": " {\"" }
}
]
},
"index": 0
}
Because this is the first tool_calls value, the accumulator stores the list directly:
if key not in acc:
acc[key] = delta_value
continue
So the accumulated snapshot now contains two physical list entries with index: 0.
Later chunks like this:
{
"delta": {
"tool_calls": [
{
"index": 0,
"function": { "arguments": "path\": \".\"}" }
}
]
}
}
are merged into acc_value[0], while the second duplicate index: 0 entry remains separate. This strands part of the tool call arguments and produce invalid final JSON. Ending up with:
[
{
"index": 0,
"id": "functions.list_files:0",
"type": "function",
"function": {
"name": "list_files",
"arguments": "path\": \".\"} "
}
},
{
"index": 0,
"function": {
"arguments": " {\""
}
}
]
Expected behavior
List entries with an "index" field should be merged by logical index, not by physical list position.
The two index: 0 entries in the first chunk should accumulate into one tool call:
[
{
"index": 0,
"id": "functions.list_files:0",
"type": "function",
"function": {
"name": "list_files",
"arguments": " {\"path\": \".\"}"
}
}
]
Note that this is not a problem with the OpenAI's Go SDK because it uses the index directly.
To Reproduce
I ran basic tool calling with Kimi 2.6 using speculative decoding using vLLM OpenAI compatible server, and this SDK.
https://recipes.vllm.ai/moonshotai/Kimi-K2.6
Code snippets
OS
Arch Linux
Python version
Python 3.14.4
Library version
openai v2.35.0
Confirm this is an issue with the Python library and not an underlying OpenAI API
Describe the bug
accumulate_delta(https://github.com/openai/openai-python/blob/main/src/openai/lib/streaming/_deltas.py#L6) appears to assume that an indexed list entry’s"index"field matches its physical position in the Python list, and ignore the index entry.This breaks when the first streamed chunk contains multiple
tool_callsentries with the sameindex.Example first chunk:
Because this is the first tool_calls value, the accumulator stores the list directly:
So the accumulated snapshot now contains two physical list entries with index: 0.
Later chunks like this:
are merged into acc_value[0], while the second duplicate index: 0 entry remains separate. This strands part of the tool call arguments and produce invalid final JSON. Ending up with:
Expected behavior
List entries with an "index" field should be merged by logical index, not by physical list position.
The two index: 0 entries in the first chunk should accumulate into one tool call:
Note that this is not a problem with the OpenAI's Go SDK because it uses the index directly.
To Reproduce
I ran basic tool calling with Kimi 2.6 using speculative decoding using vLLM OpenAI compatible server, and this SDK.
https://recipes.vllm.ai/moonshotai/Kimi-K2.6
Code snippets
OS
Arch Linux
Python version
Python 3.14.4
Library version
openai v2.35.0