Repository navigation
[xAI/Grok Responses] V2 child result agent_message causes parent HTTP 422 #3907
Description
Client or integration
Codex App
Provider or upstream service
xAI OAuth / Grok 4.6
OpenCodex version
2.46.0 (also reproduced on 2.43.0)
Endpoint or capability
POST /v1/responses, MultiAgentV2, routed-parent child-result delivery
Current behaviour
A Codex App task using xai/grok-4.6 as the V2 parent can spawn and run xai/grok-4.6 children successfully. The failure begins when the first child completes and Codex appends the child result to the parent history as a plaintext agent_message input item.
The next parent request is routed correctly to xAI/Grok, but the strict Responses endpoint rejects the whole request with HTTP 422 because agent_message is not in its accepted input-item union. Codex retries the same incompatible request and the parent turn ends in systemError.
This reproduced twice on Ubuntu 24.04 with Codex CLI/App Server 0.153.4:
- OpenCodex 2.43.0: first returned child result was followed immediately by repeated 422 errors at
input[134]. - OpenCodex 2.46.0: 248 requests completed with HTTP 200; the first child then completed, one plaintext
agent_messagewas recorded in the parent rollout, and six consecutive parent requests failed with HTTP 422 atinput[69].
The child itself completed normally. The failure boundary is child-result delivery to the routed parent, not child creation, model routing, rate limiting, or encrypted NEW_TASK delivery.
As a control, the same workload on the V1 surface did not emit this agent_message failure and did not produce the 422 class.
Expected behaviour
For a translated/strict xAI Responses destination, OpenCodex should lower a complete readable plaintext Codex agent_message into a wire-safe ordinary user message before dispatch, so the routed parent can consume the child result and continue orchestration.
Encrypted-only or malformed agent messages should remain fail-closed. Native ChatGPT passthrough, genuine tool-result items, and unrelated Responses input types should remain unchanged.
Minimal redacted request or reproduction
# Configuration shape
# - OpenCodex 2.46.0
# - Codex 0.153.4
# - multiAgentMode: v2
# - xAI OAuth provider
# - parent model: xai/grok-4.6
# - child models: xai/grok-4.6
1. Start a fresh Codex App task on xai/grok-4.6 with the V2 collaboration surface.
2. Ask the parent to spawn multiple xai/grok-4.6 workers, wait for them, and aggregate their returned results.
3. Observe that child requests execute successfully.
4. Wait for the first child to complete.
5. Confirm that the parent rollout receives an item shaped as:
{
"type": "agent_message",
"id": "amsg_<redacted>",
"author": "/root/<redacted-worker>",
"recipient": "/root",
"content": "<non-empty plaintext child result>"
}
6. The immediately following parent request to /v1/responses returns HTTP 422.The production reproduction used ten workers, but the first completed worker was sufficient to trigger the failure; no 422 occurred before the first agent_message arrived.
Actual response or error
unexpected status 422 Unprocessable Entity: {
"error": "Failed to deserialize the JSON body into the target type: input[69]: unknown item type \"agent_message\"; expected one of: message, reasoning, function_call, function_call_output, shell_call, shell_call_output, web_search_call, file_search_call, code_interpreter_call, mcp_call, custom_tool_call, image_generation_call, compaction"
}, url: http://127.0.0.1:10100/v1/responsesThe earlier 2.43.0 reproduction reported the same error at input[134].
Upstream documentation
xAI documents ordinary Responses inputs and tool-result continuation using message and function_call_output; it does not document Codex-private agent_message items:
- https://docs.x.ai/developers/tools/function-calling
- https://docs.x.ai/developers/model-capabilities/text/comparison
There is no public xAI specification for Codex App's private inter-agent input envelope. The expected behaviour is based on the concrete Codex client requirement that a routed parent receive a completed child's plaintext result.
Suggested mapping or implementation notes
This appears similar in failure class to #3838, where a strict translated Responses endpoint rejects Codex-private agent_message items and a provider-scoped lowering converts readable content to a user message.
Suggested narrow boundary:
- Apply only on translated/strict xAI Responses dispatch, not canonical ChatGPT forwarding.
- Recognize only a structurally complete plaintext
agent_messagewith representable content. - Convert the readable content to an ordinary user
message, optionally retaining non-sensitive author/recipient attribution in text. - Keep encrypted-only, empty, or malformed items fail-closed.
- Add a regression covering routed Grok parent -> routed Grok child -> child completion -> parent continuation.
The existing common parser already maps agent_message to a user-role context message, but the observed xAI Responses outbound request still carries the raw private item, suggesting the passthrough/raw-body lane bypasses that parsed representation.
Additional context and attachments
Related but distinct:
- fix(opencode-go): lower Codex-private input items Console Go rejects #3838: provider-specific lowering of Codex-private
agent_messageitems for another strict Responses endpoint. - [Responses] Codex task-input envelopes are rejected by translated adapters #3735: external Codex task-input envelope lowering for translated adapters.
- [Bug] V2 custom-parent → custom-child delegation needs current-dev trace #418: routed/custom parent-to-child V2 completion tracing.
- V2 cross-provider sub-agent loses NEW_TASK body in encrypted_content #92: native-parent to routed-child encrypted
NEW_TASK; this report is the opposite direction and the returned child result is readable plaintext.
No research content, filesystem paths, credentials, account identifiers, request authorization, full child output, or unredacted payloads are included.
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
lidge-jun commentedon Sep 7, 2026
리뷰 · 우선순위 72 / 80
이 이슈는 MultiAgentV2에서 부모·자식 모두 xAI/Grok Responses일 때, 자식이 정상 끝난 뒤 부모가 자식 결과를 이어받지 못하는 버그입니다. Codex App은 자식 완료 결과를 부모 history에 Codex 전용
agent_message아이템으로 붙입니다. 그런데 xAI 쪽 Responses는 입력 union이 매우 빡세서message,reasoning,function_call,function_call_output같은 공개 타입만 받고,agent_message는 "unknown item type"으로 HTTP 422를 냅니다. 자식 요청 자체는 200으로 잘 끝나고, 깨지는 지점은 자식 결과 → 라우팅된 부모 다음 턴뿐입니다. V1 표면에서는 이agent_message실패가 안 났다는 제어 실험도 있으니, V2 협업 레인과 직결됩니다.현재
dev(2.47.0, HEADf802f711) 기준으로 보면, 비슷한 실패 등급은 이미 OpenCode Go 쪽에만 좁게 고쳐져 있습니다.src/adapters/opencode-go.ts의normalizeOpenCodeGoAgentMessages는 plaintextagent_message를 일반 usermessage로 낮추고, encrypted/빈/이상한 content는 그대로 둡니다. 그런데src/adapters/openai-responses.ts에서 이 함수를 호출하는 조건은!forward && isOpenCodeGo(provider.baseUrl)한 줄뿐입니다. xAI 목적지는src/providers/xai-transport.ts의isXaiResponsesDestination(api.x.ai / cli-chat-proxy.grok.com)으로 따로 인식되지만, 같은 낮추기 단계가 xAI 레인에는 연결되어 있지 않습니다.경로·심볼로 오늘 코드가 하는 일과 구멍은 이렇게 정리됩니다.
src/responses/parser.ts—agent_message를 파싱할 때 user-role context로 넣습니다. 번역 어댑터용 “읽기” 쪽은 이미 알고 있습니다.src/adapters/openai-responses.ts— 실제 와이어는parsed._rawBody에서 출발합니다. Go 전용 낮추기만 있고, xAI에는 없습니다.stripInvalidItemIds는 오히려agent_message/amsg_prefix를 유지합니다.src/adapters/opencode-go.ts— fix(opencode-go): lower Codex-private input items Console Go rejects #3838 계열의 참고 구현. plaintext content part(input_text/input_image/input_file)만 message로 바꿉니다. 이슈 재현 JSON은content가 문자열인 형태로도 보이므로, xAI 포트 시 문자열·파트 배열 둘 다 확인이 필요합니다.src/server/grok-responses-control-frame.ts/ fix(grok): preserve strict Responses event framing #3831 — Grok 응답 SSE에서 Codex 전용 control frame을 가리는 축입니다. 입력agent_message422와는 다른 레이어지만, “Grok strict Responses”라는 같은 엄격성 축입니다.src/server/responses/agent-task-recovery.ts,encrypted-payload.ts,core.ts의AGENT_MESSAGE_TYPE— encrypted/task recovery·spawn 호환 스택이agent_message를 계속 다룹니다. 이번 보고는 읽기 가능한 plaintext 자식 결과이므로, encrypted-only fail-closed 규칙은 유지한 채 wire 낮추기만 추가하는 편이 맞습니다.메인테이너의 판단이 필요한 지점
normalizeOpenCodeGoAgentMessages를 xAI에도 재사용할지,isXaiResponsesDestination가드의 별도 함수로 둘지.contentvs 기존 Go 헬퍼의 part-array 가정 — 실제 Codex 0.153.4 rollout 형태를 한 번 더 고정할지.너의 추천
우선순위 높게 잡고, xAI Responses outbound에만 plaintext
agent_message→ usermessage낮추기를 붙이세요.openai-responses.ts의 Go 호출 옆에isXaiResponsesDestination(provider)분기를 두거나, 공통 헬퍼로 빼서 Go/xAI가 같은 규칙을 쓰게 하면 됩니다. encrypted·empty·malformed는 지금처럼 fail-closed, forward(ChatGPT)는 스킵. 회귀 테스트는routed Grok parent → routed Grok child → child 완료 → parent 재요청에서 outboundinput에type:"agent_message"가 남지 않고 422가 안 나는지까지 한 시나리오로 고정하세요. MultiAgentV2 + Grok이 사실상 첫 자식 완료 순간부터 막히므로, lane D나 Anthropic residual(#3719)보다 이 버그 먼저 닫는 편이 사용자 체감이 큽니다.이 댓글은 grok-bot이 작성했습니다
lidge-jun commentedon Sep 8, 2026
Landed via #3991 at 7730f66
xAI string-valued child
agent_messagecontinuation is ondev(allowStringContentpath in routed-agent-messages + exact xAI destination guard). Closing as completed.이 댓글은 grok-bot이 작성했습니다
fix(xai): lower plaintext string child-result messages
fix(xai): lower plaintext string child-result messages