Skip to content

feat(llm): add openai_codex provider using ChatGPT subscription quota - #1195

Open
LeonWTW wants to merge 1 commit into
TauricResearch:mainfrom
LeonWTW:feat/openai-codex-provider
Open

feat(llm): add openai_codex provider using ChatGPT subscription quota#1195
LeonWTW wants to merge 1 commit into
TauricResearch:mainfrom
LeonWTW:feat/openai-codex-provider

Conversation

@LeonWTW

@LeonWTW LeonWTW commented Aug 1, 2026

Copy link
Copy Markdown

Closes #1194 — that issue carries the full rationale; this is the implementation.

Adds an openai_codex provider so a run can be billed to an existing ChatGPT subscription instead of API credits. Nothing changes for any other provider: every code path here is behind the new provider name.

Why this needs a provider rather than openai_compatible + backend_url

The endpoint breaks three assumptions the shared OpenAI client makes:

Assumption Reality Handled in
Auth comes from an env var OAuth token in ~/.codex/auth.json, refreshed near expiry, refresh token rotates and must be written back or the Codex client logs out llm_clients/codex_auth.py via ProviderSpec.credentials_fn
stream: false / store: true / temperature are fine All rejected CodexChatOpenAI — first two pinned as constructor kwargs (a class-level field default sets the payload but not langchain's streaming dispatch), temperature filtered in get_llm
system role is fine 400 "System messages are not allowed" — and every agent prompt here is a ChatPromptTemplate starting with a system message, so the first analyst node fails on its first call _get_request_payload relabels those items developer, the Responses-API name for the same role

What changed

  • tradingagents/llm_clients/codex_auth.py (new) — resolve, refresh, rotate, persist. Path overridable via TRADINGAGENTS_CODEX_AUTH_PATH.
  • tradingagents/llm_clients/openai_client.pyCodexChatOpenAI; auth-error messages stay actionable after the file re-read.
  • tradingagents/llm_clients/model_catalog.py, api_key_env.py — registry entry; no API key is read for this provider.
  • tradingagents/graph/trading_graph.py_get_provider_kwargs forwards openai_reasoning_effort for openai_codex as well.
  • cli/utils.py, cli/main.py — picker entry, login preflight (so an unauthenticated user gets "sign in with the Codex client first" instead of a 401 mid-run), and the reasoning-effort prompt.
  • README.md — provider docs, including the caveats below.

Trying it

codex login          # or sign in with the Codex desktop app
tradingagents        # pick "OpenAI Codex (ChatGPT subscription quota)"

Subscription traffic hits transient "servers are currently overloaded" errors far more often than the paid API, so the README suggests TRADINGAGENTS_LLM_MAX_RETRIES=5 or higher.

Testing

pytest -q614 passed, 5 skipped; ruff check . → clean.

New coverage: auth-file resolution/refresh/rotation (test_codex_auth.py), provider registration and payload shaping (test_codex_provider.py), CLI preflight (test_codex_cli.py). test_codex_smoke.py drives the live endpoint with a real ChatPromptTemplate and is opt-in behind -m smoke, so CI never calls out. The smoke test matters for the system→developer fix specifically: a bare-string invoke carries no system message and passed throughout, which is how that bug survived.

Caveats

This endpoint is undocumented and unversioned, so OpenAI can change it without notice, and driving subscription credentials from a third-party tool is not clearly sanctioned by OpenAI's terms. Both points are stated in the README next to the provider. If you would rather gate this further or not carry it at all, say so in #1194 and I will rework or withdraw it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FFuMQCxPhTkWLwrCQ57tTp

Adds an `openai_codex` provider so a run can be billed to an existing
ChatGPT subscription instead of API credits.

It is the only provider here that does not authenticate from an env
var. It reuses the OAuth token the official Codex app/CLI stores in
`~/.codex/auth.json` (overridable with `TRADINGAGENTS_CODEX_AUTH_PATH`)
via `ProviderSpec.credentials_fn`, refreshes it when it nears expiry,
and writes the rotated refresh token back — not persisting it would log
the Codex client itself out.

The endpoint also rejects three things the shared OpenAI client sends by
default, so `CodexChatOpenAI` overrides them:

- `stream: false` and `store: true` are pinned as constructor kwargs; a
  class-level field default sets the payload but not langchain's
  streaming dispatch, so the non-streaming path would still be taken.
- `temperature` is filtered out in `get_llm`.
- Input items with role `system` return 400. Every agent prompt in this
  repo is a `ChatPromptTemplate` whose first message is a system
  message, so the first analyst node failed on its first call and the
  run stalled. `_get_request_payload` relabels those items `developer`,
  the Responses-API name for the same role. Adding `instructions` does
  not make `system` acceptable, and only the item list preserves
  ordering when several system messages reach one call.

Because subscription traffic hits transient overload errors far more
often than the paid API, the README suggests raising
`TRADINGAGENTS_LLM_MAX_RETRIES`.

Caveat, stated in the README too: this endpoint is undocumented and
unversioned, so OpenAI can change it without notice, and driving
subscription credentials from a third-party tool is not clearly
sanctioned by OpenAI's terms. Nothing else in the codebase changes
behaviour unless the provider is selected.

Tests: auth-file resolution/refresh/rotation, provider registration and
payload shaping, the CLI login preflight, plus an opt-in live smoke test
behind `-m smoke`. `pytest -q` is 614 passed / 5 skipped and
`ruff check .` is clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FFuMQCxPhTkWLwrCQ57tTp
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@LeonWTW

LeonWTW commented Aug 1, 2026

Copy link
Copy Markdown
Author

CI is held at action_required here pending maintainer approval, so I ran the same workflow on my fork in the meantime — all six jobs green (py3.10–3.13, ruff strict full-repo, clean-install smoke):

https://github.com/LeonWTW/TradingAgents/actions/runs/30714455163

No rush on my side; flagging it only so the approval decision doesn't have to double as a "does it even build" question.

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.

feat: bill runs to a ChatGPT subscription via an openai_codex provider

1 participant