Skip to content

[Bug] Responses adapter drops client User-Agent, breaking Codex-specific provider compatibility #4699

Closed

Description

@RailyW

Client or integration

Codex CLI

Provider or upstream service

Volcengine Ark (火山方舟), and other Responses-compatible providers that use the caller's User-Agent to select Codex-specific compatibility handling.

OpenCodex version

Source inspection: dev at cc182a4. The affected user's installed OpenCodex version has not been collected; their upstream log shows Bun/1.4.0.

Endpoint or capability

OpenAI Responses-compatible requests (/v1/responses or the provider's equivalent Responses endpoint).

Current behaviour

OpenCodex drops the original client's User-Agent while building the upstream Responses request. Without an explicit provider header override, a Bun fetch can consequently send its default User-Agent, such as Bun/1.4.0.

Some Responses-compatible providers, including Volcengine Ark in the reported deployment, use User-Agent to recognize Codex requests and enable client-specific compatibility handling. Losing that identity prevents the compatibility handling from being selected and causes requests that depend on it to fail.

The Responses adapter creates a fresh header map. API-key mode adds Content-Type, Authorization, and provider.headers, but does not copy the incoming User-Agent. The OAuth forward-header allowlist also omits User-Agent.

Expected behaviour

Preserve the actual incoming User-Agent on Responses upstream requests when the provider has not explicitly configured a User-Agent. Treat configured header names case-insensitively and keep the provider's explicit override authoritative. If the caller sends no User-Agent, do not invent a Codex identity.

Minimal redacted request or reproduction

  1. Configure an API-key provider using the openai-responses adapter, with no User-Agent in provider.headers.
  2. Send a Codex request through OpenCodex to that provider, carrying the client's normal User-Agent.
  3. Compare the incoming User-Agent with the outgoing header at a controlled upstream receiver.
  4. The incoming identity is absent from the adapter's built request; the Bun transport can supply Bun/ instead.
  5. With an upstream that selects Codex compatibility by User-Agent, observe that the Codex compatibility path is no longer selected.

This can be regression-tested against a local HTTP receiver without provider credentials. A provider-backed reproduction has not yet been run as part of this report.

Actual response or error

Redacted diagnostic evidence supplied by the reporter:

{"upstream_request_headers":{"user_agent":"Bun/1.4.0"}}

The reported consequence is a provider compatibility error. The exact provider status code and response body are not available, so this report does not attribute a specific error payload to Ark.

Upstream documentation

No public specification for Ark's User-Agent-based compatibility selection is supplied with this report; that requirement is based on the reported deployment behavior.

OpenCodex source: https://github.com/lidge-jun/opencodex/blob/cc182a40526a1d87cf5b4b7949fdc6979e70747f/src/adapters/openai-responses/passthrough.ts

Bun documents its default fetch User-Agent: https://bun.sh/docs/runtime/networking/fetch#debugging

Suggested mapping or implementation notes

Copy only the incoming User-Agent as a fallback in the Responses adapter. Preserve explicit provider overrides regardless of header-name casing, without expanding credential or arbitrary-header forwarding. Cover API-key and forward modes, custom overrides, missing UA, and the header actually received over HTTP.

Additional context and attachments

Related: #1751 discussed adding an OpenCodex-specific UA and was declined because providers depend on the upstream client's fingerprint. This report requests preservation of the caller's existing identity rather than a new product identity.

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
    on Sep 15, 2026
  2. Ingwannu commented on Sep 15, 2026

    @Ingwannu
    Owner

    Confirmed on current dev (cc182a405). createResponsesPassthroughAdapter().buildRequest() creates a fresh header record. Key mode adds only content type, bearer auth, and configured headers; canonical forward mode copies the narrow FORWARD_HEADERS set, which also excludes user-agent. With no configured override, the caller identity is therefore absent and Bun may supply its own runtime User-Agent.\n\nI will patch this as a narrow non-credential fallback shared by both Responses auth modes: copy the incoming User-Agent only when it is present and no provider header with that name exists in any casing. A configured provider value remains authoritative, missing caller UA stays missing at the adapter boundary, and no arbitrary request headers are widened. I will cover key mode, canonical forward mode, case-insensitive override precedence, missing UA, and the value observed by a local upstream receiver, then link the exact-head PR here.

  3. Ingwannu commented on Sep 15, 2026

    @Ingwannu
    Owner

    Implemented in #4702 on exact current dev base. The PR preserves only the caller User-Agent fallback, keeps configured provider headers authoritative case-insensitively, and does not widen credential or arbitrary-header forwarding. Focused tests (24), typecheck, structure, privacy, docs build (441 pages), and diff checks passed under isolated temporary homes. @lidge-jun please review before merge; I will not self-approve or self-merge.

  4. lidge-jun commented on Sep 15, 2026

    @lidge-jun
    Owner

    리뷰 · 우선순위 70 / 80

    이 이슈는 Responses 어댑터가 호출자 User-Agent를 버려, UA로 Codex 호환 경로를 고르는 Responses 호환 공급자(보고: Volcengine Ark)가 깨진다는 버그다. 현재 tip 51d577c3f의 src/adapters/openai-responses/passthrough.ts를 확인하면 여전히 그렇다. buildRequest는 새 헤더 맵을 만들고, key 모드는 Content-Type·Bearer·provider.headers만 넣으며, forward 모드는 FORWARD_HEADERS만 복사한다. 그 목록에 user-agent는 없다. 호출자 UA가 없으면 Bun이 Bun/<version>을 실을 수 있다. Ingwannu 확인 댓글·리포터 진단 JSON(user_agent: Bun/1.4.0)과 일치한다. 닫힌 #1751은 OpenCodex 전용 UA 신설을 거절했고, 이번 이슈는 ‘이미 들어온 호출자 지문 보존’이라 Decision Log와 맞다.

    구현 PR이 두 개 열려 있다. #4702(Ingwannu, ready)는 좁은 applyCallerUserAgentFallback만 넣고 이전에 74/80으로 머지 추천했다. #4712(RailyW, draft)는 같은 이슈를 Closes로 걸며 FORWARD_HEADERS 확장·search/vision·문서 산포까지 간다. 본선 수정은 #4702를 살리고, search/vision이 필요하면 그 부분만 #4702에 이식하거나 후속으로 받는 편이 깔끔하다.

    Ark 실계정 재현은 이슈에도 없고, 로컬 수신기 계약으로 고정하는 방향이 두 PR 모두와 맞다. types/config 스플릿·고드파일 모놀리스와 무관하다.

    경로 src/adapters/openai-responses/passthrough.ts FORWARD_HEADERS / buildRequest - tip에 아직 caller UA 폴백 없음.
    경로 #4702 - 좁은 본선 수정, ready, 권장 랜딩 후보.
    경로 #4712 - 중복 draft; search/vision이 유일한 추가 범위.
    경로 #1751 - 제품 UA 신설은 거절됨; 이번 이슈와 구분.

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

    너의 추천
    이슈는 유효하다. #4702를 머지해 닫고, #4712는 중복으로 닫거나 search/vision만 후속으로 이식하라. 실 Ark 재현 없이도 로컬 수신기 테스트로 계약을 고정하면 충분하다.

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

  5. lidge-jun commented on Sep 16, 2026

    @lidge-jun
    Owner

    Closing as completed on dev by #4702 (45cfb04). The implementation is still present at the audited dev commit ada3a9b: src/adapters/openai-responses/passthrough.ts applies applyCallerUserAgentFallback after provider headers, preserves case-insensitive explicit overrides, and does not invent a caller identity when none was supplied. This addresses the narrow contract requested here without widening arbitrary or credential header forwarding.

    This records merged-on-dev completion, not a claim of a new release or a new live Ark reproduction. #4712 was already closed as the duplicate implementation.

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 reports

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions