返回博客

让 Codex CLI 使用任意模型:OpenRouter、DeepSeek、Ollama

2026年10月14日AutoJev

Codex 只说 OpenAI Responses 协议。本文介绍如何借助本地网关把 Responses 转换为 Chat Completions,让 Codex 用上 OpenRouter、DeepSeek、Ollama 或任意 OpenAI 兼容模型,以及 ~/.codex/config.toml 里写入了什么。

Codex CLI 是 OpenAI 推出的终端编程智能体,速度快、可脚本化,擅长多步骤代码修改。但它围绕一种协议构建:OpenAI Responses API。问题在于,DeepSeek、OpenRouter、Ollama,以及 vLLM 这类自部署服务,最普遍提供的仍然是 Chat Completions 协议。

本文介绍如何用 AutoJev 让 Codex 跑在这些模型上。AutoJev 是一款免费、开源的桌面应用,在本机运行一个本地网关 http://127.0.0.1:9527/v1,并负责协议之间的转换。读完本文,你将:

  • 一键把 Codex 接入本地网关;
  • 在 Codex 里看到一份包含所有已选模型和路由的模型目录;
  • 让 OpenRouter、DeepSeek 和本机 Ollama 模型并存可用;
  • 搞清楚哪些 Responses 功能可以转换、哪些不行。

协议之间的鸿沟

Codex 发出的是 POST /v1/responses 请求。Responses 对输入项、工具定义(包括自定义工具)、工具调用输出和流式事件都有自己的结构;而 Chat Completions 把同样的对话表示成一组带 tool_calls 的消息,流式增量的格式也不同。

只支持 Chat Completions 的模型无法直接回应 Responses 请求。必须有人在入口把请求翻译过去,在出口把流式事件翻译回来——同时保证工具调用 ID 稳定,因为 Codex 要靠它把工具结果对应到发起调用的那一步。

这正是 AutoJev 的工作:

Codex ──Responses──▶ AutoJev(127.0.0.1:9527/v1)──▶ Chat Completions 上游
                                                ──▶ Responses 上游(原生)
                                                ──▶ Anthropic Messages 上游

如果模型的上游本来就支持 Responses,请求会原样透传;否则 AutoJev 会完成转换,调用服务商的 /v1/chat/completions(或 /v1/messages),再把响应转换回 Responses 事件。

第一步:安装 AutoJev 并添加服务商

从下载页下载 AutoJev(macOS、Windows x64、Linux x64),打开后网关会在 9527 端口启动。

在「服务商」中添加你需要的服务商,预设会自动填好地址:

预设接口地址
OpenRouterhttps://openrouter.ai/api
DeepSeekhttps://api.deepseek.com
Ollamahttp://127.0.0.1:11434
OpenAIhttps://api.openai.com/v1

其他服务——Kimi(Moonshot)、GLM(智谱)、Qwen(DashScope)、SiliconFlow、vLLM、LM Studio——可以用「OpenAI 兼容」或「Anthropic 兼容」填入对应地址。本机 Ollama 一般不需要密钥。添加后逐个点击测试。

如果你的服务商配置已经在 CC Switch 或 Termany 里,直接导入即可。AutoJev 会读取 ~/.cc-switch/cc-switch.db 或 ~/.termany/termany.db,并按接口地址去重。

第二步:添加模型,选对 API 类型

在「模型」中为每个模型添加一条记录。最关键的字段是 API 类型,它描述的是上游,而不是 Codex:

服务商模型 ID 示例API 类型
OpenRouterqwen/qwen3-coder-flashchat_completions
OpenRouteranthropic/claude-sonnet-4chat_completions
DeepSeekdeepseek-chatchat_completions
Ollamaollama list 中显示的模型名chat_completions
OpenAI支持 Responses 的模型responses

常见误区是:因为 Codex 用 Responses,就把所有模型都设成 responses。千万别这样——AutoJev 需要知道上游的真实格式,才能正确转换。

再填上每百万 token 的输入、输出和缓存价格,让「用量」页面能估算费用。然后跑一次测速:AutoJev 会对每个模型发送三次简短的流式请求,记录首字延迟和每秒输出 token 数。定时测速默认开启(每 30 分钟一次),为速度优先路由提供最新数据。

第三步:创建路由(可选,但推荐)

Codex 可以直接连接单个模型,但用路由的好处是:以后换模型不用再动 Codex 的配置。在「路由」中可以这样建:

  • fast:智能选择,偏好设为速度优先。AutoJev 根据近期测速数据在本地选择,不调用 Jev。
  • cheap:智能选择,偏好设为成本优先。AutoJev 选出满足能力要求、费用最低的候选。打开「优先使用本地模型」,符合条件时会优先用 Ollama。
  • quality:智能选择,偏好设为质量优先。由 OpenRouter 上的 Jev 决策模型来选,只发送路由元数据,不发送对话内容。

路由对智能体显示为 autojev/fast、autojev/cheap、autojev/quality;单个模型显示为 <服务商 ID>/<模型 ID>,例如 deepseek/deepseek-chat。

第四步:接入 Codex

打开「智能体」,AutoJev 会在 ~/.codex/config.toml 检测到 Codex。选择一个或多个模型和路由,指定默认项,点击「连接」。AutoJev 会先备份原文件,然后写入:

toml
model = "autojev/fast"
model_provider = "autojev"
model_catalog_json = "/Users/you/.codex/autojev-models.json"
web_search = "disabled"
 
[model_providers.autojev]
name = "AutoJev"
base_url = "http://127.0.0.1:9527/v1"
wire_api = "responses"
 
[model_providers.autojev.http_headers]
x-autojev-agent = "codex"

逐行说明:

  • model:Codex 启动时使用的默认模型或路由。
  • model_provider = "autojev" 与 [model_providers.autojev]:让 Codex 以 Responses 格式把请求发往本地网关。
  • x-autojev-agent = "codex":给请求打上标签,「日志」和「用量」就能按智能体拆分。
  • web_search = "disabled":关闭 Codex 的托管联网搜索,因为托管工具无法转换给 Chat Completions 或 Messages 模型。
  • model_catalog_json:指向 AutoJev 写入的另一个文件 ~/.codex/autojev-models.json。

这份目录列出了你选中的所有模型和路由,方便在 Codex 内部切换。精简后的单条记录如下:

json
{
  "models": [
    {
      "slug": "autojev/fast",
      "display_name": "Fast",
      "description": "AutoJev · fast",
      "visibility": "list",
      "supported_in_api": true,
      "input_modalities": ["text", "image"],
      "supports_search_tool": false,
      "apply_patch_tool_type": "freeform"
    }
  ]
}

config.toml 中的其他设置都会保留。如果 Codex 正在运行,重启后试一下:

bash
codex "给注册接口加上输入校验,并补一个测试"

在 AutoJev 的「日志」里可以看到:智能体、路由 ID、实际响应的模型和服务商、token 数、首字节与总耗时、预估费用;详情页还会列出每一次上游尝试。

能转换的部分

AutoJev 支持 Responses、Chat Completions、Anthropic Messages 三者之间全部六个方向的转换。对“Codex + Chat Completions 模型”来说,关键能力都已覆盖:

  • 系统指令和完整的对话历史;
  • 函数工具、工具选择、工具调用与工具输出,调用 ID 保持稳定;
  • Responses 自定义工具:转换为只有一个字符串参数 input 的函数,返回时再解码回自定义工具输入。上游函数接口不会强制执行语法约束;
  • 流式文本和流式工具参数,包括被网络分片切开的 UTF-8 字符;
  • 图片(URL 或 base64);
  • Responses 与 Chat Completions 之间的结构化输出格式;
  • token 用量和符合协议格式的错误。上游流中断或格式异常时会报告为错误,而不是当作成功完成。

不能转换的部分

有些 Responses 功能在 Chat Completions 里没有对应物,AutoJev 会明确拒绝,而不是假装支持:

  • previous_response_id 和 conversation:跨协议转换要求每次请求都携带完整历史;
  • 托管工具,例如联网搜索——这就是写入 web_search = "disabled" 的原因;
  • 音频和文件内容、带命名空间的工具定义、多候选输出;
  • 推理状态:各家专有的 thinking 块、加密推理和签名会被丢弃,推理控制参数也不会转换。如果某个模型要求后续工具结果必须附带它原有的私有推理状态,那么跨协议时可能无法完整跑完智能体循环,这种场景请使用其原生 API。

另外,一条通用原则:转换无法让模型凭空获得工具调用、视觉、推理能力或更大的上下文。给 Codex 选模型时,请优先考虑工具调用能力强的模型。

用本机 Ollama 模型跑 Codex

本地模型适合处理敏感代码,或者干脆不想调用付费 API 的场景:

  1. 启动 Ollama 并拉取一个编程模型;
  2. 在 AutoJev 中启用 Ollama 服务商(http://127.0.0.1:11434),添加该模型,API 类型选 chat_completions;
  3. 让 Codex 直接连接 ollama/<模型名>,或者把它加入一条打开了「优先使用本地模型」的路由,再放一个云端模型作为第二候选。

用路由的方式还有故障转移兜底:如果本地服务没启动,或者在开始输出之前返回 5xx,AutoJev 会尝试下一个候选。默认最多尝试 4 次、冷却 30 秒。已经开始输出的流不会重放,所以 Codex 不会把同一个工具操作执行两遍。

用 OpenRouter 或 DeepSeek 跑 Codex

步骤完全相同,只是换了服务商。两个建议:

  • 用路由做对比。 把一个 OpenRouter 模型和 DeepSeek 放进同一条负载均衡路由,权重相同。新会话会分配到两边,会话保持让每个会话始终使用同一个模型。之后在「用量」里按模型对比结果。
  • 关注费用。 为每个模型设置价格,并在路由中选择一个「成本基准」,就能估算相对参照模型节省了多少。粗略规划时可以借助 LLM 费用计算器。

断开连接

在「智能体」中对 Codex 点击「断开」,AutoJev 会恢复备份的 config.toml,并保留你之后做的、与其字段不冲突的修改;如果模型目录文件原本不存在,会被删除。「停止并恢复配置」会对所有已接入的智能体做同样的事,托盘菜单里的「Quit AutoJev (restore agents)」也是如此。

排错

Codex 提示某功能不受支持。 检查请求是否用到了 previous_response_id、托管工具或文件内容。可以把该会话切换到 API 类型为 responses 的模型,或者开一个新会话。

请求发到了意料之外的服务商。 在「日志」里打开这条请求,详情会显示路由、每一次上游尝试,以及智能选择路由的决策原因。

速度优先一直在用负载均衡。 速度路由需要近期测速数据——最近 30 分钟内最多 5 个样本。手动测速一次,或保持定时测速开启。

网关已暂停。 暂停期间请求会返回 HTTP 404 和 gateway_paused,在 AutoJev 中恢复服务即可。

小结

Codex 只说 Responses,但你的模型不必如此。AutoJev 只在 ~/.codex/config.toml 中写入一小段可还原的配置,再在 ~/.codex/autojev-models.json 生成模型目录,实时把 Responses 转换为 Chat Completions 或 Messages,并由路由决定每次请求交给哪个模型。

延伸阅读: