Last updated

How Codex Router Works — Architecture & Request Flow

Codex Router is a local service between coding-agent clients and external model providers. Codex remains its primary frontend, while the same authenticated model registry can also be published to DeepSeek Harness, Gemini CLI, Cursor, Claude Code, OpenClaw, opencode, pi, omp, Command Code and Hermes Agent. This page explains the request flow and security boundaries.

Why a router is needed

The Codex App expects the Responses API and a Codex-shaped model catalog. Kimi and DeepSeek expose OpenAI-compatible Chat Completions APIs with different authentication and request details. A router is needed to bridge those contracts while leaving native GPT traffic on the normal ChatGPT Codex backend.

The four pieces

  • A generated catalog places external models beside native GPT models in Codex’s model_catalog_json.
  • A dispatcher chooses native or external routing by namespaced model ID — anything starting with deepseek/, kimi-oauth/, anthropic-api/ and so on goes to the external path.
  • LiteLLM translates Responses requests, streams and tool calls to each provider’s native protocol, including OpenAI-compatible Chat Completions and Anthropic Messages.
  • Credential forwarders inject only the selected provider’s authentication and strip everything else.

Every listener binds to 127.0.0.1, so the whole service is local to your machine.

Request flow

Codex sends a Responses request to the loopback router on port 4202:

PortListenerRole
4202RouterReceives client requests and authenticates the caller capability
4200LiteLLMTranslates Responses to each provider’s native protocol
4201Kimi OAuthForwards to Kimi with a refreshed OAuth bearer
4203API forwarderForwards to API-key providers with the selected key

For a native GPT model, the router forwards the request to the ChatGPT Codex backend with allow-listed Codex headers and the native model ID — the router never sends a native request to an external provider.

For a registry model (for example kimi-oauth/k3), the router validates the caller, passes a gateway model plus an internal key to LiteLLM, which translates the request and hands it to the matching forwarder. The forwarder discards the internal key and injects only the selected provider credential. The stream flows back through LiteLLM as Responses events.

One registry, multiple clients

Codex, DeepSeek Harness, Gemini CLI, Cursor, Claude Code, OpenClaw, opencode, pi, omp, Command Code and Hermes Agent consume the same provider visibility and per-model picker state. Each publisher adapts only the outer client contract—Responses, Gemini, Anthropic Messages or Cursor’s edge—then re-enters the same routed request path. Command Code and Hermes Agent reach the same Anthropic Messages surface Claude Code uses, while opencode, pi and omp receive the authenticated loopback /v1 path. The five published-into clients have no MODEL_ROUTER_TARGET and no second service; enabling a provider or curating a model republishes them together. Native ChatGPT models are exposed to non-Codex clients only after the user explicitly enables shared-session access with chatgpt-session enable.

Credential boundaries

RouteIncoming Codex credentialUpstream credential
Native GPTAllow-listed and forwardedExisting ChatGPT/Codex authentication
Kimi OAuthDiscardedKimi CLI OAuth bearer from ~/.kimi-code
Kimi APIDiscardedKimi Platform API key
DeepSeekDiscardedDeepSeek API key
GitHub CopilotDiscardedFine-grained GitHub token after Copilot entitlement and endpoint validation

The Codex-to-router and internal-service trust boundaries use two different random keys, each stored with mode 600 or a current-user Windows ACL. External forwarders remove Codex account, installation, attestation and private headers before sending a request upstream.

GitHub Copilot is a catalog-only provider. Its fine-grained token is first validated against GitHub’s Copilot account endpoint, and the returned inference endpoint must be a GitHub-owned Copilot host. Live discovery exposes only the account-visible Responses models that support streaming and tool calls. Available models and usage limits therefore follow the user’s Copilot plan and organization policy.

Security model

  • Local caller authentication. The managed base URL contains a separate random capability; the router validates it before reading a model request or contacting any upstream. Codex cannot attach a router-specific header to the built-in provider, so the capability lives in the URL path. Status, migration and support tools redact it.
  • No browser access. The router requires JSON content, rejects browser-origin headers, and never grants CORS access.
  • Sanitized errors. Network-facing errors are bounded and non-sensitive; raw exception text is replaced.
  • No credential leakage. Diagnostics report presence and source, never values. Protected files use mode 600 or a current-user ACL.

Transport and compaction

Current Codex builds may use an authenticated Responses WebSocket. The router accepts it on the same caller-capability edge, derives identity per request and preserves quota/error metadata while routing the turn through the same managed Responses path; HTTP remains supported. Request bodies may use Zstandard, gzip, deflate or Brotli, and oversized compressed frames are refused before decoding.

External Chat Completions providers cannot create OpenAI’s opaque encrypted compaction payload, so the router asks the selected external model for a continuation summary and wraps it in a router-owned kcr1: payload. On replay it converts that payload back to a plain continuation message.

What stays in Codex

Commands, permissions, MCP tools, skills, agent loops and task state remain in Codex. The router handles model inference and external-model compaction; it cannot add a capability the selected model or provider does not implement.

For collaboration subagents, the router relays the exact native task payload through the already-authenticated native Codex backend — the relay requires an active ChatGPT sign-in and fails closed in login-free mode rather than forwarding unreadable ciphertext to an external provider. Enabling a model as a subagent now researches it first: a detached probe verifies streaming and a forced tool call, a passing model is advertised as an experimental v2 override, and the first real child turn records a machine-local proof — a structural rejection demotes it back to v1 with the reason kept. Each generated routed-agent definition also writes that model’s configured model_reasoning_effort, so a low-effort parent does not silently force every child onto low effort.

When a model that looked eligible cannot be delegated to, ask why instead of spawning one and reading codex exited 1:

./bin/model-router codex subagents explain <provider/model>

The command names the first blocker plus the command that fixes it, and distinguishes a typo from an uncurated model from a native slug. It also reports whether a route’s v2 claim comes from the registry, from a local five-check run, or from your own selection. It is read-only and consumes no quota.

Native tools and the custom-model skill pack

Routed custom models keep Codex’s native threads, automations, in-app browser and computer-use tools. Because some models need clearer tool-calling guidance, the installer adds four managed skills: codex-router, codex-app-threads, codex-in-app-browser and codex-computer-use. The installer skips any same-named skill owned by the user, the uninstaller removes only router-managed copies, and doctor verifies that the installed pack matches the checkout and current app toolset.

The native catalog is preserved

The integration preserves the built-in OpenAI provider, native GPT models, ChatGPT sign-in, profiles, MCP settings, project trust and reasoning defaults. It adds one marked root block and one inert custom-provider table to the Codex config, and disable restores the previous values exactly.

Related: installation, models overview, troubleshooting.