Skip to content
IQ Routing

Codex CLI

Codex speaks the OpenAI Responses API, and so does the gateway: point a custom model provider at the gateway base URL, give it a gateway key, and every Codex turn (planning, edits, shell commands, streamed tool calls) routes through IQ. Codex reads provider configuration from ~/.codex/config.toml.

Drop-in switch

Add a custom model provider to ~/.codex/config.toml and make it the default:

model = "auto-coding"
model_provider = "iq-routing"

[model_providers.iq-routing]
name = "IQ Routing"
base_url = "https://gateway.iq-routing.com/v1"
env_key = "IQ_GATEWAY_KEY"
wire_api = "responses"

Then export your gateway key under the name you gave env_key and run Codex:

export IQ_GATEWAY_KEY="gw_live_xxxxxxxx"
codex

base_url keeps the /v1 suffix, since Codex calls /v1/responses. wire_api = "responses" pins the wire format Codex 0.142 and later actually speak; the gateway implements the stateful Responses API end to end, so streamed tool calls and previous_response_id continuation work the same as they do against OpenAI directly. model = "auto-coding" routes each turn by complexity within the coding band; use auto for the general classifier, or pin a concrete id or a capability alias instead (see below).

Opt-in wrapper instead of a default

If you would rather keep plain codex on its existing login and route through the gateway only when you choose, skip the config-file default and pass the same provider as -c overrides from a shell function:

iqcodex() {
  codex \
    -c model_provider=iq \
    -c model=auto-coding \
    -c 'model_providers.iq.name="IQ Routing"' \
    -c 'model_providers.iq.base_url="https://gateway.iq-routing.com/v1"' \
    -c 'model_providers.iq.env_key="IQ_GATEWAY_KEY"' \
    -c 'model_providers.iq.wire_api="responses"' \
    "$@"
}

iqcodex then routes through IQ while bare codex stays exactly as it was.

Verify it routes

Start Codex in a scratch repo and give it a one-line task (“list the files in this directory”). The tool call streams, executes, and the summary renders with the gateway's standard latency. Open your dashboard at /requests and each Codex turn is its own row, with the classifier's chosen model, the cost, and the cache-hit status. The response also carries the x-iq-routing header (chosen_provider, chosen_model, cache_hit), so you can confirm which concrete model handled the turn. No row after a turn that otherwise looked normal usually means model_provider stayed on its default -- see Common gotchas below.

Using capability aliases

Set model to a cap:<name> alias to route by stable intent instead of a pinned model id. The six default capabilities are reason-heavy, tool-call-strict, long-context-128k, vision, cheap-fast, and json-mode:

model = "cap:reason-heavy"
model_provider = "iq-routing"

Codex sends that string through as the model field on each call, and the gateway resolves it to a concrete model at routing time, shaped by your per-org overrides and circuit-breaker state. See the capability aliases docs for the full resolver decision tree.

Common gotchas

Codex has no environment-variable override for its endpoint -- OPENAI_BASE_URL does nothing; the binary does not read it. The model_provider you select, whether the config.toml default above or a -c model_provider=... override, is the only thing that decides where a turn goes. If Codex is signed in with codex login (a ChatGPT subscription) and model_provider is left at its default, turns go straight to OpenAI on that subscription, never reach the gateway, and leave no row in /requests. Set model_provider to your iq-routing (or iq) block, as the config.toml default or per invocation with the wrapper above, to guarantee routing.

If you are following an older recipe that pins wire_api = "chat", drop it: recent Codex releases default to the Responses wire, and some no longer accept wire_api = "chat" at all, so a stale pin carried over from an old config can break the connection outright. Run codex --version and check which wire formats your installed build supports if a config that used to work stops connecting. The gateway itself still accepts both wire formats, so other OpenAI-shape clients that speak Chat Completions are unaffected.

Function tools round-trip fully, streamed or not. Two categories do not cross the gateway yet: namespaced tool groups (Codex sub-agents and MCP-app tools) and provider-hosted tools such as web_search and image_generation. The gateway drops those entries from the roster instead of forwarding them, so a Codex run that reaches for one falls back to its function tools rather than erroring the whole call.

On startup Codex refreshes model metadata from /v1/models. The gateway's response carries the top-level models array Codex reads alongside the standard OpenAI data array, so the refresh parses cleanly and routing is unaffected.

Codex sends its own system prompt and tool definitions; the gateway passes the prompt through untouched and routes on the full request. Each Codex turn is its own row in /requests; the gateway does not collapse a multi-turn session into one entry.