Skip to content

[codex] fix claude codex composition semantics#178

Merged
mxyhi merged 1 commit intomainfrom
codex/fix-claude-codex-composition
Mar 18, 2026
Merged

[codex] fix claude codex composition semantics#178
mxyhi merged 1 commit intomainfrom
codex/fix-claude-codex-composition

Conversation

@mxyhi
Copy link
Owner

@mxyhi mxyhi commented Mar 18, 2026

Summary

This PR fixes a composition bug in the Claude-to-Codex request path.

The individual legs already worked:

  • POST /v1/messages -> openai-responses
  • POST /v1/responses -> codex

But the composed path POST /v1/messages -> codex could still misbehave for agentic traffic because the Responses -> Codex adapter was not preserving request semantics.

User impact

For Claude Code style traffic routed through Anthropic -> Responses -> Codex, the proxy could change the meaning of the request before it reached Codex. In practice this meant the composed path was not reliably equivalent to the two working legs above, which made Claude/Codex interoperability fragile in tool-calling flows.

Root cause

The issue was in crates/token_proxy_core/src/proxy/codex_compat/request.rs:

  • parallel_tool_calls was always overwritten to true, even when the upstream conversion had explicitly set it to false
  • function_call_output.output_parts was forwarded to Codex unchanged, even though Codex only needs the flattened output string for this request shape

This made the adapter non-compositional: the intermediate Anthropic -> Responses conversion produced one semantic payload, and the subsequent Responses -> Codex conversion changed that payload again.

Fix

This PR makes the Responses -> Codex adapter preserve the upstream semantics instead of overriding them:

  • only default parallel_tool_calls to true when the field is absent
  • strip output_parts from function_call_output items before forwarding to Codex

The change is intentionally narrow and only affects the Responses -> Codex request path.

Tests

Added focused regression tests for the exact broken behavior:

  • responses_request_to_codex_preserves_parallel_tool_calls_false
  • responses_request_to_codex_strips_output_parts_from_function_call_output

Validated with:

  • cargo test -p token_proxy_core responses_request_to_codex_preserves_parallel_tool_calls_false -- --nocapture
  • cargo test -p token_proxy_core responses_request_to_codex_strips_output_parts_from_function_call_output -- --nocapture
  • cargo test -p token_proxy_core anthropic_messages_request_routes_to_codex -- --nocapture
  • cargo test -p token_proxy_core anthropic_messages_request_falls_back_from_responses_to_codex -- --nocapture
  • cargo fmt --all
  • cargo test -p token_proxy_core

Preserve explicit parallel_tool_calls values and strip output_parts from function_call_output before forwarding Responses payloads to Codex. This keeps the Claude /v1/messages -> Responses -> Codex composition aligned with the working individual legs and locks the regression with focused tests.

Co-authored-by: Codex <noreply@openai.com>
@mxyhi mxyhi marked this pull request as ready for review March 18, 2026 06:03
@mxyhi mxyhi merged commit 2eecf12 into main Mar 18, 2026
1 check passed
@mxyhi mxyhi deleted the codex/fix-claude-codex-composition branch March 18, 2026 06:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant