Checked other resources
Area (Required)
Feature description
Summary
Add support for the OpenAI Codex CLI (codex) as a first-class LLM provider in deepagents-cli. Unlike every other provider, Codex authenticates via the user's local session (codex login) rather than an API key environment variable, so the existing PROVIDER_API_KEY_ENV mechanism does not apply. This issue tracks the changes needed across provider detection, credential checking, model creation, startup error reporting, and the CLI help screen.
Background
How provider detection currently works
All supported providers are mapped in libs/cli/deepagents_cli/model_config.py:
PROVIDER_API_KEY_ENV: dict[str, str] = {
"openai": "OPENAI_API_KEY",
"anthropic": "ANTHROPIC_API_KEY",
# ... 17 more entries ...
}
has_provider_credentials(provider) consults this map and calls os.environ.get(env_var) to confirm credentials are available before model creation. If the env var is absent, the user sees:
OPENAI_API_KEY is not set or is empty
detect_provider(model_name) in libs/cli/deepagents_cli/config.py infers the provider from the model name prefix (gpt-* → openai, claude* → anthropic, etc.) and returns None if it can't determine a provider.
_get_default_model_spec() auto-selects the first provider whose API key env var is set. If none are set, it raises:
ModelConfigError: No credentials configured. Please set one of:
ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY, GOOGLE_CLOUD_PROJECT, or NVIDIA_API_KEY
What Codex needs instead
The Codex CLI uses a local OAuth/session token stored by codex login. There is no environment variable to check. Instead:
- Auth check: run
codex login status (or equivalent) as a subprocess and inspect the exit code / stdout.
- Model invocation: run
codex exec --model <model> <prompt> (or use the Codex SDK/langchain integration if one exists).
- No
OPENAI_API_KEY required: Codex's session is independent of OPENAI_API_KEY. A user may have neither env var set yet still be authenticated via Codex.
Desired Behaviour
-
Session check at startup — when no API-key env vars are set, the CLI should run codex login status to test whether the user has an active Codex session. If they do, Codex should be selected as the default provider automatically.
-
Codex as an explicit provider — users should be able to run:
deepagents --model codex:o4-mini
and have the CLI route through codex exec.
-
Graceful error when unauthenticated — if codex login status reports the user is not logged in and every API-key env var in PROVIDER_API_KEY_ENV is unset, the CLI should display a human-readable error in the terminal (not a traceback) such as:
No credentials configured. You have no API key environment variables set and are not logged in to Codex.
Run codex login to authenticate, or set one of: ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY, GOOGLE_CLOUD_PROJECT, NVIDIA_API_KEY.
-
Non-blocking startup — the codex login status subprocess must run in the background worker (same pattern as the existing _start_server_background worker) and must have a timeout (e.g. 5 s) so a slow or missing codex binary does not freeze the CLI.
-
Help screen updated — ui.show_help() and the --help argparse output must mention Codex as a supported provider and describe the codex login pre-requisite.
Required Code Changes
1. libs/cli/deepagents_cli/model_config.py
-
Add a dedicated constant (do not add to PROVIDER_API_KEY_ENV because Codex has no API key env var):
CODEX_PROVIDER_NAME = "codex"
-
Add has_codex_credentials() -> bool | None that runs codex login status as a subprocess:
True — user is logged in and codex binary is present
False — binary present but user is not logged in
None — binary not found on PATH (FileNotFoundError) or timed out
import subprocess
def has_codex_credentials() -> bool | None:
"""Check whether the user has an active Codex CLI session.
Runs `codex login status` as a subprocess. Returns True if the session
is active, False if the binary is found but the user is not logged in,
and None if the `codex` binary is not on PATH or the check times out.
"""
try:
result = subprocess.run(
["codex", "login", "status"],
capture_output=True,
text=True,
timeout=5,
)
return result.returncode == 0
except FileNotFoundError:
return None
except subprocess.TimeoutExpired:
return None
Note: verify the exact subcommand (codex login status, codex auth status, or similar) against the real codex CLI before implementation.
-
Update has_provider_credentials(provider: str) -> bool | None to short-circuit for "codex" before the env-var lookup:
if provider == CODEX_PROVIDER_NAME:
return has_codex_credentials()
-
Update get_credential_env_var(provider: str) -> str | None to return None for "codex" (it has no env var).
2. libs/cli/deepagents_cli/config.py
-
Add a has_codex property to the Settings class alongside the existing has_openai, has_anthropic, etc.:
@property
def has_codex(self) -> bool:
"""True if the user has an active Codex CLI session.
Calls `codex login status` as a subprocess. Returns False if the
binary is absent or the session is not active.
"""
from deepagents_cli.model_config import has_codex_credentials
return has_codex_credentials() is True
-
Update detect_provider(model_name: str) -> str | None to recognise the codex: namespace prefix:
# At the top of detect_provider():
if model_lower.startswith("codex:") or model_lower == "codex":
return "codex"
-
Update _get_default_model_spec() to try Codex after the existing env-var providers but before raising ModelConfigError. Suggested default model: codex:o4-mini.
# After existing openai / anthropic / google / nvidia checks ...
# Codex session-based auth — no API key needed
from deepagents_cli.model_config import has_codex_credentials
if has_codex_credentials() is True:
return "codex:o4-mini"
raise ModelConfigError(
"No credentials configured. Run `codex login` to authenticate with Codex, "
"or set one of: ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY, "
"GOOGLE_CLOUD_PROJECT, or NVIDIA_API_KEY"
)
-
Update create_model() to handle provider == "codex". Two implementation paths:
- If a
langchain-codex package exists: follow the same init_chat_model(model_name, model_provider="codex") pattern.
- If not: create a thin
CodexChatModel wrapper (a langchain_core.language_models.chat_models.BaseChatModel subclass) that invokes codex exec --model <model> as a subprocess and adapts the output to LangChain's AIMessage format. Place it in libs/cli/deepagents_cli/providers/codex.py.
3. libs/cli/deepagents_cli/app.py
-
In the /model command handler (around the credential-check block), add a Codex-specific error:
if has_creds is False and provider == "codex":
await self._mount_message(
ErrorMessage(
"Codex session not found. Run `codex login` and try again."
)
)
return
-
Verify the existing banner.set_failed(str(event.error)) path in on_deep_agents_app_server_start_failed displays the updated ModelConfigError message mentioning codex login clearly.
4. libs/cli/deepagents_cli/ui.py (help screen)
- Add Codex to the provider list. Mention that it requires
codex login instead of an API key env var.
- Update both
ui.show_help() and the argparse --model help text together so the drift-detection test (TestHelpScreenDrift) continues to pass.
5. libs/cli/deepagents_cli/widgets/welcome.py
-
Add a tip to _TIPS:
"Use `codex login` to authenticate with the Codex CLI — no API key required",
6. libs/cli/pyproject.toml
-
If a langchain-codex (or equivalent) package is published, add an optional dependency group:
codex = ["langchain-codex>=X.Y.Z,<N.0.0"]
If no such package exists, implement as a built-in thin wrapper with no additional dependency (just a clear error if codex is not on PATH).
-
Add codex to all-providers once the package is available.
7. libs/cli/tests/unit_tests/test_model_config.py
has_codex_credentials() returns None when codex binary is not on PATH (mock subprocess.run to raise FileNotFoundError).
has_codex_credentials() returns False when codex login status exits non-zero.
has_codex_credentials() returns True when codex login status exits 0.
has_provider_credentials("codex") delegates to has_codex_credentials() rather than checking an env var.
8. libs/cli/tests/unit_tests/test_config.py
detect_provider("codex:o4-mini") → "codex".
_get_default_model_spec() returns a "codex:..." spec when all API-key env vars are unset but has_codex_credentials() is True.
_get_default_model_spec() raises ModelConfigError with an updated message (mentioning codex login) when all API keys are unset and has_codex_credentials() returns False or None.
Acceptance Criteria
Open Questions
- Exact
codex subcommand — is the auth-status check codex login status, codex auth status, or something else? Verify against the official CLI docs / codex --help.
- LangChain integration — does
langchain-openai already support routing through codex exec (e.g. via a base-URL override), or is a custom BaseChatModel wrapper needed?
- Model naming — what model names does
codex exec accept? Is o4-mini correct, or is there a Codex-specific naming scheme?
- Streaming — does
codex exec support streaming output? If not, the wrapper should buffer and return a single AIMessage.
- Windows PATH —
codex may be installed in a non-standard location on Windows; the subprocess call must handle FileNotFoundError gracefully.
Labels
enhancement, cli, provider
Proposed solution (optional)
No response
Additional context (optional)
No response
Checked other resources
Area (Required)
Feature description
Summary
Add support for the OpenAI Codex CLI (
codex) as a first-class LLM provider indeepagents-cli. Unlike every other provider, Codex authenticates via the user's local session (codex login) rather than an API key environment variable, so the existingPROVIDER_API_KEY_ENVmechanism does not apply. This issue tracks the changes needed across provider detection, credential checking, model creation, startup error reporting, and the CLI help screen.Background
How provider detection currently works
All supported providers are mapped in
libs/cli/deepagents_cli/model_config.py:has_provider_credentials(provider)consults this map and callsos.environ.get(env_var)to confirm credentials are available before model creation. If the env var is absent, the user sees:detect_provider(model_name)inlibs/cli/deepagents_cli/config.pyinfers the provider from the model name prefix (gpt-*→openai,claude*→anthropic, etc.) and returnsNoneif it can't determine a provider._get_default_model_spec()auto-selects the first provider whose API key env var is set. If none are set, it raises:What Codex needs instead
The Codex CLI uses a local OAuth/session token stored by
codex login. There is no environment variable to check. Instead:codex login status(or equivalent) as a subprocess and inspect the exit code / stdout.codex exec --model <model> <prompt>(or use the Codex SDK/langchain integration if one exists).OPENAI_API_KEYrequired: Codex's session is independent ofOPENAI_API_KEY. A user may have neither env var set yet still be authenticated via Codex.Desired Behaviour
Session check at startup — when no API-key env vars are set, the CLI should run
codex login statusto test whether the user has an active Codex session. If they do, Codex should be selected as the default provider automatically.Codex as an explicit provider — users should be able to run:
and have the CLI route through
codex exec.Graceful error when unauthenticated — if
codex login statusreports the user is not logged in and every API-key env var inPROVIDER_API_KEY_ENVis unset, the CLI should display a human-readable error in the terminal (not a traceback) such as:Non-blocking startup — the
codex login statussubprocess must run in the background worker (same pattern as the existing_start_server_backgroundworker) and must have a timeout (e.g. 5 s) so a slow or missingcodexbinary does not freeze the CLI.Help screen updated —
ui.show_help()and the--helpargparse output must mention Codex as a supported provider and describe thecodex loginpre-requisite.Required Code Changes
1.
libs/cli/deepagents_cli/model_config.pyAdd a dedicated constant (do not add to
PROVIDER_API_KEY_ENVbecause Codex has no API key env var):Add
has_codex_credentials() -> bool | Nonethat runscodex login statusas a subprocess:True— user is logged in andcodexbinary is presentFalse— binary present but user is not logged inNone— binary not found on PATH (FileNotFoundError) or timed outUpdate
has_provider_credentials(provider: str) -> bool | Noneto short-circuit for"codex"before the env-var lookup:Update
get_credential_env_var(provider: str) -> str | Noneto returnNonefor"codex"(it has no env var).2.
libs/cli/deepagents_cli/config.pyAdd a
has_codexproperty to theSettingsclass alongside the existinghas_openai,has_anthropic, etc.:Update
detect_provider(model_name: str) -> str | Noneto recognise thecodex:namespace prefix:Update
_get_default_model_spec()to try Codex after the existing env-var providers but before raisingModelConfigError. Suggested default model:codex:o4-mini.Update
create_model()to handleprovider == "codex". Two implementation paths:langchain-codexpackage exists: follow the sameinit_chat_model(model_name, model_provider="codex")pattern.CodexChatModelwrapper (alangchain_core.language_models.chat_models.BaseChatModelsubclass) that invokescodex exec --model <model>as a subprocess and adapts the output to LangChain'sAIMessageformat. Place it inlibs/cli/deepagents_cli/providers/codex.py.3.
libs/cli/deepagents_cli/app.pyIn the
/modelcommand handler (around the credential-check block), add a Codex-specific error:Verify the existing
banner.set_failed(str(event.error))path inon_deep_agents_app_server_start_faileddisplays the updatedModelConfigErrormessage mentioningcodex loginclearly.4.
libs/cli/deepagents_cli/ui.py(help screen)codex logininstead of an API key env var.ui.show_help()and the argparse--modelhelp text together so the drift-detection test (TestHelpScreenDrift) continues to pass.5.
libs/cli/deepagents_cli/widgets/welcome.pyAdd a tip to
_TIPS:"Use `codex login` to authenticate with the Codex CLI — no API key required",6.
libs/cli/pyproject.tomlIf a
langchain-codex(or equivalent) package is published, add an optional dependency group:If no such package exists, implement as a built-in thin wrapper with no additional dependency (just a clear error if
codexis not on PATH).Add
codextoall-providersonce the package is available.7.
libs/cli/tests/unit_tests/test_model_config.pyhas_codex_credentials()returnsNonewhencodexbinary is not on PATH (mocksubprocess.runto raiseFileNotFoundError).has_codex_credentials()returnsFalsewhencodex login statusexits non-zero.has_codex_credentials()returnsTruewhencodex login statusexits 0.has_provider_credentials("codex")delegates tohas_codex_credentials()rather than checking an env var.8.
libs/cli/tests/unit_tests/test_config.pydetect_provider("codex:o4-mini")→"codex"._get_default_model_spec()returns a"codex:..."spec when all API-key env vars are unset buthas_codex_credentials()isTrue._get_default_model_spec()raisesModelConfigErrorwith an updated message (mentioningcodex login) when all API keys are unset andhas_codex_credentials()returnsFalseorNone.Acceptance Criteria
deepagents --model codex:o4-ministarts a session routed throughcodex execwhen the user is logged in.deepagents(no flags) auto-selects Codex when no API-key env vars are set andcodex login statussucceeds.codex login statusfails and all API-key env vars are unset, the CLI shows a clear, actionable error — no traceback, no crash — mentioningcodex loginas the remedy.--helpoutput andshow_help()screen list Codex as a supported provider.make lint && make testpasses.TestHelpScreenDrift) continues to pass.Open Questions
codexsubcommand — is the auth-status checkcodex login status,codex auth status, or something else? Verify against the official CLI docs /codex --help.langchain-openaialready support routing throughcodex exec(e.g. via a base-URL override), or is a customBaseChatModelwrapper needed?codex execaccept? Iso4-minicorrect, or is there a Codex-specific naming scheme?codex execsupport streaming output? If not, the wrapper should buffer and return a singleAIMessage.codexmay be installed in a non-standard location on Windows; the subprocess call must handleFileNotFoundErrorgracefully.Labels
enhancement,cli,providerProposed solution (optional)
No response
Additional context (optional)
No response