Summary
Trinity's Codex runtime resolves an OpenAI API key and passes it to codex exec
via the environment only. That is no longer sufficient: current Codex CLI
authenticates its wss://api.openai.com/v1/responses transport from
$CODEX_HOME/auth.json, and with only OPENAI_API_KEY set every turn fails with
repeated 401 Unauthorized and a non-zero exit.
Net effect: an API-key Codex agent cannot complete a single turn. Only
subscription agents (which already ship an auth.json, #1971) work.
Evidence
Same key, same prompt, same image, both CLI versions — reproduced while
validating #2207:
| Setup |
Result |
-e OPENAI_API_KEY=…, codex 0.139.0 (current pin) |
exit=1, 7x 401 Unauthorized |
-e OPENAI_API_KEY=…, codex 0.147.0 |
exit=1, 7x 401 Unauthorized |
printenv OPENAI_API_KEY | codex login --with-api-key first, then same turn |
exit=0, result PONG, 0x 401 |
ERROR codex_api::endpoint::responses_websocket: failed to connect to websocket:
HTTP error: 401 Unauthorized, url: wss://api.openai.com/v1/responses
The key itself is fine — GET /v1/models, POST /v1/responses and
POST /v1/chat/completions all return 200 with it. The failure is specific to
the CLI's websocket transport, which reads auth.json.
Not a regression from the #2207 CLI bump — 0.139.0 and 0.147.0 fail
identically, so this predates it.
Why it was invisible
_codex_auth_ready() accepts either an API key or an auth.json, so the
pre-flight gate passes and the failure surfaces later as a CLI auth error.
responses_websockets / responses_websockets_v2 are listed as removed
in codex features list, i.e. the transport is no longer toggleable — there
is no flag to fall back to the HTTP path that does accept a bare env key.
- Nothing in
startup.sh or codex_runtime.py ever runs codex login
(grep -rn "codex login" → no hits).
Proposed fix
Materialise the resolved key into $CODEX_HOME/auth.json before the first
codex exec, e.g. run codex login --with-api-key (key on stdin — the
--api-key flag is removed in current versions) once at agent start or lazily on
first use, keeping the existing subscription-auth.json path untouched and
taking precedence per #1971.
Care needed:
- Do not clobber an existing subscription
auth.json.
- The key must reach the CLI on stdin, never argv (process listing).
CODEX_HOME is under $TMPDIR and wiped on recreate, so this must be
idempotent per container start.
Acceptance Criteria
Technical Notes
docker/base-image/agent_server/services/codex_runtime.py —
_load_api_key_with_source, _codex_auth_ready, _codex_home, _execute_codex
docker/base-image/startup.sh — the other candidate home for the login step
Found while verifying #2207 (AC #10); that issue is scoped to model/pricing and
deliberately does not fix this.
Summary
Trinity's Codex runtime resolves an OpenAI API key and passes it to
codex execvia the environment only. That is no longer sufficient: current Codex CLI
authenticates its
wss://api.openai.com/v1/responsestransport from$CODEX_HOME/auth.json, and with onlyOPENAI_API_KEYset every turn fails withrepeated
401 Unauthorizedand a non-zero exit.Net effect: an API-key Codex agent cannot complete a single turn. Only
subscription agents (which already ship an
auth.json, #1971) work.Evidence
Same key, same prompt, same image, both CLI versions — reproduced while
validating #2207:
-e OPENAI_API_KEY=…, codex 0.139.0 (current pin)exit=1, 7x401 Unauthorized-e OPENAI_API_KEY=…, codex 0.147.0exit=1, 7x401 Unauthorizedprintenv OPENAI_API_KEY | codex login --with-api-keyfirst, then same turnexit=0, resultPONG, 0x 401The key itself is fine —
GET /v1/models,POST /v1/responsesandPOST /v1/chat/completionsall return 200 with it. The failure is specific tothe CLI's websocket transport, which reads
auth.json.Not a regression from the #2207 CLI bump — 0.139.0 and 0.147.0 fail
identically, so this predates it.
Why it was invisible
_codex_auth_ready()accepts either an API key or anauth.json, so thepre-flight gate passes and the failure surfaces later as a CLI auth error.
responses_websockets/responses_websockets_v2are listed as removedin
codex features list, i.e. the transport is no longer toggleable — thereis no flag to fall back to the HTTP path that does accept a bare env key.
startup.shorcodex_runtime.pyever runscodex login(
grep -rn "codex login"→ no hits).Proposed fix
Materialise the resolved key into
$CODEX_HOME/auth.jsonbefore the firstcodex exec, e.g. runcodex login --with-api-key(key on stdin — the--api-keyflag is removed in current versions) once at agent start or lazily onfirst use, keeping the existing subscription-
auth.jsonpath untouched andtaking precedence per #1971.
Care needed:
auth.json.CODEX_HOMEis under$TMPDIRand wiped on recreate, so this must beidempotent per container start.
Acceptance Criteria
OPENAI_API_KEYin its.envcompletes a real chat andtask turn (currently: 401 on every turn).
auth.jsonis unaffected.successful turn.
Technical Notes
docker/base-image/agent_server/services/codex_runtime.py—_load_api_key_with_source,_codex_auth_ready,_codex_home,_execute_codexdocker/base-image/startup.sh— the other candidate home for the login stepFound while verifying #2207 (AC #10); that issue is scoped to model/pricing and
deliberately does not fix this.