If you want Codex to use DeepSeek, the first instinct is usually to edit ~/.codex/config.toml:
|
|
That idea can work in some older versions or in regular OpenAI SDK scenarios. But with the current Codex CLI, it can easily run into a lower-level mismatch: custom model providers in Codex use the OpenAI Responses protocol, while DeepSeek’s official API is mainly exposed through an OpenAI-compatible Chat Completions interface.
My local version is currently codex-cli 0.111.0. codex --help shows support for configuration entry points such as --config, --model, and --profile. The official OpenAI Codex configuration reference is also explicit: model_providers.<id>.wire_api currently supports only responses, and defaults to responses when omitted.
DeepSeek’s official docs, meanwhile, show the call path as https://api.deepseek.com/chat/completions, with examples such as client.chat.completions.create(...). So the issue is not that DeepSeek cannot be called through OpenAI-style tooling. The issue is that the request semantics Codex sends are not exactly the same as what DeepSeek’s native API understands.
That is why changing base_url directly to https://api.deepseek.com may produce symptoms such as:
- The request path does not match, resulting in a 404 or an unexpected response format.
- Multi-turn conversations, tool calls, or patch generation fail during parsing.
tool_callsorder, message structure, or streaming event format does not line up.- The model seems able to answer a plain prompt, but starts failing once Codex does real work.
The steadier approach is to put a translation layer between Codex and DeepSeek. There are two common routes.
Method 1: Bridge DeepSeek Through a Local Gateway
A local gateway should do more than simple forwarding. Its job is to convert Responses-style requests from Codex into Chat Completions-style requests that DeepSeek can handle, then convert DeepSeek’s result back into a format Codex can consume.
If you use a local gateway such as ccx, the configuration idea looks roughly like this:
|
|
Then set the DeepSeek key in your terminal and start Codex with that profile:
|
|
In PowerShell:
|
|
There are two details to watch.
First, base_url should point to the gateway endpoint exposed to Codex, not the official DeepSeek address. The gateway calls DeepSeek behind the scenes.
Second, the correct value for env_key depends on how the gateway handles authentication. Some gateways read the official DeepSeek key directly. Others ask you to provide a local proxy key, while storing the DeepSeek key in the gateway backend. In that case, env_key should be changed to whatever environment variable the gateway expects.
This route is local and controllable, and it is easier to reason about latency and cost. The tradeoff is that you must confirm the gateway really supports the current Responses semantics used by Codex, rather than only acting as a basic Chat Completions proxy.
Method 2: Use OpenRouter BYOK as an Online Bridge
If you do not want to run a local gateway, OpenRouter BYOK is another option. BYOK means binding your own upstream provider key to OpenRouter, which then handles routing and forwarding.
The most common mistake here is the environment variable. Codex is calling OpenRouter, so env_key should usually be OPENROUTER_API_KEY, not DEEPSEEK_API_KEY. The DeepSeek key should be added in OpenRouter’s BYOK or provider key settings.
Example configuration:
|
|
Start it like this:
|
|
PowerShell:
|
|
Then add your DeepSeek provider key in the OpenRouter dashboard. OpenRouter’s BYOK documentation says provider keys are stored encrypted and used for routing to the corresponding provider.
This route saves you from maintaining a local gateway and feels more like using a regular third-party API proxy. The downside is that an online service sits in the middle, so troubleshooting may require checking Codex, OpenRouter, and DeepSeek error messages together.
Should You Keep Using the deepseek-chat Model Name?
In DeepSeek’s documentation as of May 2026, the recommended model names include deepseek-v4-flash and deepseek-v4-pro, with a note that compatibility aliases such as deepseek-chat and deepseek-reasoner will be deprecated after 2026-07-24.
For new configurations, it is better to test:
|
|
If you are using OpenRouter, follow OpenRouter’s model naming format, for example:
|
|
The actual available names depend on your gateway or OpenRouter’s model page. When the model name is wrong, errors usually look like model not found, 404, or the provider failing to find the matching endpoint.
Why Directly Setting DeepSeek’s Official base_url Is Not Recommended
You can certainly try this as an experiment:
|
|
But this is more of a debugging experiment than a stable setup. Codex talks to custom providers through the Responses protocol, while DeepSeek’s official examples use /chat/completions. If DeepSeek or Codex adds a full compatibility layer later, direct connection may become simple. Until then, a bridge layer is more reliable.
What If Codex Still Uses OpenAI After Editing the Config?
First, confirm the config file location. The global config should be:
|
|
The project-level .codex/config.toml is not the right place for machine-level provider settings such as model_provider and model_providers. The official OpenAI docs also note that project-level configuration does not override local provider and authentication fields.
If Codex still asks you to log in through the web, or appears to use the default OpenAI model, log out first:
|
|
Some older tutorials write this as /logout inside the interactive UI. With the current CLI, running codex logout directly in the terminal is the more reliable option.
You can also run a quick check with a temporary profile:
|
|
Or:
|
|
If that works, the config itself is readable. If it does not, check the profile name, TOML syntax, and whether the environment variable only exists in the current shell session.
Troubleshooting Checklist
401: The key is wrong, orenv_keypoints to the wrong environment variable.404:base_urlor the model name is wrong, or a Responses request is being sent to an endpoint that only supports Chat Completions.tool_calls, patch, or streaming parse errors: the protocol bridge is likely incomplete.- Still prompted to log in to OpenAI: run
codex logout, then confirm you are using the correct profile. - PowerShell environment variable disappears in a new window:
$env:...only applies to the current session. Use user environment variables if you need it to persist. - OpenRouter BYOK is not using your own DeepSeek key: check whether the provider key is bound in OpenRouter, whether the current OpenRouter API key is allowed to use it, and whether fallback is enabled.
Conclusion
Using DeepSeek with Codex is not impossible through config.toml. The catch is that changing only base_url is usually not enough.
The two steadier routes today are:
- Use a local gateway as a protocol bridge: Codex talks to the local gateway, and the gateway talks to DeepSeek.
- Use OpenRouter BYOK as an online proxy: Codex talks to OpenRouter, while the DeepSeek key is bound in the OpenRouter dashboard.
If you only want a quick test, OpenRouter is easier. If you want tighter control over keys, cost, and logs, a local gateway is better for long-term tinkering.
References: