Codex Custom Model Providers: GLM-5.3, Mistral and Ollama

TL;DR
Codex only speaks the Responses API now. Tested config.toml blocks for GLM-5.3, Mistral Large 4 through a gateway, local Ollama and an internal proxy.
Last updated: October 9, 2026
To use a custom model provider in Codex, add a [model_providers.<id>] table to ~/.codex/config.toml with a base_url that ends in /v1, an env_key, and wire_api = "responses", then set model_provider and model. The catch in late 2026: Codex only speaks the OpenAI Responses API, so the endpoint must serve /v1/responses.
That one requirement decides everything below. Z.ai ships a Responses endpoint for GLM-5.3, and Ollama has served one since v0.13.3, so both plug in directly. Mistral's API reference lists Chat Completions and Conversations but no Responses endpoint, so Mistral Large 4 goes through a translating gateway. Older guides that set wire_api = "chat" now fail at startup.
Every provider block on this page was loaded by Codex CLI 0.162.0 (the current npm release on October 9, 2026) and run once with codex exec, with base_url swapped for a local mock Responses server that logged what Codex actually sent. That proves the wiring: path, auth header, custom headers, model ID and reasoning fields. It does not prove model quality, and we did not hold live Z.ai or Mistral keys for this run. The one block we did not run is the token-command auth example, which is copied from the docs.
The verified base block#
# ~/.codex/config.toml
model_provider = "zai"
model = "glm-5.3"
[model_providers.zai]
name = "Z.ai"
base_url = "https://api.z.ai/api/v1"
env_key = "ZAI_API_KEY"
wire_api = "responses"
export ZAI_API_KEY="..."
codex
Here is what each key does, checked against the Codex configuration reference:
| Key | What it does | What we saw in the test |
|---|---|---|
base_url | API root for the provider | Codex appends /responses, so .../api/v1 became POST /api/v1/responses |
env_key | Env var holding the API key | Sent as Authorization: Bearer <value> |
wire_api | Protocol | responses is the only supported value and the default; "chat" is a hard error |
http_headers | Static headers | Arrived on every request |
env_http_headers | Headers read from env vars | Arrived with the env var's value |
request_max_retries / stream_max_retries | Retry counts | Defaults 4 and 5 per the reference |
stream_idle_timeout_ms | SSE idle timeout | Default 300000 (5 minutes) |
Three rules from the advanced config docs save most debugging time:
- Reserved IDs.
openai,ollamaandlmstudioare built in. Defining[model_providers.ollama]yourself stops Codex at startup. - User config only. Codex ignores
model_provider,model_providersandopenai_base_urlin a project's.codex/config.tomland prints a warning. A cloned repo cannot reroute your agent to a different model host. - Proxying OpenAI itself needs no provider. If you only want OpenAI models through a gateway or a data-residency host, set
openai_base_url = "https://us.api.openai.com/v1"instead of defining a new provider.
For a one-off test without editing the file, -c overrides work. We ran this and Codex hit the overridden URL with the overridden model:
codex exec -c 'model_providers.zai.base_url="https://api.z.ai/api/v1"' -m glm-5.3 "summarize the test commands in this repo"
Z.ai GLM-5.3#
Z.ai's Codex setup page says Codex needs its dedicated Responses endpoint, https://api.z.ai/api/v1, and adds a second file most guides skip: a model catalog. Without it, Codex 0.162.0 prints this on every run:
warning: Model metadata for `glm-5.3` not found. Defaulting to fallback metadata; this can degrade performance and cause issues.
That warning is not cosmetic. In our logged requests, the fallback metadata sent nine tools and no apply_patch tool, so the model has to edit files through shell commands. With Z.ai's catalog loaded, Codex added apply_patch as a freeform tool and passed the configured reasoning effort through unchanged (we tested max, which arrived as reasoning: {"effort": "max"}).
Save Z.ai's catalog as ~/.codex/models.json. This is their published entry, unchanged:
{
"models": [
{
"slug": "glm-5.3",
"display_name": "glm-5.3",
"description": "Z.ai's latest flagship model",
"default_reasoning_level": "max",
"supported_reasoning_levels": [
{ "effort": "low", "description": "Light reasoning" },
{ "effort": "high", "description": "Enhanced reasoning" },
{ "effort": "max", "description": "Deep reasoning" }
],
"shell_type": "shell_command",
"visibility": "list",
"supported_in_api": true,
"priority": 0,
"base_instructions": "",
"supports_reasoning_summaries": true,
"default_reasoning_summary": "none",
"support_verbosity": false,
"apply_patch_tool_type": "freeform",
"truncation_policy": { "mode": "bytes", "limit": 10000 },
"context_window": 1048576,
"max_context_window": 1048576,
"effective_context_window_percent": 95,
"supports_parallel_tool_calls": true,
"experimental_supported_tools": [],
"input_modalities": ["text"]
}
]
}
Then point the config at it:
model_provider = "zai"
model = "glm-5.3"
model_reasoning_effort = "high"
model_catalog_json = "~/.codex/models.json"
[model_providers.zai]
name = "Z.ai"
base_url = "https://api.z.ai/api/v1"
env_key = "ZAI_API_KEY"
wire_api = "responses"
One deliberate change from Z.ai's page: their example puts the key in experimental_bearer_token. The Codex reference marks that field "discouraged; use env_key", and env_key produced the same Bearer header in our test without leaving a secret in a dotfile.
On cost, Z.ai's pricing page lists per million tokens:
| Model | Input | Cached input | Output |
|---|---|---|---|
| GLM-5.3 | $1.40 | $0.26 | $4.40 |
| GLM-5.3-FlashX | $0.37 | $0.075 | $1.25 |
| GLM-5.3-Flash | $0.15 | $0.03 | $0.50 |
The catalog declares three effort levels: low, high and max, with max as the default. Reasoning tokens bill as output, so high or low is the cost lever for routine edits. Z.ai's Codex page is written for GLM Coding Plan keys; if you pay per token, confirm your key is accepted on that endpoint before you debug anything else. Plan tiers and third-party hosts are compared in where to run GLM-5.3 free and cheap.
Mistral Large 4 (through a gateway)#
The Codex docs still show a Mistral provider with base_url = "https://api.mistral.ai/v1". With wire_api now fixed to responses, that block makes Codex call https://api.mistral.ai/v1/responses. The Mistral Large 4 model page lists the model on /v1/chat/completions and /v1/conversations, and we found no Responses endpoint in the API reference. Treat the docs snippet as a shape example, not a working Mistral config.
The route that works today is a gateway that serves /v1/responses and translates to Chat Completions upstream. LiteLLM's proxy does this for every provider it supports. A minimal litellm.yaml:
model_list:
- model_name: mistral-large-4
litellm_params:
model: mistral/mistral-large-4
api_key: os.environ/MISTRAL_API_KEY
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY
export MISTRAL_API_KEY="..."
export LITELLM_MASTER_KEY="sk-local-..."
litellm --config litellm.yaml --port 4000
And the Codex side:
model_provider = "mistral_gw"
model = "mistral-large-4"
model_context_window = 1000000
[model_providers.mistral_gw]
name = "Mistral via LiteLLM"
base_url = "http://127.0.0.1:4000/v1"
env_key = "LITELLM_MASTER_KEY"
wire_api = "responses"
We ran this chain end to end with LiteLLM 1.104.2 and a mock Mistral-style upstream: Codex posted to the proxy's /v1/responses, LiteLLM answered 200, and the upstream received a streaming POST /v1/chat/completions for mistral-large-4 with the Mistral key as the bearer token. The translation is visible in the tools: Codex's grouped namespace tool arrived flattened into plain functions (multi_agent_v1__spawn_agent and its siblings), and only function tools reached the upstream. That is the behavior you want from a bridge, but it is also why a bridge is a compatibility layer, not a native endpoint. If edits misbehave, look at the gateway log before blaming the model.
For the test we added an api_base line pointing at the mock. The YAML above leaves it out, so LiteLLM's mistral/ prefix sends requests to Mistral's hosted API.
Why bother: Mistral lists Large 4 as a public preview with a 1M context window, 52B active and 1.05T total parameters, at $1.36 input and $4.18 output per million tokens, shown at a sale price of $0.68 and $2.09 when we checked. Mistral's launch post reports 61.7% on DeepSWE v1.1 and 28.3% on Terminal-Bench 4, and says weights land at the end of October. Those are vendor numbers. Our Mistral Large 4 breakdown covers what they do and do not prove.
Local Ollama#
Ollama added POST /v1/responses in v0.13.3, with streaming and function tools, but only the stateless flavor: no previous_response_id. Every request Codex sent in our logs had store: false, so it does not lean on server-side state and that limit does not bite.
The fastest path is built in. Ollama's Codex page documents both:
ollama launch codex # writes a Codex profile and model catalog, then starts Codex
codex --oss -m gpt-oss:120b # use the built-in ollama provider directly
If you want a named provider instead (another port, another machine, or a model you pin in config), give it a non-reserved ID:
model_provider = "local_ollama"
model = "qwen3.5:27b"
model_context_window = 65536
[model_providers.local_ollama]
name = "Local Ollama"
base_url = "http://localhost:11434/v1"
wire_api = "responses"
No env_key is needed for a local server, and our logged request carried no Authorization header. The number to get right is context. Ollama's context length docs default to 4k on GPUs under 24 GiB, 32k on 24-48 GiB and 256k at 48 GiB or more, and say agents and coding tools need at least 64000 tokens. Codex's own instructions and tool definitions take a large slice of that before your code does, so a 4k default truncates almost immediately. Set it on the server:
OLLAMA_CONTEXT_LENGTH=65536 ollama serve
Then tell Codex the same number with model_context_window, so its compaction triggers before the server starts silently dropping tokens. For which local models are worth the effort, see the best local coding LLMs.
Internal proxy or gateway#
This is the enterprise shape: one gateway owns keys, logging, budgets and routing, and developers keep the Codex workflow.
model_provider = "company_proxy"
model = "gpt-6.1-sol"
[model_providers.company_proxy]
name = "Company LLM gateway"
base_url = "https://llm-gateway.internal.example.com/v1"
env_key = "COMPANY_LLM_KEY"
wire_api = "responses"
http_headers = { "X-Client" = "codex" }
env_http_headers = { "X-Team" = "CODEX_TEAM" }
export COMPANY_LLM_KEY="..."
export CODEX_TEAM="platform"
codex exec "review the staged diff and list the risky changes"
In our run both headers reached the server: X-Client: codex and X-Team: platform. If your gateway issues short-lived tokens, the docs support a command-backed credential instead of env_key:
[model_providers.company_proxy.auth]
command = "/usr/local/bin/fetch-codex-token"
args = ["--audience", "codex"]
timeout_ms = 5000
refresh_interval_ms = 300000
The command must print the token to stdout, and the docs say not to combine it with env_key, experimental_bearer_token or requires_openai_auth. Whatever the gateway is, it must serve /v1/responses. The Codex team's deprecation notice told platform teams exactly that before the February 2026 cutoff.
What breaks#
These are the failures we reproduced on Codex 0.162.0, plus the ones the docs and issue tracker document.
| Symptom | Cause | Fix |
|---|---|---|
Error loading config.toml: `wire_api = "chat"` is no longer supported. | Old guide or old config | Set wire_api = "responses" and point at a Responses endpoint or gateway |
model_providers contains reserved built-in provider IDs: ollama | Redefined a built-in | Rename to local_ollama or similar |
ERROR: Missing environment variable: `ZAI_API_KEY`. | Key exported in another shell | Export it where Codex runs, or use the auth command |
| 404 on every turn | base_url without /v1 | Codex posts to base_url + /responses; our no-/v1 test hit POST /responses |
Model metadata ... not found warning, model never uses apply_patch | No catalog entry for a non-OpenAI model | Add a model_catalog_json entry, as Z.ai and Ollama's launcher do |
unknown variant `function`, expected `freeform` | Catalog asks for function-style apply_patch | Only freeform parses in 0.162.0; if your server cannot take freeform tools, drop the catalog entry and let edits go through the shell |
Incorrect role information (Z.ai error 1214) | Codex sends developer messages; Z.ai's Chat Completions endpoint rejected them in issue #9612 | Use Z.ai's Responses endpoint, https://api.z.ai/api/v1 |
| Session forgets earlier files or loops | Server context smaller than the conversation | Raise the server limit and match model_context_window; tune model_auto_compact_token_limit |
model_verbosity does nothing | The docs say it applies only to Responses providers, and the model must support it | Expected for GLM; Z.ai's catalog sets support_verbosity: false |
The tool-call mismatches are the subtle ones. Codex sends more than plain function tools: in our logs the fallback request mixed function and namespace tool types, and the GLM catalog added a custom (freeform) tool for apply_patch. A server that only understands function tools may reject the request or drop those tools. When a provider "connects but never edits", log the request at the gateway and check which tool types it is receiving.
Which route to pick#
| You want | Use | Why |
|---|---|---|
| Cheapest strong cloud model in Codex | GLM-5.3 or GLM-5.3-Flash on Z.ai's Responses endpoint | Native endpoint, official catalog, $0.15 input on Flash |
| Mistral Large 4 | LiteLLM (or your existing gateway) in front of Mistral | No native Responses endpoint in Mistral's docs today |
| Offline or private | ollama launch codex, or a named provider with 64k+ context | Native /v1/responses, no key |
| Team-wide control | Internal gateway that serves /v1/responses | Central keys, headers, budgets, logging |
| OpenAI models through a proxy | openai_base_url | No custom provider needed |
As a rough cost check using the published list prices: a long Codex session that reads 1M input tokens and writes 100k output costs about $1.84 on GLM-5.3 ($1.40 + $0.44), $0.20 on GLM-5.3-Flash, and $1.78 on Mistral Large 4 at list price. Cached input is far cheaper ($0.26 on GLM-5.3), and an agent session rereads the same context turn after turn, so cache hits move the real bill more than the sticker price. Compare that with what your ChatGPT plan already includes in Codex usage limits and pricing.
Start with one provider, run the same small task set you already trust, and keep the diffs:
codex exec "Read this repo and list the test commands. Do not edit files."
codex exec "Add one regression test for the smallest parser edge case you can find."
git diff --stat
A model that connects is not the same as a model that finishes. The second command is the real test, because it needs the edit tools to work end to end. For running the same providers unattended, see Codex exec in CI.
What people are actually saying#
- The cutoff was announced, not sprung. A Codex maintainer posted the chat/completions deprecation on December 9, 2025, with removal slated for early February 2026, and told teams running gateways to make sure they serve the Responses API. A January commenter thought support was already gone in 0.84.0; the maintainer said it stayed until February 1, and that corner-case regressions in the old path would likely be left unfixed.
- Bridges work for the basics. In the same thread, one developer built a local bridge that maps Responses requests to Chat Completions and says plain text and function calling map cleanly, but stored state, hosted tools, reasoning items and streaming lifecycle events all need explicit handling. Another commenter, who maintains one such proxy, wrote on October 7, 2026 that chat-only providers such as DeepSeek and GLM still work this way, and that they checked Codex 0.160 editing a file and running a shell command through it.
- Role mapping was the classic GLM failure. Issue #9612 documents Z.ai's chat endpoint rejecting Codex's
developerrole in January 2026. It was closed as not planned, which is why Z.ai's own Codex page now points at a dedicated Responses endpoint. - The counter-case: stale guides still rank. A Don't Panic Labs walkthrough from August 2026 defines
[model_providers.ollama], which Codex 0.162.0 rejects as a reserved ID. And the skeptic view from the original Hacker News thread on Codex with open models (April 2025) still holds: Codex's prompts and tool loop are tuned for large hosted models, and small local models often need a different setup entirely.
FAQ#
Does Codex still support wire_api = "chat"?#
No. The configuration reference says responses is the only supported value and the default. Codex 0.162.0 refuses to load a config that sets "chat" and points to the deprecation discussion. A Chat Completions-only provider needs a gateway that serves /v1/responses.
How do I use GLM-5.3 in Codex?#
Point a custom provider at https://api.z.ai/api/v1 with wire_api = "responses", set model = "glm-5.3", and add Z.ai's model catalog through model_catalog_json. Without the catalog, Codex falls back to generic metadata and leaves out the apply_patch tool.
Can Codex call the Mistral API directly?#
Not as of October 9, 2026, as far as Mistral's docs show. Codex calls <base_url>/responses, and Mistral documents Chat Completions and Conversations, not Responses. Put a translating gateway such as LiteLLM in front and point Codex at the gateway.
Can I name my provider ollama?#
No. openai, ollama and lmstudio are reserved, and Codex stops at startup if you redefine one. Use codex --oss, ollama launch codex, or a custom ID like local_ollama.
Why does my local model read files but never edit them?#
Usually context or tools. Make sure the server context is at least 64k and matches model_context_window, and check whether the model received an apply_patch tool. Without a catalog entry it does not, so edits must go through shell commands.
Can a repo's .codex/config.toml switch my model provider?#
No. Codex ignores model_provider, model_providers and openai_base_url in project config and prints a warning. Provider settings belong in ~/.codex/config.toml.
Continue Reading#
- Where to run GLM-5.3 free and cheap - Coding Plan tiers, Flash pricing and third-party hosts
- Mistral Large 4 is the open-weight frontier test - what the launch claims do and do not prove
- The best local coding LLMs - which models are worth pointing Codex at offline
- Codex exec in CI - running custom providers unattended
- Model routers and the optionality advantage - why a gateway in front of every provider pays off
- Codex vs Claude Code: June 2026 - where Codex fits in an agent-first workflow
- GLM 5.2 vs DeepSeek v4 vs Qwen3: Open-Weights Coding Showdown - the models worth pointing Codex at
- Sign in with ChatGPT: Run Coding Agents on Your Plan - how the plan-usage flow works and the per-app cap to set
- Codex - OpenAI's coding agent: plans, install routes, and how it compares
- OpenAI Codex course - the CLI, cloud tasks, and IDE extension, hands-on and grounded in the official docs
- How to Use Claude Code and Codex With Meta Muse: Every Setup That Actually Works - running Claude Code and Codex on Muse Spark 1.3 through the Meta Model API, from OpenCode Go, and inside Muse Code
Sources#
- Codex advanced configuration: custom model providers (formerly developers.openai.com/codex/config-advanced)
- Codex configuration reference
- Codex CLI documentation
- Deprecating chat/completions support in Codex, discussion #7782
- Z.AI GLM-4.7 integration issue, openai/codex #9612
- Z.ai: Codex setup
- Z.ai pricing
- Mistral API reference
- Mistral Large 4 model page
- Introducing Mistral Large 4
- LiteLLM /responses endpoint
- Ollama OpenAI compatibility
- Ollama: Codex integration
- Ollama: context length
- @openai/codex on npm (version 0.162.0 used for the tests above)
Get the next deep dive like this in your inbox
One email a week on Codex and the rest of the AI dev stack. Free.
Read next on AI coding tools
GLM-5.3 Free and Cheap: Every Route and Price (October 2026)
GLM-5.3 has no free hosted tier. Cheapest on October 9: Wafer via OpenRouter at $0.049/$3.39, Flash from $0.075/$0.25. Z.ai's promos ended October 7.
13 min readMistral Large 4: Specs, Pricing, Benchmarks and Weights Date
Mistral Large 4 is a 1T-parameter multimodal MoE with 52B active, in public preview at $0.68/$2.09 per million tokens, with open weights due end of October.
14 min readCodex Exec in CI: Practical Guide to Headless OpenAI Agents
codex exec is OpenAI's non-interactive mode to run Codex agents from scripts, CI and GitHub Actions. How to set it up safely with real flags and working YAML.
9 min readNew here? Start with
Technical content at the intersection of AI and development. Building with AI agents, Claude Code, and modern dev tools - then showing you exactly how it works.








