Skip to content

[Bug]: AgentRouter openai-chat providers need a Codex client fingerprint; non-English fix only covers anthropic #2717

Description

@rrmlima

Client or integration

Codex CLI (also reproducible with a direct HTTP client).

Provider or upstream service

AgentRouter (agentrouter.org)

Version

OpenCodex 2.33.0.

Operating system

Linux server (x86_64).

Provider and model

AgentRouter / claude-opus-5.

OpenCodex version

2.33.0, official npm package; affected adapter files verified byte-for-byte against the published tarball.

Endpoint or capability

/v1/responses translated to an AgentRouter openai-chat provider at https://agentrouter.org/v1; client authentication/fingerprint and non-English prompts.

Summary

AgentRouter openai-chat providers fail with 401 unless a recognized Codex client fingerprint is manually configured, and minimal Portuguese requests still fail with 400 content-blocked because the 2.31 fix covers only the Anthropic adapter.

Current behaviour

Two independent failures remain after the AgentRouter language fix merged in #2162:

  1. A valid AgentRouter key on a normal openai-chat provider is rejected with HTTP 401 unauthorized_client_error unless the operator manually adds an undocumented recognized-client fingerprint (User-Agent or originator) to provider.headers.
  2. Once fingerprint authentication succeeds, a minimal Portuguese request still returns HTTP 400 content-blocked. The same provider works from the real Codex CLI because Codex supplies a large English harness context before the Portuguese user prompt.

OpenCodex 2.33.0 implements AgentRouter language framing only in src/adapters/anthropic.ts. src/adapters/openai-chat.ts has no AgentRouter-specific host detection, fingerprint defaults, or language framing.

Controlled header matrix, same key/model/body/process:

Provider headers Minimal EN request Real Codex PT request
none 401 unauthorized client 401 after five retries
version: 0.149.1 only 401 not run
User-Agent: codex_cli_rs/0.149.1 only 200 200
originator: codex_cli_rs only 200 200
UA + originator + version 0.149.1 200 200
UA + originator + version 0.145.0-alpha.30 200 200

The old version is not required; the recognized Codex identity is what matters.

Expected behaviour

A first-class AgentRouter provider/preset using openai-chat should work with a valid key without requiring operators to discover and copy undocumented magic headers.

OpenCodex should either:

  • supply a documented, stable AgentRouter-compatible client fingerprint by default for exact agentrouter.org hosts; or
  • expose a documented clientFingerprint compatibility option and diagnose the upstream 401 clearly.

AgentRouter's non-English request policy should also be applied consistently to both the Anthropic and OpenAI Chat adapter paths, including translated /v1/responses and raw /v1/chat/completions passthrough.

Operator-specified headers must continue to override defaults, and non-AgentRouter providers must remain unchanged.

Reproduction

The exact minimal reproduction is provided below.

Minimal redacted request or reproduction

# 1. Configure a provider (valid key redacted):
# providers.agentrouter-test = {
#   adapter: "openai-chat",
#   baseUrl: "https://agentrouter.org/v1",
#   authMode: "key",
#   apiKey: "<redacted>",
#   liveModels: false,
#   models: ["claude-opus-5"],
#   selectedModels: ["claude-opus-5"],
#   defaultModel: "claude-opus-5"
# }

# 2. Send an English request with no custom provider headers:
curl -sS http://127.0.0.1:10100/v1/responses \
  -H "Authorization: Bearer $OPENCODEX_API_AUTH_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{
    "model":"agentrouter-test/claude-opus-5",
    "input":"Reply with exactly: OK",
    "stream":false,
    "store":false,
    "max_output_tokens":64
  }'
# => HTTP 401 unauthorized client

# 3. Add either header and repeat:
# headers: { "User-Agent": "codex_cli_rs/0.149.1" }
# OR
# headers: { "originator": "codex_cli_rs" }
# => HTTP 200

# 4. With the recognized fingerprint, change input to Portuguese:
# "input":"Responda somente com: OK"
# => minimal direct request: HTTP 400 content-blocked

# 5. Run through the real Codex CLI, which supplies English harness context:
codex exec --ephemeral --skip-git-repo-check \
  -m agentrouter-test/claude-opus-5 \
  'Responda somente com: OK'
# => HTTP 200 / exact answer

Actual response or error

# Without recognized client fingerprint:
HTTP 401
{
  "error": {
    "message": "unauthorized client detected, contact support for assistance"
  },
  "type": "unauthorized_client_error"
}

# With recognized fingerprint, minimal Portuguese request:
HTTP 400
{
  "error": {
    "code": "content-blocked",
    "type": "agent_router_api_error"
  }
}

# With recognized fingerprint, real Codex CLI Portuguese request:
HTTP 200
turn.completed

Request IDs, credentials, account details, and host-specific data were removed.

Upstream documentation

AgentRouter does not appear to publish a public specification documenting the required User-Agent/originator client allowlist or the non-English content-scoring contract. The observable behavior above is based on controlled black-box compatibility testing against the service.

OpenCodex context:

Suggested mapping or implementation notes

  1. Register AgentRouter as a first-class compatibility policy/preset.
  2. For parsed hostnames exactly equal to agentrouter.org or ending in .agentrouter.org, provide default static headers only when absent:
{
  "User-Agent": "codex_cli_rs/<detected-current-version>",
  "originator": "codex_cli_rs"
}

If impersonating Codex is not acceptable, use a stable OpenCodex-owned fingerprint coordinated/documented with AgentRouter, or require an explicit compatibility option.

  1. Use existing case-insensitive mergeRegistryStaticHeaders() semantics so operator headers win.
  2. Share exact-host AgentRouter policy between anthropic and openai-chat adapters.
  3. Cover translated /v1/responses and raw Chat Completions passthrough.
  4. Preserve user content byte-for-byte, keep framing idempotent, and never match hostile lookalike hostnames such as agentrouter.org.attacker.example.
  5. Map unauthorized_client_error to an actionable diagnostic.

Additional context and attachments

The final local provider was validated across restart with:

  • current Codex fingerprint 0.149.1;
  • two consecutive Portuguese Codex requests returning 200;
  • exact expected output;
  • no patch in OpenCodex adapters;
  • original AgentRouter providers disabled during isolated testing;
  • custom provider created through the 2.33.0 management API.

The key conclusion is that #2162 fixed only Anthropic first-turn framing. It did not make AgentRouter openai-chat providers self-configuring, and it did not address AgentRouter's required client identity.

Checks

  • I searched existing provider and compatibility issues.
  • The request and response were redacted.
  • The expected behaviour is based on a concrete Codex CLI client requirement and controlled upstream behavior.

Activity

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

    bugSomething isn't workingproviderProvider 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