Codex CLI 接入第三方模型:config.toml 里的 wire_api 是个坑(2026)

Codex CLI 通过 ~/.codex/config.toml 里的 [model_providers.<id>] 段接入任意 OpenAI 兼容端点;最容易翻车的字段是 wire_api——它决定请求发到 /responses 还是 /chat/completions,选错了表现是 404 或 400,而不是优雅的报错。 判据只有一条:上游是不是原生 Responses API? 官方 OpenAI 用 wire_api = "responses",绝大多数第三方兼容网关和本地模型(DeepSeek、阿里云百炼、OpenRouter、Ollama、new-api 之类)只提供 /chat/completions,必须写 wire_api = "chat"。下面给一份可直接用的配置模板和实测过的排错顺序。

上面这段就是全文的结论块,可以直接拿走。下面是装、配、排错。

Codex CLI 到第三方模型的路径

Codex CLI 是什么?和 Claude Code 有什么区别?

Codex CLI 是 OpenAI 出的终端编程智能体,和 Claude Code 属于同一类工具:读你的仓库、改文件、跑命令。 定位差别在配置模型上——Claude Code 主要靠环境变量(ANTHROPIC_BASE_URL 等)指向自定义后端,Codex CLI 则用一份 TOML 描述多个 provider 和多个 profile,可以在同一台机器上"切换着用"。

维度 Codex CLI Claude Code
配置载体 ~/.codex/config.toml ~/.claude/settings.json + 环境变量
多后端 原生支持多 provider + profile 切换 靠环境变量切,通常一套一套改
项目级配置 支持 .codex/config.toml(需信任项目) 支持项目级 CLAUDE.md
接第三方 自定义 provider,注意 wire_api 只要兼容 Anthropic API 即可

两个都接第三方模型的完整做法我都跑过,Claude Code 那篇在这里。如果你已经在用 new-api 这类聚合网关,那 Codex CLI 接它一个端点就能把上游模型全用上。

Codex CLI 怎么装、怎么跑?

# 1) 装(需要 Node 18+)
$ npm install -g @openai/codex
$ codex --version

# 2) 登录官方账号(用官方模型时)
$ codex login

# 3) 直接在项目目录里跑
$ cd ~/projects/my-app
$ codex                       # 交互式
$ codex exec "把 src/utils.py 里的重复代码合并成一个函数"   # 非交互

装完先跑一次 codex --version 并记下版本号——Codex CLI 迭代很快,TOML 的字段名在版本之间有过调整,遇到不认识的键时先对照 codex --help 和当前版本的官方配置文档。

步骤 1:安装与验证

config.toml 怎么写?一份可直接用的模板

结论:把官方 provider 留作默认,第三方按业务分组写进 model_providers,再用 profiles 做"一套配置一个场景"。 下面这份模板在 ~/.codex/config.toml:

# ---- 默认走官方 ----
model = "gpt-5"
model_provider = "openai"

# ---- 第三方 provider:注意 wire_api ----
[model_providers.deepseek]
name = "DeepSeek"
base_url = "https://api.deepseek.com/v1"
env_key = "DEEPSEEK_API_KEY"
wire_api = "chat"          # 兼容端点走 /chat/completions
request_max_retries = 4

[model_providers.dashscope]
name = "阿里云百炼(OpenAI 兼容)"
base_url = "https://dashscope.aliyuncs.com/compatible-mode/v1"
env_key = "DASHSCOPE_API_KEY"
wire_api = "chat"

[model_providers.local_ollama]
name = "本地 Ollama"
base_url = "http://localhost:11434/v1"
wire_api = "chat"          # 本地模型不需要 key

[model_providers.mynewapi]
name = "自建聚合网关"
base_url = "https://api.example.com/v1"
env_key = "NEWAPI_KEY"
wire_api = "chat"

# ---- profile:一套配置一个场景 ----
[profiles.deepseek]
model = "deepseek-chat"
model_provider = "deepseek"

[profiles.local]
model = "qwen2.5-coder:14b"
model_provider = "local_ollama"

# ---- 沙箱与审批 ----
approval_policy = "on-request"
sandbox_mode = "workspace-write"

[sandbox_workspace_write]
network_access = false

把 key 交给环境变量(env_key 指的是变量名,不是密钥本身):

$ echo 'export DEEPSEEK_API_KEY="sk-你的key"' >> ~/.bashrc && source ~/.bashrc

然后按 profile 启动:

$ codex --profile deepseek
$ codex --profile local exec "解释一下这个函数的算法复杂度"

两个硬性限制:model_provider 和 openai_base_url 这类键不允许被项目级 .codex/config.toml 覆盖——这是官方故意的设计,防止你 clone 的仓库把请求悄悄导向别处。所以想换后端,只能在用户级配置或命令行里改。

步骤 2:写 config.toml

wire_api 到底该填哪个?

结论:先看上游文档的端点路径,再决定取值。 判据表:

上游情况 wire_api 原因
OpenAI 官方 API responses 官方原生支持 Responses API
兼容网关标注 "OpenAI 兼容" chat 通常只实现 /v1/chat/completions
DeepSeek / 百炼 / OpenRouter chat 走 chat completions
本地 Ollama / LM Studio chat 兼容层只提供 chat completions
自建 new-api / one-api 类网关 chat 透传 chat completions

写错的症状:填 responses 打一个只有 chat 端点的上游,返回 404(路径不存在)或者 400(请求体结构不符);反过来填 chat 打官方 Responses,工具调用会退化,复杂任务的工具链容易断。排错时不要猜,直接打一次上游端点看路径存不存在:

# 判据 1:上游是否提供 /responses
$ curl -s -o /dev/null -w "%{http_code}\n" \
    -X POST https://api.deepseek.com/v1/responses \
    -H "Authorization: Bearer $DEEPSEEK_API_KEY" -d '{}'
# 404 → 只有 chat 端点,wire_api 用 "chat"

# 判据 2:判据 1 之外,直接看 chat 端点是否通
$ curl -s https://api.deepseek.com/v1/chat/completions \
    -H "Authorization: Bearer $DEEPSEEK_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"model":"deepseek-chat","messages":[{"role":"user","content":"hi"}]}' | head -c 300

步骤 3:判定并验证 wire_api

怎么验证真的通了?

结论:别只看"能对话",要验证工具调用——那是编程智能体的核心能力。 一个能对话但工具调用退化的配置,用起来会在改文件时突然卡死。

# 1) 确认当前生效的 provider
$ codex --profile deepseek exec "只回答你正在使用哪个模型名"

# 2) 验证工具调用:让它读一个文件
$ codex --profile deepseek exec "读一下 README.md,用一句话总结" --cd ~/projects/my-app

# 3) 验证写权限(沙箱配 workspace-write 时)
$ codex --profile deepseek exec "在项目根目录建一个 hello.txt,内容写 ok"
$ cat ~/projects/my-app/hello.txt

三条都过,说明这个后端不只是"能聊天",而是能完成"读—改—跑"的完整循环。

步骤 4:验证工具调用

三个真会踩的坑

  1. provider id 撞了保留名:openai、ollama、lmstudio 这三个 id 是内置保留的,自定义 provider 用它们会加载失败。想接 Ollama 用 local_ollama 这种名字,别叫 ollama。
  2. 项目级配置需要"信任"才生效:.codex/config.toml 在项目里必须先把该目录标记为信任才会被加载。现象是"我在项目里配了 profile 却不生效"——查一下信任状态,别在 TOML 语法上找半天。
  3. 沙箱把网络关了,工具调用看着像卡住:模板里 network_access = false 是默认安全姿势,但脚本里要 pip install 或者 curl 时会静默失败。要么临时把 sandbox_mode 调成 danger-full-access(只在你信任的目录用),要么显式开 [sandbox_workspace_write] network_access = true。

Codex CLI 常见问题(2026)

Q:没有 OpenAI 账号,能只用第三方模型吗?
A:能。把 model + model_provider 指向自定义 provider、key 用环境变量提供即可,不需要走 codex login。本地的 Ollama 连 key 都不需要。

Q:一份 config.toml 能配多少个 provider?
A:没有实际限制。典型做法是官方一个、国内一个、本地一个,用 profile 切换。别把 key 直接写进 TOML,用 env_key 指环境变量名。

Q:wire_api = "responses" 到底什么时候用?
A:只在确认上游原生实现了 Responses API 时用。判断方法就是上面那条 curl -o /dev/null -w "%{http_code}" 打 /responses,返回 404 就不要用。

Q:接了第三方模型,工具调用不稳定怎么办?
A:优先换 wire_api = "chat" 再测;仍不稳就换模型——小模型的 function calling 支持差异很大。想统一入口和模型路由,可以在前面放一层 new-api 聚合。

Q:和 Claude Code 哪个更值得用?
A:两个都留着不冲突。Codex CLI 的多 provider + profile 更适合"同一台机器上到处切后端";想要 本地模型 那种离线兜底,两边都能接。

Q:base_url 结尾要不要带 /v1?
要。绝大多数兼容网关的完整前缀是 https://host/v1,Codex CLI 不会帮你补。少了 /v1 最常见的症状是 404;多了斜杠(/v1/)在某些网关上也会出问题。照着上游文档一字不差地抄,别自己改。

Q:换 provider 后历史会话还能用吗?
上下文本身在客户端,换 provider 不丢;但不同模型的工具调用格式不一致,跨模型续接同一任务偶发中断。稳妥做法是换 provider 时开新会话。

一句总结

Codex CLI 接第三方模型,90% 的失败都出在 wire_api 这一个字段上:先确认上游的端点路径,再定取值,然后用"读文件 + 写文件 + 跑命令"三条验证工具调用。配置这件事真正的成本不在写,而在于知道该验哪三条。

相关阅读

上一篇 Cloudflare Tunnel 实战:零开放端口把内网服务暴露到公网(2026)