DEV Community

member_0af6418a
member_0af6418a

Posted on • Originally published at kunpeng-ai.com

Codex + Tencent LKEAP 401: It Was Not the Key

I ran into a failure that looked like an authentication problem at first:

unexpected status 401 Unauthorized
Enter fullscreen mode Exit fullscreen mode

The setup was Codex against Tencent Cloud LKEAP Token Plan, using an OpenAI-compatible Chat Completions endpoint.

The important clue was not the 401. It was the final URL:

https://api.lkeap.cloud.tencent.com/plan/v3/chat/completions/responses
Enter fullscreen mode Exit fullscreen mode

That URL shape is already wrong.

Codex LKEAP protocol path debugging cover

The config that caused it

The provider entry looked roughly like this:

[model_providers.custom]
name = "custom"
wire_api = "responses"
requires_openai_auth = true
base_url = "https://api.lkeap.cloud.tencent.com/plan/v3/chat/completions"
Enter fullscreen mode Exit fullscreen mode

The mistake is subtle.

The Tencent endpoint in this setup is Chat Completions-style:

/plan/v3/chat/completions
Enter fullscreen mode Exit fullscreen mode

But newer Codex expects a Responses API-style provider when wire_api = "responses" is used. So Codex appended /responses to a base URL that already ended in /chat/completions.

That produced:

/plan/v3/chat/completions/responses
Enter fullscreen mode Exit fullscreen mode

The broken URL revealed the root cause

At that point, rotating the API key is unlikely to help. The request is already going to the wrong protocol path.

Why not switch Codex back to Chat Completions?

That was the next thing I checked.

The newer Codex configuration rejects wire_api = "chat":

invalid configuration: `wire_api = "chat"` is no longer supported.
How to fix: set `wire_api = "responses"` in your provider config.
Enter fullscreen mode Exit fullscreen mode

So this is not just a missing slash or a bad base URL. It is a protocol mismatch:

  • Codex wants to speak Responses API.
  • The LKEAP endpoint I was using speaks Chat Completions.
  • "OpenAI-compatible" does not automatically mean "compatible with every OpenAI client mode."

That last point is the real lesson.

Responses API and Chat Completions are different protocol shapes

My debugging order now

For this class of issue, I would check things in this order:

  1. Inspect the final request URL.
  2. Confirm the client's wire protocol.
  3. Confirm the upstream endpoint shape.
  4. Only then spend time on keys and permissions.

If the URL contains patterns like these, stop and look at path composition first:

/chat/completions/responses
/v1/v1
/responses/chat/completions
Enter fullscreen mode Exit fullscreen mode

The status code may be a symptom. The URL shape is often the evidence.

Workaround: local protocol adapter

The workaround I tested toward was a small local Node.js proxy.

Codex calls a local Responses-shaped endpoint:

http://127.0.0.1:15722/v1/responses
Enter fullscreen mode Exit fullscreen mode

The local proxy converts that into a Chat Completions request and forwards it to:

https://api.lkeap.cloud.tencent.com/plan/v3/chat/completions
Enter fullscreen mode Exit fullscreen mode

The Codex config then points to the local proxy:

model_provider = "tencent_lkeap_proxy"
model = "glm-5.1"
disable_response_storage = true

[model_providers.tencent_lkeap_proxy]
name = "Tencent LKEAP via local Responses proxy"
wire_api = "responses"
base_url = "http://127.0.0.1:15722/v1"
requires_openai_auth = true
env_key = "OPENAI_API_KEY"
Enter fullscreen mode Exit fullscreen mode

The real Tencent key stays in the proxy process environment:

$env:TENCENT_LKEAP_API_KEY="REDACTED"
$env:TENCENT_LKEAP_MODEL="glm-5.1"
node tools\codex-responses-to-chat-proxy.mjs
Enter fullscreen mode Exit fullscreen mode

Codex still expects an OpenAI auth variable for this provider shape, so I used a local dummy value:

$env:OPENAI_API_KEY="local-proxy-dummy"
Enter fullscreen mode Exit fullscreen mode

The proxy ignores that dummy value and uses TENCENT_LKEAP_API_KEY upstream.

Use a local proxy to translate Responses requests to Chat Completions

Boundary

I would not describe this as a complete drop-in replacement.

What was verified in the original debugging record:

  • the failure path was identified
  • the local proxy script was created
  • node --check passed

Still to verify:

  • full end-to-end smoke test with a real LKEAP key
  • streaming behavior under longer tasks
  • Codex tool-call traffic
  • cancellation, timeout, and error mapping

That distinction matters. A protocol adapter can be useful, but it should be treated as an adapter to harden, not as magic compatibility.

The practical takeaway:

When an AI coding tool fails against an "OpenAI-compatible" endpoint, do not ask only whether the key is valid. Ask whether the client and server are actually speaking the same API shape.

Original version:
https://kunpeng-ai.com/en/blog/codex-lkeap-protocol-path-debugging/

Top comments (0)