最后更新

Codex Router 工作原理 — 架构与请求流程

Codex Router 是编码 Agent 客户端与外部模型供应商之间的本地服务。Codex 仍是主要前端,同一份已认证模型注册表还可发布给 DeepSeek Harness、Gemini CLI、Cursor、Claude Code、OpenClaw、opencode、pi、omp、Command Code 与 Hermes Agent。本页解释请求流程与安全边界。

为什么需要路由器

Codex App 期望 Responses API 和 Codex 形态的模型目录。Kimi 与 DeepSeek 暴露的是认证和请求细节不同的 OpenAI 兼容 Chat Completions API。路由器桥接这些契约,同时让原生 GPT 流量继续走常规 ChatGPT Codex 后端。

四个组成部分

  • 生成的目录把外部模型放到 Codex model_catalog_json 中原生 GPT 模型旁边。
  • 调度器按命名空间模型 ID 选择原生或外部路由——以 deepseek/、kimi-oauth/、anthropic-api/ 等开头的都走外部路径。
  • LiteLLM 把 Responses 请求、流与工具调用翻译为各供应商的原生协议,包括 OpenAI 兼容 Chat Completions 与 Anthropic Messages。
  • 凭据转发器只注入所选供应商的认证,其余全部剥除。

所有监听器都绑定 127.0.0.1,整个服务都在你的机器本地。

请求流程

Codex 把 Responses 请求发送到 4202 端口的回环路由器:

端口监听器职责
4202路由器接收客户端请求并认证 caller capability
4200LiteLLM把 Responses 翻译为各供应商的原生协议
4201Kimi OAuth用刷新后的 OAuth bearer 转发给 Kimi
4203API 转发器用所选密钥转发给 API Key 供应商

对于原生 GPT 模型,路由器用放行列表中的 Codex 头与原生模型 ID 转发给 ChatGPT Codex 后端——路由器绝不会把原生请求发送给外部供应商。

对于需要协议翻译的注册表模型(例如 kimi-oauth/k3),路由器校验调用方、把网关模型加内部密钥交给 LiteLLM,LiteLLM 翻译请求并交给匹配的转发器。转发器丢弃内部密钥,只注入所选供应商凭据。流经 LiteLLM 以 Responses 事件返回。

Responses 原生外部模型现在直接通过持有凭据的 API 转发器,即使其他路线仍启用 LiteLLM 也是如此。普通回合和远端压缩保留原有的请求准备、工具身份、流校验与凭据边界;需要翻译的路线继续经过 LiteLLM。

检出目录提供 node src/runtime-dependency-requirements.mjs,以 JSON 查询所选路线需要的服务;加上 --gateway-required 则返回 required 或 unused。可选兼容层设置现在也决定哪些路线会被发布,以及 LiteLLM 网关是否启动。

可选兼容层

LiteLLM 默认启用。只使用原生 GPT 与 Responses 原生路线的安装可通过 node src/control.mjs compatibility-layer off 持久关闭;用 status 查看状态,on 重新启用。全新源码检出可在安装前运行 node src/compatibility-layer-state.mjs off,跳过 Python 安装。更改后按需准备依赖、重启路由器并刷新客户端目录。关闭时,需要 LiteLLM 的 Chat、Messages、Vertex、OAuth 与 Ollama 路线会从有效目录消失;直接请求返回 compatibility_layer_disabled。凭据与选择仍保留。Homebrew 在构建阶段仍依赖 Python。

运行时现在只启动并探测所选路线需要的服务。因此即使兼容层仍启用,只选择原生模型或 Responses 原生路线时,未用到的 LiteLLM 网关也可以不启动;选择需要翻译的路线时才启动。

服务重启时,路由器会在 LiteLLM 启动的同时开放监听端口。原生回合可立即运行;需要网关的路线在启动阶段最多等待 60 秒(CODEX_ROUTER_STARTUP_HOLD_MS)。

一份注册表,多个客户端

Codex、DeepSeek Harness、Gemini CLI、Cursor、Claude Code、OpenClaw、opencode、pi、omp、Command Code 与 Hermes Agent 共用供应商可见性和逐模型选择状态。每个发布器只适配最外层客户端契约——Responses、Gemini、Anthropic Messages 或 Cursor edge——随后重新进入同一条路由请求路径。Command Code 与 Hermes Agent 使用 Claude Code 相同的 Anthropic Messages 接口,opencode、pi 与 omp 则接收已认证的本地回环 /v1 路径。这五个“发布进去”的客户端没有 MODEL_ROUTER_TARGET,也没有第二个服务;启用供应商或整理模型会一并重新发布。只有用户显式运行 chatgpt-session enable 后,非 Codex 客户端才会看到原生 ChatGPT 模型。

凭据边界

路由入站 Codex 凭据上游凭据
原生 GPT放行并转发已有 ChatGPT/Codex 认证
Kimi OAuth丢弃~/.kimi-code 的 Kimi CLI OAuth bearer
Kimi API丢弃Kimi Platform API Key
DeepSeek丢弃DeepSeek API Key
GitHub Copilot丢弃经过 Copilot 权益和端点校验的 GitHub fine-grained token

Codex 到路由器与内部服务这两条信任边界使用两个不同的随机密钥,分别以 mode 600 或当前用户 Windows ACL 存储。外部转发器在上游请求前移除 Codex 账户、安装、attestation 与私有头。

GitHub Copilot 是 catalog-only 供应商。它会先通过 GitHub Copilot 账户端点校验 fine-grained token,并且只接受 GitHub 自有的 Copilot 推理主机。实时发现只展示当前账户可见、同时支持流式输出和工具调用的 Responses 模型,因此实际模型和额度取决于用户的 Copilot 套餐及组织策略。

安全模型

  • 本地调用方认证。 托管 base URL 包含独立的随机能力;路由器在读取模型请求或联系任何上游前先校验它。Codex 无法给内置供应商附加路由器专用头,因此能力放在 URL 路径中。状态、迁移与支持工具会脱敏它。
  • 无浏览器访问。 路由器要求 JSON 内容、拒绝浏览器来源头、绝不授予 CORS。
  • 脱敏错误。 面向网络的错误有限且不含敏感信息;原始异常文本被替换。
  • 无凭据泄漏。 诊断只报告存在与来源,绝不报告值。受保护文件使用 mode 600 或当前用户 ACL。

传输与压缩

当前 Codex 构建可能使用带认证的 Responses WebSocket。路由器会在同一个 caller-capability 边缘接受连接、按请求推导身份,并保留配额/错误元数据,再让请求进入同一条受管理 Responses 路径;HTTP 仍然支持。请求体可使用 Zstandard、gzip、deflate 或 Brotli,声明超限的压缩帧会在解码前被拒绝。

在该 WebSocket 上,Codex 可以中断正在生成的回合,并通过同一连接继续。路由器会取消本地请求、保留已完成的输出与已观察到的用量、丢弃未完成条目,并把被中断的响应标为 incomplete。重复或迟到的中断不会破坏后续回合;续接历史超出边界时需恢复完整上下文。

WebSocket 回合现在会在逻辑上的完成、取消或失败事件发生时结算,不再等待 HTTP 连接关闭,从而保留路由用量和续接状态。

请求传输状态与生成结果分别记录。流即使返回 HTTP 200,生成仍可能失败或未完成;Control Center 的 Dashboard 和 Status 会为近期请求区分 completed、failed、incomplete、canceled 与 indeterminate。所有结果的计费 token 仍可见。旧记录会标明当时未记录生成结果,而不把它们断言为生成成功。

对 Chat Completions 工具调用的续接,只有完整的流式推理链达到受支持的成功终止状态时,才会缓存供重放。截断或失败的流不会留下部分推理链供后续使用。

外部 Chat Completions 供应商无法创建 OpenAI 的不透明加密压缩载荷,因此路由器让所选外部模型生成续写摘要,并以路由器所有的 kcr1: 载荷包装。重放时把它转回普通续写消息。

只有收到成功完成事件后,压缩摘要才会替换历史。部分流或标记为未完成的 JSON 响应会被视为失败;已观察到的 token 用量仍会记录,可能已经执行过的流也不会自动触发另一轮付费尝试。

原生生成 POST 现在默认使用 CODEX_ROUTER_NATIVE_RETRY_POLICY=at-most-once:只有确认请求尚未发出、且没有输出送到调用方时才自动重试,例如 DNS 或连接失败,包括 TLS 握手完成前的连接重置。模糊的连接重置或边缘 5xx 可能发生在生成已执行之后,因此默认直接传递错误,避免自动重复可能计费的回合。运维者可显式选择 availability,允许在尚未输出时对不确定故障进行有限重试,但可能重复执行。原生生成请求的重定向会被拒绝;应配置最终 API 地址。该策略只约束本路由器的自动重试,不约束 Codex 或其它中间层。原生远端压缩流即使缺少响应元数据或 SSE Content-Type,断线时也会保留可识别的失败信息。

API Key、路由和视觉生成请求的重定向也会被拒绝,不跟随或泄露 Location。API 转发器会报告不可重试的端点配置错误;请直接配置供应商的最终 URL。

哪些仍留在 Codex

命令、权限、MCP 工具、技能、代理循环与任务状态都留在 Codex。路由器只处理模型推理与外部模型压缩;它不能添加所选模型或供应商未实现的能力。

对于原生 Codex 发起的协作子代理,路由器通过已认证的原生 Codex 后端转发确切的原生任务载荷——该转发要求有效 ChatGPT 登录,在免登录模式下宁可失败关闭,也不把不可读密文转发给外部供应商。路线只有在注册表含已审核的协作证据,或操作者运行 subagents mode selected 与 subagents set <slug> on 明确选择时,才会作为 v2 子代理发布。本机诊断记录不会认证或自动提升路线,试验性的 subagents certify 命令已移除。手动选择表示使用意愿,并不证明委派一定可用。生成的路由 agent 定义还会写入该模型配置的 model_reasoning_effort,因此低推理档位的父代理不会悄悄把所有子代理也限制在低档位。

在 Responses 原生子代理路线中,该推理档位覆盖会放在 reasoning.effort;扁平的 reasoning_effort 别名仅留给 Chat Completions 兼容路线,避免 Responses 委派请求在到达上游前收到 HTTP 400。

Azure Responses 路线现在使用 Codex 的明文协作交接,让 Azure Sol 父代理可以把任务委派给已配置的 Luna 子代理。路由器会恢复客户端可见的工具命名空间;未指定子代理模型时保留已配置的默认值。请使用当前 Codex 的 collaboration 工具命名空间,以便走受支持的交接和脱敏路径。

当某个看起来符合条件的模型无法被委派时,不必先派一个子代理再从 codex exited 1 里找原因,直接提问即可:

./bin/model-router codex subagents explain <provider/model>

该命令会指出第一个阻塞点以及修复它的命令,并区分拼写错误、尚未定制的模型与原生 slug。它还会说明某条路线的 v2 声明来自注册表还是你的明确选择。该命令只读,不消耗任何额度。 已启用的通用供应商现在也能被识别,不会再误报为供应商未启用。

原生工具与自定义模型技能包

对经路由的 Chat Completions 与 Messages 模型,CODEX_ROUTER_APP_CONNECTORS=none 可从提示中暂不提供 Codex 应用连接器函数;也可用 airtable,gmail 等逗号分隔列表,只让指定连接器预先可见。不设置或设为 all 则保持通常的连接器集合。历史调用和显式工具选择可重新声明被隐藏的定义;Codex 自有应用工具、协作工具及自定义工具仍可使用。请在路由器服务环境中设置并重启服务。

通过路由器运行的自定义模型仍可使用 Codex 原生的任务、自动化、应用内浏览器和电脑操作工具。考虑到部分模型需要更明确的工具调用引导,安装程序会加入四个受管理技能:codex-router、codex-app-threads、codex-in-app-browser 和 codex-computer-use。若用户已有同名技能则跳过,不会覆盖;卸载时只移除路由器管理的副本,doctor 会核验技能包是否与当前检出和应用工具集一致。

工具是否可用仍取决于路线。Azure KMAMC Responses 无法提供 Codex 的图片生成扩展,因此路由器会在转发前移除相关的托管和命名空间工具声明。该路线仍不能生成图片;其它供应商的工具声明不变。

已完成的路由工具调用只有在工具 schema 无需输入时才允许空参数。需要输入的工具若收到空参数,会在 Codex 存储调用前被拒绝,避免损坏线程;旧线程中仅得到 Codex 解析失败的空参数调用可被省略,使线程恢复。

向路由模型投影工具 schema 时,路由器现在会保留所有有效的操作选项以及客户端原有的执行约束,让可选的工具模式保持可用,同时不放宽引用规则。

旧工具结果只有在同一对话和权限上下文中存在精确的私有快照及签名的本地读取证明后,才会从后续模型上下文中省略。可用 ./bin/control tool-result-aging read <handle> 分页读取原文。无法本地读取或存储失败时仍保留完整结果;回执不会要求代理重新执行可能改变状态的工具。流式工具校验被拒后,该回合会终止,不再自动重放。

上下文压缩现在沿用相同的老化策略:最新四项结果保持原样,不再对近期工具输出另行做启发式整形。没有执行工具的完整历史摘要器会收到精确的原始结果。

桌面客户端可能将签名的读取证明包在工具结果 JSON 中。路由器现在可识别有界的嵌套封装,但仍校验签名、有效期、对话和权限范围;证明无效或无法读取时保留完整工具输出。

工具结果老化会保留指令文件、技能和明确的运行时文档读取,包括 Codex 电脑操作的初始化说明;普通页面快照和数据结果仍可归档。持有有效归档句柄时,可用 ./bin/control tool-result-aging read <handle> --scope-search --find '字面文本' 只搜索同一签名对话和权限范围内的原文。若返回 nextCursor,继续传入 --cursor N --index HASH;complete: false 不能当作“没有匹配”。该操作不会重跑来源命令。

高级可选设置可把某条路由模型的老化大小阈值从默认 32 KiB 调到 8–32 KiB,并开启本地读取提示。原生 OpenAI 路线默认不老化;最新四个结果和未经验证可本地恢复的结果仍受保护。提示默认关闭,读取探测失败后也会被抑制。更小的历史可能增加探测费用或失去缓存命中,启用前应比较实际用量。详见上游逐模型历史策略。

启用原生老化后,Responses Lite 会话也能归档通过 additional_tools 逐步声明的合格工具结果;明确的工具限制与签名本地回读要求仍然适用。

原生目录被保留

集成保留内置 OpenAI 供应商、原生 GPT 模型、ChatGPT 登录、配置档案、MCP 设置、项目信任与推理默认值。它只向 Codex 配置添加一个标记根块和一个惰性自定义供应商表,disable 会精确恢复此前值。

路由器服务运行期间,每五分钟检查已登录账户的原生模型目录并重新发布变化。CODEX_ROUTER_NATIVE_CATALOG_POLL_INTERVAL_MS 可将间隔延长至至少五分钟。Codex 只在启动时加载 model_catalog_json,因此新模型发布后需完全退出并重开 Codex;仍可使用 ./bin/refresh-catalog 手动刷新。

相关:安装、模型总览、故障排查。