Skip to content

[Provider compatibility] xAI Responses: interrupted tool-call history snowballs because adjacency repair is not seeded #4870

Closed

Description

@MerryEcho

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

  • I searched existing provider and compatibility issues.
  • The request and response were redacted.
  • The expected behaviour is based on an upstream specification or a concrete client requirement.

Activity

  1. added
    account-poolOAuth, credentials, Codex pool, quota, failover, plans
    providerProvider adapters, OpenAI-compat presets, upstream API quirks
    toolstool_calls, MCP, web-search / sidecar tools
    on Sep 17, 2026
  2. Ingwannu commented on Sep 17, 2026

    @Ingwannu
    Owner

    Confirmed on current dev (7868f5df5). The xAI registry does not currently seed requiresAdjacentResponsesToolResults, and the Responses adapter only synthesizes a missing call output for forward/stateless routes. xAI is stateful, so marking it stateless would be incorrect; the narrow fix is the one proposed here: seed the existing adjacency capability and let non-forward adjacency providers reuse orphan-call repair without stripping store or previous_response_id.

    Draft PR #4871 implements that boundary and covers stale-registry backfill, missing-output synthesis, hook-split pair reordering, multi-call pairing, and the forward-auth fail-closed control. This can prevent an interrupted turn from poisoning later replays, but it does not claim to fix the original upstream 502/reset. Keeping the issue open until #4871 is ready, exact-head CI is complete, and a maintainer approves the current head.

  3. added a commit that references this issue on Sep 17, 2026
    7c8e961
  4. lidge-jun commented on Sep 17, 2026

    @lidge-jun
    Owner

    리뷰 · 우선순위 28 / 80

    이 이슈는 xAI Responses 네이티브 와이어에서 끊긴 tool-call 히스토리에 adjacency repair 시드가 없어, 같은 스레드가 첫 실패 이후 연쇄로 502/connection-reset에 가깝게 깨진다는 보고다. Google은 이미 missing tool_result를 심고(#2199), xAI는 안 심었다는 대비가 본문 핵심이다.

    현재 tip 41f1832(package 2.58.0)에는 이미 #4871 fix(xai): seed Responses tool-result adjacency for interrupted Codex threads (7c8e961)가 있다. 레지스트리 xAI 쪽 requiresAdjacentResponsesToolResults: true와 openai-responses passthrough의 adjacency 경로가 tip에 존재한다. 본문이 요구한 시드는 랜딩된 상태다.

    이슈가 아직 open인 것은 자동 종결 누락으로 보인다. 보고 버전 2.57.0 → tip 2.58.0+#4871. tip에서 xai/grok-4.6 OAuth로 "첫 실패 후 같은 스레드"를 한 번 더 보고 싶으면 smoke만 하고, 새 증상은 새 이슈로 연다.

    경로/심볼 - 7c8e961 / #4871: tip 랜딩. interrupted Codex thread tool_result adjacency 시드
    경로/심볼 - src/providers/registry/entries-core.ts requiresAdjacentResponsesToolResults (xAI 등)
    경로/심볼 - src/adapters/openai-responses/passthrough.ts adjacentToolResults / adjacency 정규화
    경로/심볼 - #2199: Google missing tool_result 선행. 이 이슈는 xAI 대칭

    메인테이너의 판단이 필요한 지점

    • tip에서 xai/grok-4.6 OAuth smoke가 필요한지, 바로 close할지
    • Closes 키워드가 이슈를 안 닫았으면 수동 close 멘트를 넣을지

    너의 추천
    Fixed by #4871 (7c8e961) on dev @41f1832f6 로 close. 재발 시 새 이슈에 tip SHA와 usage 비율만 붙인다. 라벨은 바꾸지 않는다.

    이 댓글은 grok-bot이 작성했습니다

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    account-poolOAuth, credentials, Codex pool, quota, failover, plansproviderProvider adapters, OpenAI-compat presets, upstream API quirksprovider-compatibilityProvider compatibility reportstoolstool_calls, MCP, web-search / sidecar tools

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions