Client or integration
Codex App
Provider or upstream service
xai
OpenCodex version
2.57.0
Endpoint or capability
/v1/responses tool history replay
Current behaviour
On Codex Desktop through OpenCodex, xai/grok-4.6 OAuth uses the native Responses wire (modelWireDefaults, xaiResponsesDefaultVersion: 1). The first failed tool turn in a thread is often an upstream 502 / connection-reset (commonly around 15s). After that, later turns in the same thread fail much more often, while neighboring healthy threads on the same machine keep returning 200.
Local usage log (redacted counts, OpenCodex 2.57.0):
- google-antigravity: about 1.06% failed requests
- xAI grok-4.6: about 3.3-3.9% failed requests, including 200 HTTP 502 and 150 connection-reset events, with a cluster near 15s
- After the first failure in a thread, the next 10 requests in that thread fail about 20.6% of the time
- Threads that never fail stay clean (one sampled healthy thread: 37/37 and 4529/4529 successes)
Google already synthesizes a missing tool_result ([missing tool_result for this tool_use in history], #2199). xAI Responses does not. Codex can therefore replay a function_call / custom_tool_call with no matching output, or with hook-injected developer context between the pair. The existing repair (normalizeResponsesToolResultAdjacency + orphan-call placeholder) is gated on requiresAdjacentResponsesToolResults / statelessResponses. DeepSeek and Kimi seed that capability; xAI does not. xAI also cannot be marked statelessResponses: the public Responses API stores conversations for 30 days and documents previous_response_id.
This is distinct from the 15s upstream reset itself. Adjacency repair cannot stop the first 502; it stops the dirty history from 400ing every later turn.
Expected behaviour
xAI should get the same Responses tool-history repair as Kimi (#4726) and DeepSeek (#1292): seed requiresAdjacentResponsesToolResults: true, reorder an unambiguous call/result batch around hook-injected context, and synthesize an honest placeholder function_call_output when a call has no recorded result. Do not set statelessResponses (would strip store / previous_response_id). Forward-auth replay should stay fail-closed and not synthesize.
Minimal redacted request or reproduction
Codex App -> local OpenCodex proxy -> xai/grok-4.6 OAuth Responses. Run a long tool-using thread until an upstream 502 / connection-reset, then continue the same thread.
Equivalent replay body the proxy currently forwards after an interrupted tool turn (redacted):
{
"model": "grok-4.6",
"stream": true,
"input": [
{ "type": "message", "role": "user", "content": [{ "type": "input_text", "text": "continue the task" }] },
{ "type": "function_call", "call_id": "call_interrupted", "name": "exec_command", "arguments": "{}" },
{ "type": "message", "role": "developer", "content": [{ "type": "input_text", "text": "[hook] LSP diagnostics: none" }] },
{ "type": "function_call_output", "call_id": "call_other", "output": "ok" }
]
}
Actual response or error
HTTP 502 / connection-reset on the first interrupted tool turn (often ~15s).
Later turns in the same thread then 400 or fail closed because the replayed input still contains
a function_call with no matching function_call_output, or a hook-injected developer message
between the call and its result.
Upstream documentation
Suggested mapping or implementation notes
Seed requiresAdjacentResponsesToolResults: true on the xai registry entry. Keep statelessResponses unset. In src/adapters/openai-responses/passthrough.ts, run the existing repairOrphanedInputItems(..., synthesizeMissingCallOutputs) for non-forward adjacency providers, not only for statelessResponses. Cursor is a separate protobuf adapter and should stay out of this change.
Additional context and attachments
Related: #2199, #4726, #1292, #2156, #3384, #186, #4191, #4808, #3506. Cursor 429 / empty-spin is a different adapter; not requested here. The 15s connection-reset cluster is an upstream cut-off and should stay a separate issue.
Checks
Client or integration
Codex App
Provider or upstream service
xai
OpenCodex version
2.57.0
Endpoint or capability
/v1/responses tool history replay
Current behaviour
On Codex Desktop through OpenCodex,
xai/grok-4.6OAuth uses the native Responses wire (modelWireDefaults,xaiResponsesDefaultVersion: 1). The first failed tool turn in a thread is often an upstream 502 / connection-reset (commonly around 15s). After that, later turns in the same thread fail much more often, while neighboring healthy threads on the same machine keep returning 200.Local usage log (redacted counts, OpenCodex 2.57.0):
Google already synthesizes a missing
tool_result([missing tool_result for this tool_use in history], #2199). xAI Responses does not. Codex can therefore replay afunction_call/custom_tool_callwith no matching output, or with hook-injected developer context between the pair. The existing repair (normalizeResponsesToolResultAdjacency+ orphan-call placeholder) is gated onrequiresAdjacentResponsesToolResults/statelessResponses. DeepSeek and Kimi seed that capability; xAI does not. xAI also cannot be markedstatelessResponses: the public Responses API stores conversations for 30 days and documentsprevious_response_id.This is distinct from the 15s upstream reset itself. Adjacency repair cannot stop the first 502; it stops the dirty history from 400ing every later turn.
Expected behaviour
xAI should get the same Responses tool-history repair as Kimi (#4726) and DeepSeek (#1292): seed
requiresAdjacentResponsesToolResults: true, reorder an unambiguous call/result batch around hook-injected context, and synthesize an honest placeholderfunction_call_outputwhen a call has no recorded result. Do not setstatelessResponses(would stripstore/previous_response_id). Forward-auth replay should stay fail-closed and not synthesize.Minimal redacted request or reproduction
Codex App -> local OpenCodex proxy ->
xai/grok-4.6OAuth Responses. Run a long tool-using thread until an upstream 502 / connection-reset, then continue the same thread.Equivalent replay body the proxy currently forwards after an interrupted tool turn (redacted):
{ "model": "grok-4.6", "stream": true, "input": [ { "type": "message", "role": "user", "content": [{ "type": "input_text", "text": "continue the task" }] }, { "type": "function_call", "call_id": "call_interrupted", "name": "exec_command", "arguments": "{}" }, { "type": "message", "role": "developer", "content": [{ "type": "input_text", "text": "[hook] LSP diagnostics: none" }] }, { "type": "function_call_output", "call_id": "call_other", "output": "ok" } ] }Actual response or error
Upstream documentation
storedefaults true;previous_response_idcontinues a stored conversation)Suggested mapping or implementation notes
Seed
requiresAdjacentResponsesToolResults: trueon thexairegistry entry. KeepstatelessResponsesunset. Insrc/adapters/openai-responses/passthrough.ts, run the existingrepairOrphanedInputItems(..., synthesizeMissingCallOutputs)for non-forward adjacency providers, not only forstatelessResponses. Cursor is a separate protobuf adapter and should stay out of this change.Additional context and attachments
Related: #2199, #4726, #1292, #2156, #3384, #186, #4191, #4808, #3506. Cursor 429 / empty-spin is a different adapter; not requested here. The 15s connection-reset cluster is an upstream cut-off and should stay a separate issue.
Checks