1. 为什么新版 codex 接国产模型这么折腾
新版 codex 在 0.8 之后把模型调用协议收窄了,只认 responses 传输协议。这个变化对本地 CLI 用户影响很大:以前改个config.toml里的base_url就能把 ds、glm、kimi 接进来,现在这条路走不通了。原因不复杂,responses 协议和 chat 协议在请求体结构、流式返回格式、工具调用字段上都不一样,codex 内部解析器只按 responses 的格式读数据,你给它一个 chat 格式的返回,它直接报解析错误。
我实测下来,目前国产模型里明确走 responses 协议的只有火山引擎和阿里云两家,但即便你接这两家,codex 也会因为某个布尔字段没传过去而握手失败。所以结论很直接:想让 ds、glm、kimi 这类只提供 chat 接口的模型跑在新版 codex 里,中间必须有一个协议转换层。CLIProxyAPI 就是干这个的,它在本地起一个 HTTP 服务,把 codex 发来的 responses 请求翻译成 chat 请求转发给国产模型,再把返回包装回 responses 格式。
这套链路适合谁?适合在 Windows 或 WSL 下用 codex 做本地 agent 开发、需要 websocket 服务(app-server --listen)的 CLI 用户。如果你只是偶尔问答,用网页版就够了;但你要跑基于 codex 的自动化项目,或者需要多模型切换做对比测试,那这套配置值得花二十分钟搭起来。
TaoToken 在这里的角色是统一 Key 通道。你不用为 ds、glm、kimi 分别去各家平台注册、充值、管理一堆 Key,而是用 TaoToken 一个 Key 走统一入口,CLIProxyAPI 那边只需要填一次认证信息。官网入口在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end ,API 地址是 https://taotoken.net/api ,注意 API 地址不带 UTM 参数,配置里填这个就行。
2. TaoToken 前置准备:拿 Key 和确认通道
在动 CLIProxyAPI 之前,先把 TaoToken 这边的接入点准备好。打开 https://taotoken.net/api-keys ,登录后创建一个 API Key。这个 Key 就是你后面填进 CLIProxyAPI 配置里的凭证,格式通常是一串sk-开头的字符串。创建时给它起个能认出来的名字,比如codex-local,方便以后在控制台里区分。
创建完 Key 之后,顺手确认一下你要用的模型在 TaoToken 这边是否可用。打开模型对话页面 https://taotoken.net/model-chat ,在模型选择里找一下 ds、glm、kimi 对应的条目。这一步不是必须的,但能帮你提前排除「模型名写错」这类低级问题。我踩过的坑就是 glm 的模型名写成了glm-4,实际要用glm-4.7这种带版本号的完整名称,codex 那边报 404 我还以为是协议问题。
如果你打算长期用 codex 做编码或 agent 任务,可以顺带看一下 Coding Plan 页面 https://taotoken.net/coding-plan ,它针对的就是这类高频 CLI 调用场景。不过这篇教程的核心是打通链路,计费细节你按自己用量判断就行。
TaoToken 的 API 通道地址是https://taotoken.net/api,这个地址在 CLIProxyAPI 的配置里会作为上游 endpoint 出现。注意不要写成带 UTM 的官网地址,API 调用只认/api这个路径。
3. CLIProxyAPI 配置骨架与 settings.json 片段
CLIProxyAPI 的安装方式参考官方文档 https://taotoken.net/doc ,这里不重复安装步骤,直接给配置骨架。假设你已经把 CLIProxyAPI 跑起来了,它默认监听localhost:8317,这个端口就是 codex 要连的本地中转地址。
先看 CLIProxyAPI 自己的配置文件,通常叫settings.json或config.yaml,放在 CLIProxyAPI 的安装目录下。核心是配一个 provider,指向 TaoToken 的 API 通道:
{ "port": 8317, "providers": [ { "name": "taotoken", "type": "openai", "base_url": "https://taotoken.net/api", "api_key": "sk-你的TaoTokenKey", "models": [ "deepseek-chat", "glm-4.7", "kimi-latest" ] } ], "log_level": "info" }这里base_url填https://taotoken.net/api,不要加尾部斜杠。models数组里列出你计划用的模型名,CLIProxyAPI 会把这些名字注册到本地路由上。api_key就是你刚才在 TaoToken 控制台创建的那串。
接下来是 codex 这边的config.toml,放在~/.codex/目录下(Windows 是C:\Users\你的用户名\.codex\)。单模型默认接入的写法:
model_provider = "taotoken" model = "deepseek-chat" [model_providers.taotoken] name = "TaoToken" base_url = "http://localhost:8317/v1" wire_api = "responses" requires_openai_auth = true preferred_auth_method = "apikey"关键字段解释一下。base_url指向本地 CLIProxyAPI 的8317端口,不是 TaoToken 的远程地址,因为协议转换在本地完成。wire_api = "responses"告诉 codex 用 responses 协议发请求,CLIProxyAPI 收到后会转成 chat 协议发给 TaoToken。requires_openai_auth = true和preferred_auth_method = "apikey"是让 codex 走 Key 认证而不是 OAuth。
然后新建auth.json,和config.toml同目录:
{ "OPENAI_API_KEY": "sk-你的TaoTokenKey" }这个 Key 和 CLIProxyAPI 里填的是同一个。codex 启动时会读这个文件,把 Key 放进请求头里发给本地8317,CLIProxyAPI 再把它替换成上游认证。
多模型切换的配置稍微不同,用profiles段:
[profiles.glm] model_provider = "taotoken" model = "glm-4.7" model_reasoning_effort = "high" [profiles.kimi] model_provider = "taotoken" model = "kimi-latest" [model_providers.taotoken] name = "TaoToken" base_url = "http://localhost:8317/v1" wire_api = "responses" requires_openai_auth = true preferred_auth_method = "apikey"注意这里没有给每个 profile 单独写model_providers,而是共用一个taotokenprovider,因为上游都是同一个 TaoToken 通道,只是model字段不同。启动时用codex --profile glm或codex --profile kimi切换。
注意:
disable_response_storage这个变量不要加。有些教程里带了它,作用是关闭上下文保存,加了之后多轮对话会丢历史,codex 的 agent 模式会直接崩。
4. 启动与逐模型请求验证
配置写完后,先启动 CLIProxyAPI。在它的安装目录下执行启动命令,具体命令看你的安装方式,通常是./cliproxyapi或cliproxyapi.exe。启动后终端会打印监听端口和已注册的模型列表,确认看到8317和你在settings.json里配的模型名。
然后开另一个终端,验证 CLIProxyAPI 本身是否通。用 curl 直接打本地端口:
curl http://localhost:8317/v1/models \ -H "Authorization: Bearer sk-你的TaoTokenKey"如果返回一个 JSON 数组,里面包含deepseek-chat、glm-4.7、kimi-latest,说明 CLIProxyAPI 到 TaoToken 的链路是通的。如果返回 401,检查auth.json和settings.json里的 Key 是否一致;如果返回 404,检查base_url是不是写成了https://taotoken.net/api/带了尾部斜杠。
接下来验证 codex 单模型。在项目目录下直接输入codex,它会读默认的model_provider和model。进去之后随便问一句「用 Python 写一个快速排序」,看它是否正常流式返回。如果卡住不动,大概率是wire_api没设成responses,codex 用 chat 协议发请求,CLIProxyAPI 那边解析不了。
多模型验证逐个来。先codex --profile glm,问一句「解释一下什么是闭包」,确认返回正常。退出后再codex --profile kimi,问同样的问题,对比一下两个模型的回答风格。这里有个细节:codex 进入交互模式后,内置的/model命令只能切 GPT 系列,切不了你自定义的 profile,所以换模型必须退出重进,用--profile参数指定。
如果你想在脚本里非交互式调用,可以用codex exec子命令:
codex exec --profile glm "把当前目录下的 README.md 翻译成英文"这个方式适合把 codex 嵌进 CI 或自动化流程里。实测下来,CLIProxyAPI 的协议转换延迟在几十毫秒级别,对整体响应速度影响很小,流式输出的首 token 时间基本和直连差不多。
5. 本篇常见报错排查
报错一:stream error: unexpected end of JSON input
这个通常出现在 codex 启动后第一次请求时。原因是 CLIProxyAPI 返回的 responses 格式里某个字段缺失,codex 解析到一半发现 JSON 不完整。排查方向:确认 CLIProxyAPI 版本是最新的,旧版本对 responses 的output数组包装不完整。另外检查settings.json里type是不是openai,写成其他类型会导致转换逻辑走错分支。
报错二:401 Unauthorized但 Key 明明是对的
先确认auth.json的路径对不对。codex 读的是~/.codex/auth.json,不是项目目录下的。Windows 下~是C:\Users\你的用户名\。如果路径没错,检查auth.json里的 Key 有没有多余空格或换行,JSON 格式对空格敏感。还有一种情况是 CLIProxyAPI 的settings.json里api_key和auth.json里的不一致,两边必须填同一个 TaoToken Key。
报错三:model not found
codex 报这个说明它把模型名发给了 CLIProxyAPI,但 CLIProxyAPI 的models数组里没有这个名称。检查config.toml里的model字段和settings.json里的models数组是否完全匹配,大小写和连字符都要一致。比如glm-4.7不能写成GLM-4.7或glm_4.7。
报错四:codex 启动后一直转圈,终端无输出
先看 CLIProxyAPI 的终端有没有收到请求日志。如果没有,说明 codex 根本没连上8317,检查base_url是不是写成了http://127.0.0.1:8317/v1而 CLIProxyAPI 只监听了localhost,这两个在部分系统上解析不同。如果有请求日志但卡住,看日志里上游请求是否超时,可能是 TaoToken 通道的网络问题,换个时间重试或检查 API 地址是否写成了带 UTM 的官网地址。
报错五:多轮对话丢失上下文
这个就是disable_response_storage变量导致的。把它从config.toml里删掉,重启 codex。codex 默认会保存对话历史,CLIProxyAPI 在转换时会把历史消息一起打包发给上游,删掉这个变量后多轮对话就正常了。
6. 接入点与后续操作
整条链路跑通后,你日常只需要维护两个东西:TaoToken 的 Key 和 CLIProxyAPI 的本地服务。Key 在 https://taotoken.net/api-keys 管理,可以随时创建新的或吊销旧的。CLIProxyAPI 的接入文档在 https://taotoken.net/doc ,里面有针对不同操作系统的启动参数说明。
如果你在排障过程中需要确认某个模型当前是否可用,直接打开 https://taotoken.net/model-chat 发一条测试消息,比在终端里反复试错快得多。长期跑编码任务的话,https://taotoken.net/coding-plan 里有针对 CLI 场景的用量方案,你可以按自己的调用频率决定要不要切过去。
最后提醒一个实操细节:CLIProxyAPI 的服务要全程在终端里跑着,codex 才能连上8317。你可以把它做成后台服务或开机自启,但调试阶段建议保持前台运行,这样报错日志能直接看到。等配置稳定了再考虑常驻。