跳到主要内容
注册

Codex CLI 挂在中转上?根因是 Responses API

OpenAI 的 Codex CLI 调用的不是经典的 Chat Completions API,而是更新的 Responses API 协议。多数 OpenAI 兼容中转只实现了 Chat Completions,于是同一个 Key 在 curl 里正常、放进 Codex 就 404 或报格式错误。Router One 原生实现了 Responses 协议(wire_api = "responses"),改两分钟配置即可跑通。

一句话根因

Codex 把请求发往 /responses 风格的路径,请求 schema 也是 Chat Completions 服务端不认识的。只会说 Chat Completions 的中转只能回 404(路径不存在)或 400(字段不识别)。换 Key、换模型都救不了协议不匹配——必须网关本身支持。

可用的配置

在 ~/.codex/config.toml 里把 Codex 指向 Router One,并在运行 codex 的同一个 shell 里导出 Key。model 这一行要保留,Codex 才会用你选定的模型:按 Codex 的模型文档与 0.159.1 的发布说明(2026-10-06 核对),config.toml 没写 model 时 Codex 会用它推荐的模型,0.159.1 起就是 gpt-6.1-sol。按 2026-10-06 的套餐接口,gpt-5.6-sol 与 gpt-6.1-sol 都在 Pro、Max、Ultra 三个套餐的「高级模型」档。完整配置如下:

config.toml
# ~/.codex/config.toml
model = "gpt-5.6-sol"
model_provider = "router"

[model_providers.router]
name = "router"
base_url = "https://api.router.one/v1"
env_key = "ROUTER_ONE_API_KEY"
wire_api = "responses"

# 在 shell 里:
# export ROUTER_ONE_API_KEY=sk-your-router-one-key

报错排查表

改完配置仍然失败时:

报错排查表
症状原因修复
所有请求都 404base_url 指向了不支持 Responses API 的中转,或有拼写错误base_url 精确设为 https://api.router.one/v1,并保留 wire_api = "responses"。
401 未授权运行 codex 的 shell 里看不到 ROUTER_ONE_API_KEY在同一会话(或 shell profile)里导出 Key,重启终端后再运行 codex。
模型不存在模型 ID 与目录不一致从 /models 页复制精确 ID——区分大小写。
402 余额不足钱包或 Key 消费上限用尽充值,或在控制台 → API 密钥调高 maxSpend。
配置像是没生效Codex 读的配置文件不是你改的那个确认文件位于 ~/.codex/config.toml(Windows:%USERPROFILE%\.codex\config.toml)。
400 里提到 background 或 image_generationCodex 请求了后台执行或 image_generation 工具——这是网关不提供的两项 Responses 特性关掉 background 模式;图片生成改走 POST /v1/images/generations。hosted 工具与 previous_response_id 在原生走 Responses 的模型上照常可用。
400 提示模型必须走 /v1/messages你在 Codex 里填了 Claude 家族的模型 ID;Claude 在 Anthropic 兼容端点和 /v1/chat/completions 上服务,不在 /v1/responses 上换成详情页列出 POST /v1/responses 的模型(当前目录中的 GPT 系列、DeepSeek ID 与 Grok 对话模型)。要用 Claude 请改用 Claude Code。
codex-auto-review 报模型不存在把 approvals_reviewer 设为 auto_review 后,Codex 的 Auto-review 审查代理可能以模型 ID codex-auto-review 发请求(按 openai/codex rust-v0.159.3 源码,2026-10-01 核对);只认自家模型清单、或只实现 Chat Completions 的中转会拒绝这个 ID。/review 是另一回事:设了 review_model 就用它,否则用当前会话模型Router One 侧无需改动——codex-auto-review 就在目录里,走 /v1/responses 与 /v1/chat/completions。它不在任何订阅套餐内,这类请求从钱包扣费;价格见 /models/codex-auto-review。想指定 /review 用哪个模型,在 ~/.codex/config.toml 里设置 review_model。
stream disconnected before completion: idle timeout waiting for SSE(或 stream closed before response.completed)是 Codex 自己结束了这条流:在 stream_idle_timeout_ms 内没收到任何 SSE 事件,或者连接在最终的 response.completed 事件之前就关闭了在 [model_providers.router] 块里调大 stream_idle_timeout_ms,并检查代理或网络链路。详见下方讲这两个报错的一节。

Responses 端点接受什么、拒绝哪两样

Router One 自己实现了 Responses 协议,服务对象是模型详情页列出 POST /v1/responses 的模型(当前目录中的 GPT 系列、DeepSeek ID 与 Grok 对话模型)。下表按请求特性列出当前行为;表中标为接受的特性都按该模型的公示单价计费。

Responses 端点接受什么、拒绝哪两样
请求特性状态说明
function 工具(Codex 默认的工具形态)接受结构化工具调用作为一等 Responses 输出项返回。
custom 工具(Codex 的 freeform apply_patch 等)原生走 Responses 的模型上接受请用详情页列出 POST /v1/responses 的模型;其他模型返回 400 invalid_request。
previous_response_id / conversation / prompt(服务端上下文引用)原生走 Responses 的模型上接受模型限制与 custom 工具相同;引用在原生路径上解析。
hosted 工具:file_search、code_interpreter、computer_use、mcp、web_search原生走 Responses 的模型上接受按原样转发、按该模型公示单价计费——Router One 自身不执行其中任何一项。
带 file_id 或 file_url 的 input_file 块原生走 Responses 的模型上接受模型限制相同;文件引用随请求一起转发。
stream / instructions / temperature / max_output_tokens接受见 Responses 接口参考。
首个事件之前或事件之间的长时间等待(流式、指定模型)网关不会掐断原生 Responses 流没有网关侧的响应头超时或空闲超时;只会因 Codex 断开、请求 deadline 到期、上游报错或上游关闭流而结束。model:auto 的候选仍保留各自的时间预算。
耗时较长的非流式请求(stream: false)用 JSON 保活保持连接,完成后一次性返回网关以流的方式读取模型输出,生成完成后把完整的 response 对象作为一个 JSON 正文返回。约 25 秒后网关会先提交 HTTP 200 并写入 JSON 前导空白,此后发生的失败会以 HTTP 200 加顶层 error 对象返回——先判断有没有 error,再读 output。耗时长的搜索类或 agent 类请求请用 stream: true。
流到一半取消(Codex 里按 Esc,或连接断开)记为 HTTP 499 client_cancelled网关最多等 5 秒拿最终 usage 并按它计费;已有输出却没拿到最终 usage 时,上游没有报告的部分按估算计费(截至 2026-10-13)。网关会释放预留余额中未用的部分,也绝不故障转移(见 /llm-streaming)。
image_generation 工具与 image_generation_call 输入项拒绝——400 invalid_request图片生成不经 Responses 端点开放;请改走 POST /v1/images/generations(见 /image-generation-api)。
background: true拒绝——400 invalid_request不提供后台执行,也没有 GET /v1/responses/{id} 可事后取回结果;每个请求必须在自己的 HTTP 连接内完成。

Codex 报 stream disconnected before completion 怎么办

Codex CLI 用这同一个前缀报告两种不同的流中断。两者都是 SSE 流提前结束时由 Codex 自己抛出的;流中断后,Codex 最多按 stream_max_retries(默认 5 次)重试,之后才放弃。

stream disconnected before completion: idle timeout waiting for SSE

在 stream_idle_timeout_ms(默认 300000 毫秒,即 5 分钟)内没收到任何 SSE 事件,Codex 就放弃了这条流。GPT 模型长时间推理时可能这么久都没有事件,本地网络链路卡住也会这样。Router One 不会因为空闲而结束原生 Responses 流(见上表),所以触发的是 Codex 自己的计时器。以冒号开头的保活注释行(如 : ping)不管由哪个服务端发送都没用:Codex 的 SSE 解析器会丢弃注释行,只有真正的事件才会重置它的空闲计时。

stream disconnected before completion: stream closed before response.completed

连接在最终的 response.completed 事件到达之前就关闭了。先查本地链路:会切断 HTTPS 长连接的代理、VPN 或防火墙正会造成这个报错。然后按时间和模型在控制台 → 日志里找到这次请求。

要改什么

GPT 模型长时间推理时,在 provider 块里调大 stream_idle_timeout_ms,例如像下面这样设为 600000(10 分钟)。重试参数也在同一个块里:stream_max_retries(默认 5)管流中断后的重试,request_max_retries(默认 4)管 HTTP 请求的重试。这三项只对自定义的 [model_providers.<id>](例如 router)生效;内置的 openai、ollama、lmstudio 这几个 ID 是保留的,不能覆盖。仍然报错的话,换个网络或绕开代理再试。

到日志里看这次请求

Codex 因空闲超时放弃一条流时会断开连接,网关把这次请求记为 HTTP 499 client_cancelled,按上游报告的用量计费;已有输出却没拿到最终 usage 时按估算计费(截至 2026-10-13,见 /llm-streaming)。记录里有首字延迟(TTFT),说明流停止之前已经有输出,是中途断开;流式记录没有首字延迟,说明从头到尾没有输出,多半是首字太慢或在输出之前就失败了。日志里查不到这次请求只是线索,不能据此断定请求没到达网关。

config.toml
# ~/.codex/config.toml
[model_providers.router]
name = "router"
base_url = "https://api.router.one/v1"
env_key = "ROUTER_ONE_API_KEY"
wire_api = "responses"
stream_idle_timeout_ms = 600000
# 默认值:stream_max_retries = 5,request_max_retries = 4

用 trace 验证

网关发往模型的每次 Codex 调用都会出现在控制台 → 日志里,带模型、tokens、花费、总耗时(产生过输出的流式请求另有首字延迟)和状态。如果 Codex 在报错而日志是空的,改配置之前先看 Codex 打印的状态码:401(Key 无效)、402(余额不足或 Key 达到 maxSpend 上限)、Key 或账户限额触发的 429,以及模型 ID 或端点不对的 400 / 404,都在调用任何模型之前被拒绝,不会留下记录;其他情况先查本地——配置路径或环境变量。日志为空只是线索,不能单独下结论,仍在等待定价的请求也可能暂时查不到。日志里出现错误状态的记录,说明请求已经过了这些检查,记录里的状态码和错误信息会指出原因。

常见问题

为什么我的 Key 在 curl 里能用,在 Codex 里不行?

curl 测的是 Chat Completions 面;Codex 用的是 Responses API 协议。一个中转完全可以通过 curl 测试、却对 Codex 返回 404。网关必须原生实现 Responses 协议——Router One 支持。

wire_api = "responses" 到底是干什么的?

它告诉 Codex 用哪种协议形态与该 provider 块通信。设为 "responses" 时,Codex 发送 Responses API 格式的请求;对面的端点必须原生理解它。

base URL 要不要带 /v1?

要——Codex 用的 OpenAI 兼容 base URL 是 https://api.router.one/v1,包含 /v1。这和 Claude Code 正好相反:Anthropic 兼容 base URL 不带 /v1。

Codex 报 stream disconnected before completion 是什么意思,怎么解决?

这是 Codex 在报告它的 SSE 流提前结束,有两种形式。idle timeout waiting for SSE 表示在 stream_idle_timeout_ms(默认 300000 毫秒)内没收到任何事件;GPT 模型长时间推理时,在自定义 provider 块里调大它,例如 stream_idle_timeout_ms = 600000。stream closed before response.completed 表示连接在最终事件之前就关闭了,先查代理、VPN 或网络。Router One 不会因为空闲而结束原生 Responses 流,保活注释行也无法重置 Codex 的计时器。被放弃的那次请求在控制台 → 日志里记为 HTTP 499 client_cancelled,按上游报告的用量计费;已有输出却没拿到最终 usage 时按估算计费(截至 2026-10-13)。

能在内置的 openai provider 上设置 stream_idle_timeout_ms 吗?

不能。内置 provider ID(openai、ollama、lmstudio)是保留的,不能覆盖,所以 stream_idle_timeout_ms、stream_max_retries 和 request_max_retries 只对自定义的 [model_providers.<id>] 生效。本页配置的 router 块就是自定义 provider,把这几项加在那里即可。

能不能只设 openai_base_url,不加自定义 provider?

Codex 的高级配置文档(2026-10-01 核对)把 openai_base_url 介绍为把内置 openai provider 指向代理或路由服务的一种方式;本页用的是自定义的 [model_providers.router],我们也推荐这种写法。按 Codex 源码(rust-v0.159.3,2026-10-01 核对),openai_base_url 会替换内置 provider 的请求地址,与你用哪种方式登录无关,所以 Codex 为 OpenAI 保存的凭据都会发到这个地址,包括 ChatGPT 登录令牌。如果仍要用 openai_base_url,请按 Codex 的认证文档(2026-10-01 核对)用 codex login --with-api-key 以你的 Router One API Key 登录,绝不要与 ChatGPT 登录同用。自定义 provider 从 env_key 读取 Key,不用你的 OpenAI 登录凭据,上面的流式与重试参数也只能写在自定义 provider 里。按高级配置文档,项目级的 .codex/config.toml 会忽略 openai_base_url 和 model_providers,这两项都要写在 ~/.codex/config.toml 里。

通过网关 Codex 能用哪些模型?

当前目录中原生走 Responses 协议的 GPT 系列模型——2026-09-05 上架的 GPT-6 Astra(openai/gpt-6-astra)、2026-09-23 上架的 GPT-6 Sol(openai/gpt-6-sol)与 2026-09-30 上架的 GPT-6.1 Sol(openai/gpt-6.1-sol)都在其中;Astra 见 GPT-6 Astra API 接入指南,Sol 的端点、长上下文阶梯与 Codex 配置见 GPT-6 Sol 接入指南,6.1 Sol 有哪些变化、Codex 的新默认模型见 GPT-6.1 Sol 接入指南(Codex 从 0.159.1 起才在内置模型列表里收录 gpt-6.1-sol)。DeepSeek V4.1 Flash(deepseek-v4.1-flash,2026-09-10 上架)与旧 ID deepseek-v4-flash 同样在这个端点上原生服务;DeepSeek V4 Pro 不在目录。Grok 对话 id——自 2026-09-22 起的 grok-4.7、grok-4.6、grok-4.5、grok-4.3 与 grok-build-0.1,以及 2026-09-23 上架的 grok-4.7-build-fast——也在这里原生服务,Codex 可以指向其中任何一个。用 /models 页的精确模型 ID——每个模型页都会列出是否提供 POST /v1/responses。Claude 模型不在这个端点上:发过来会在调用任何模型之前就拿到 400。

Codex 里指定 Claude 模型报 400,怎么办?

网关在调用任何模型之前就拒绝了这个请求,消息里直接写明该模型在哪条路径上:model 'anthropic/claude-opus-5' must be called via /v1/messages or /v1/chat/completions。Claude 在 Anthropic 兼容端点(Claude Code 走的那条)和 /v1/chat/completions 上服务,不在 /v1/responses 上。把 Codex 换成 当前目录中的 GPT 系列模型;要用 Claude 就改用 Claude Code——见 /claude-code-china。

Codex 一直在请求的 codex-auto-review 是什么模型?

这是 Codex 的 Auto-review 可能请求的模型 ID。把 approvals_reviewer 设为 auto_review 后,由一个独立的审查代理代替你答复沙箱审批提示;按 openai/codex rust-v0.159.3 源码(2026-10-01 核对),它可能调用 codex-auto-review。/review 是另一项功能:设了 ~/.codex/config.toml 里的 review_model 就用它,否则用当前会话模型。只按自家清单校验模型名、或只实现 Chat Completions 的中转会回 model not found。Router One 的目录里就有 codex-auto-review,请求会像其他模型一样在 /v1/responses 与 /v1/chat/completions 上被路由;它不在任何订阅套餐内,套餐用户的 Auto-review 请求也从钱包扣费——当前价格见 /models/codex-auto-review。

previous_response_id 和 hosted 工具经网关能用吗?

能,在原生走 Responses 协议的模型上可用——模型页的端点列表会标明。这类请求按原样转发、按该模型公示单价计费;只有 background: true 和 image_generation 工具会被 400 拒绝。

Codex 里调图片生成为什么 400?

图片生成不经 Responses 端点开放,所以 image_generation 工具或 image_generation_call 输入项会在调用任何模型之前被 400 invalid_request 拒掉。图片生成请改走 POST /v1/images/generations——见 /image-generation-api。

能后台跑 response 吗?

不能。background 必须省略或为 false;background: true 会返回 400 invalid_request。网关不提供后台执行,也没有 GET /v1/responses/{id},连接断开后结果无法再取回。

中国大陆能用吗?

能。网关在大陆可直连、无需 VPN;上面的 config.toml 在任何地区都完全一致。