Skip to content

Add codex exec support as an LLM provider using pre-existing ChatGPT Pro accts #1

Description

@shoesCodeFor

Checked other resources

  • This is a feature request, not a bug report.
  • I searched existing issues and didn't find this feature.
  • I checked the docs and README for existing functionality.
  • This request applies to this repo (deepagents) and not an external package.

Area (Required)

  • deepagents (SDK)
  • cli

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

  1. 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.

  2. Codex as an explicit provider — users should be able to run:

    deepagents --model codex:o4-mini
    

    and have the CLI route through codex exec.

  3. 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.

  4. 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.

  5. Help screen updatedui.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

  • deepagents --model codex:o4-mini starts a session routed through codex exec when the user is logged in.
  • deepagents (no flags) auto-selects Codex when no API-key env vars are set and codex login status succeeds.
  • When codex login status fails and all API-key env vars are unset, the CLI shows a clear, actionable error — no traceback, no crash — mentioning codex login as the remedy.
  • The --help output and show_help() screen list Codex as a supported provider.
  • All new code paths have unit tests (mocking the subprocess call).
  • make lint && make test passes.
  • The help-screen drift test (TestHelpScreenDrift) continues to pass.

Open Questions

  1. 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.
  2. 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?
  3. Model naming — what model names does codex exec accept? Is o4-mini correct, or is there a Codex-specific naming scheme?
  4. Streaming — does codex exec support streaming output? If not, the wrapper should buffer and return a single AIMessage.
  5. Windows PATHcodex 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

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions