Tool call streaming broken in 0.64.0 with local LLM providers
Summary
Codex 0.64.0 fails to parse streaming tool calls from local LLM providers (LM Studio, etc.), treating each character/chunk of the tool call arguments as a separate tool call instead of accumulating them into a single call.
Environment
- Codex version: 0.64.0 (broken), 0.63.0 (working)
- LLM Provider: Local provider using OpenAI-compatible API (localhost:5002/v1)
- Model: GPT-OSS-120B
- OS: macOS
- Installation: npm via nvm
Expected Behavior
Tool calls should be accumulated from streaming chunks into a single function call with complete arguments:
{
"type": "function_call",
"name": "shell",
"arguments": "{\"command\": [\"bash\", \"-lc\", \"ls -R\"], \"workdir\": \"/Users/.../test\"}",
"call_id": "701601222"
}
Actual Behavior in 0.64.0
Tool calls are fragmented into dozens of separate calls:
- First call has name but empty arguments:
``json``
{"name": "shell", "arguments": "", "call_id": "701601222"}
- Then 40+ separate calls with empty names and single-character arguments:
``json``
{"name": "", "arguments": "{\n", "call_id": "tool-call-1"}
{"name": "", "arguments": " ", "call_id": "tool-call-2"}
{"name": "", "arguments": " \"", "call_id": "tool-call-3"}
{"name": "", "arguments": "command", "call_id": "tool-call-4"}
// ... continues for each character/small chunk
Error Messages
All fragmented tool calls fail with:
- First call:
"failed to parse function arguments: Error(\"EOF while parsing a value\", line: 1, column: 0)" - Subsequent calls:
"unsupported call: "
Steps to Reproduce
- Configure Codex to use local LLM provider with OpenAI-compatible API
- Use any model that supports tool calls
- Ask Codex to perform any task requiring tool calls
- Observe fragmented tool calls in session logs
Analysis
This appears to be a regression in how Codex 0.64.0 handles streaming tool call deltas from OpenAI-compatible /v1/chat/completions endpoints. Instead of accumulating streaming chunks with the same tool call index into a single call, each chunk is being treated as a new, separate tool call.
The issue affects local LLM providers that stream tool call arguments incrementally.
Workaround
Downgrade to Codex 0.63.0:
npm install -g @openai/codex@0.63.0
Additional Context
- Issue does not occur in Codex 0.63.0 with same setup
- Using standard OpenAI-compatible API format
- No configuration changes between working (0.63.0) and broken (0.64.0) versions
- Only the Codex update triggered this issue
14 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Reviewed the potential duplicates:
This issue is specific to Codex 0.64.0 streaming tool call regression where arguments are fragmented into dozens of separate calls instead of being accumulated. Works fine in 0.63.0. Not a duplicate.
Thanks for reporting. This is a duplicate of #7051. As a workaround, try switching to
wire_api = "responses". This newer API is recommended over the older "chat" API.Update: Tried the
wire_api = "responses"workaround suggested, but it doesn't work with local LLM providers like LM Studio.Error with wire_api = "responses":
Root Cause:
The
wire_api = "responses"setting appears to be intended for OpenAI's actual Responses API, not for local LLM providers. LM Studio's/v1/responsesendpoint expects different tool formatting than what Codex sends when using this setting.Current Status:
The streaming fragmentation issue is specific to local LLM providers using the OpenAI-compatible chat completions endpoint and persists in 0.65.0.
This is not the same as #7051 - that issue is about corporate proxies that don't support the responses API. This issue is about local LLM providers where the chat API streaming changed behavior in 0.64.0+.
@latent-variable, could you provide more details about your configuration including the model you're using in LM Studio and your config.toml settings for that model? I'd like to repro what you'd seeing. Thanks!
And yes, I agree this isn't the same as #7501. It may be related to #7579.
@etraut-openai Here are the details:
Model
LM Studio model: openai/gpt-oss-120b (GGUF format)
Configuration
config.tomlsettings:LM Studio Settings
/v1/chat/completionsendpointReproduction
codex "list files in current directory")~/.codex/sessions/The session logs show tool calls split into 40+ fragments with empty names instead of one complete call.
Let me know if you need any other details!
The Chat Completions SSE parser assumes id is present in every tool call delta, falling back to format!("tool-call-{}", tool_call_order.len()) when absent. However, OpenAI's streaming format only includes id in the first
delta—subsequent deltas use index for correlation. This causes each delta to create a new tool call entry instead of accumulating arguments into a single call.
Result: JSON parse failures, corrupted conversation history, and models hanging/erroring on the second turn.
Fix:
Use index field for delta correlation when id is absent:
let id = if let Some(id_str) = provided_id {
// First delta or servers that send id in every delta
id_str.to_string()
} else if let Some(idx) = provided_index {
// Subsequent deltas - look up stored id by index
tool_call_order[idx as usize].clone()
} else {
// Fallback
format!("tool-call-{}", tool_call_order.len())
};
Affected: llama.cpp, LM Studio, and other local providers using standard OpenAI streaming format.
@latent-variable, can you confirm that you're using the latest version of LM Studio? I'm using 0.3.33, and I'm not able to repro the problem you're seeing with the "responses" endpoint. Earlier versions of LM Studio had bugs in its "responses" handling, so I wonder if you're on an older version.
@etraut-openai Yes, I'm using the latest LM Studio version 0.3.33.
@joninco's analysis appears to be correct - the issue is with how Codex's Chat Completions SSE parser handles tool call deltas. The parser creates a new tool call for each delta instead of accumulating them using the
indexfield.To clarify: I'm not using the "responses" endpoint successfully - my earlier comment showed it fails with tool format errors. The issue occurs with the standard chat completions endpoint (
/v1/chat/completions) which LM Studio implements following OpenAI's streaming format (id in first delta, index for correlation in subsequent deltas).Current workaround: Downgrade to Codex 0.63.0, which correctly handles this streaming format.
Additional detail that might help reproduce:
The issue only occurs when tool calls are involved. Simple chat responses work fine.
Works:
Model responds normally without issues.
Fails:
Model attempts to call the Read tool, and that's when the streaming parser fragments the tool call into dozens of separate calls.
So this is specifically a tool call streaming bug, not a general chat streaming issue. The parser only breaks when processing tool_calls in the SSE stream.
We have a fix for the
indexfield issue in the prerelease version0.66.0-alpha.7if you'd like to try it out.I'm trying to repro the problem you reported above with the "responses" endpoint. So far, I'm not seeing tool format errors with the latest version.
Confirmed: 0.66.0-alpha.7 fixes the issue.
Tested with tool calls - no more fragmentation. Session logs show proper tool call accumulation with complete arguments and no parse errors.
Thanks for the quick fix!
We've published
0.66.0, which I believe addresses the issue tracked in this bug report.We're announcing that we plan to deprecate support for the chat/completions API in Codex and eventually remove support completely. For details, please refer to https://github.com/openai/codex/discussions/7782, which provides the rationale and timeline.