Codex与智谱GLM完整跑通实战教程
说实话,最近Codex的热度又上来了。我听到隔壁团队提到,它在节省token方面确实很有一套,GPT-5.2-Codex编码模型用起来也相当顺手。但国内开发者面临一个很现实的尴尬——它只能绑定OpenAI自家的模型。
我们团队一直在用Claude Code,手里还有智谱GLM的Coding套餐。想直接喂给Codex用,行不行?答案是可行的,但别指望“直连”——中间必须加一层协议翻译。
很多人第一反应是掏出CC Switch,毕竟这个工具就是专门处理模型切换的。但你会发现,CC Switch对Claude Code管用,对Codex却完全失灵。
CC Switch:能力边界与限制
CC Switch大家都不陌生了。它专用于管理各种AI编码工具的配置——API Key、Base URL、MCP Server、系统提示词等等。一键切换Claude Code、Codex、Gemini CLI的provider,确实很便捷。
对于Claude Code来说,CC Switch够用了。因为GLM提供了Anthropic兼容接口(/api/anthropic),你只需要把ANTHROPIC_BASE_URL指过去,Claude Code就能直连GLM,毫无障碍。
但Codex这边可不会迁就你——它强制要求使用OpenAI的Responses API协议(POST /v1/responses),而GLM只认Chat Completions协议(POST /v4/chat/completions)。
CC Switch能帮你改URL,但改不了协议。你把Codex的Base URL指向GLM,Codex发一个Responses API请求过去,GLM直接返回404。协议上鸡同鸭讲,工具自然没辙。
新方案:litellm做协议翻译
既然Codex说Responses API,GLM听不懂,那就在中间放一个翻译层:
Codex Desktop → litellm(协议翻译)→ 智谱 GLM
litellm是一个开源的大模型网关,它最厉害的地方是支持多种API协议互转。从某个版本开始,它已经支持Responses API到Chat Completions的桥接模式,这正是我们需要的。
安装配置 litellm
安装很简单,直接pip搞定:
pip install litellm确认版本不低于1.66.3(低于这个版本不支持Responses API桥接):
python3 -c "import importlib.metadata; print(importlib.metadata.version('litellm'))"
输出类似:1.83.11另外,准备好你的智谱API Key。这里要特别提醒一句:智谱有两个接口地址,千万别搞混了。
- 标准接口:
open.bigmodel.cn/api/paas/v4 - Coding接口:
open.bigmodel.cn/api/coding/…
如果你买的是coding-plan套餐,就必须用Coding接口地址;标准套餐用标准接口。用错了,后面所有配置都是白搭。
配置litellm
创建配置文件~/.claude/litellm-config.yaml:
model_list:
# 给 Codex 用的条目
- model_name: glm-5.1
litellm_params:
model: custom_openai/glm-5.1
api_base: https://open.bigmodel.cn/api/coding/paas/v4
api_key: 你的智谱API-Key配置写好后启动litellm:
nohup litellm --config ~/.claude/litellm-config.yaml --port 4000 > /tmp/litellm.log 2>&1 &验证一下是否正常启动:
curl -s http://127.0.0.1:4000/health | python3 -c "import sys,json; d=json.load(sys.stdin); print(f'healthy: {d[\"healthy_count\"]}')"
# 输出:healthy: 1再测试Responses API桥接是否通:
curl -s -X POST http://127.0.0.1:4000/responses \
-H "Content-Type: application/json" \
-H "Authorization: Bearer 你的API-Key" \
-d '{"model":"glm-5.1","input":"你好","stream":false}'返回包含output字段的JSON,就说明协议转换成功了。接下来配置Codex Desktop。
配置Codex
Codex的配置文件在~/.codex/config.toml,编辑成下面这样:
model_provider = "custom"
model = "glm-5.1"
model_reasoning_effort = "high"
disable_response_storage = true
[model_providers]
[model_providers.custom]
name = "custom"
wire_api = "responses"
requires_openai_auth = true
base_url = "http://127.0.0.1:4000"几个关键点需要留意:
model设成glm-5.1,要和litellm配置里的model_name对上号。wire_api保持"responses",告诉Codex还是用Responses API(litellm会负责翻译)。base_url指向本地litellmhttp://127.0.0.1:4000。
然后编辑认证文件~/.codex/auth.json:
{
"OPENAI_API_KEY": "你的智谱API-Key"
}完全退出Codex Desktop再重新打开,在新对话里发条消息试试。到这里如果litellm配置正确,Codex应该已经能收到GLM的回复了——但大概率你会撞上两个报错。别急,接着看下一步。
修复 litellm 的两个 Bug(必做)
litellm的Responses API桥接模式有两个已知的bug,官方至今没修,不改的话根本跑不通。需要手动patch源码。
先找到litellm安装路径:
python3 -c "import litellm; print(litellm.__path__[0])"
# 类似:/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/litellm要改的文件是responses/litellm_completion_transformation/handler.py。
Bug 一:client_metadata 没过滤
报错长这样:AsyncCompletions.create() got an unexpected keyword argument 'client_metadata'
根本原因是Codex发的请求里带了个client_metadata字段(Codex自己用的元数据),litellm翻译的时候没过滤,直接丢给了底层OpenAI客户端,客户端不认识就炸了。
打开handler.py,找到异步方法async_response_api_handler里的这段:
acompletion_args = {}
acompletion_args.update(kwargs)
acompletion_args.update(litellm_completion_request)
litellm_completion_response: Union[在await litellm.acompletion前面插入过滤代码:
acompletion_args = {}
acompletion_args.update(kwargs)
acompletion_args.update(litellm_completion_request)
# --- Patch: 过滤 Responses API 专有参数 ---
for _k in ["client_metadata", "max_output_tokens", "previous_response_id"]:
acompletion_args.pop(_k, None)
litellm_completion_response: Union[同步方法response_api_handler里也有同样的代码,一样改(把acompletion_args换成completion_args)。
Bug 二:非 function 类型工具没过滤
Codex发的工具列表里有web_search、code_interpreter、file_search这些OpenAI专有工具类型,而GLM只支持function类型。litellm照样没过滤。
在上一步的参数过滤代码后面,紧跟加上工具过滤:
# --- Patch: 过滤非 function 类型工具 ---
_tools = acompletion_args.get("tools")
if _tools and isinstance(_tools, list):
acompletion_args["tools"] = [t for t in _tools if t.get("type") == "function"]
litellm_completion_response: Union[同步方法同理,把acompletion_args换成completion_args。
改完后重启litellm:
kill $(lsof -i :4000 -t)
nohup litellm --config ~/.claude/litellm-config.yaml --port 4000 > /tmp/litellm.log 2>&1 &然后打开Codex Desktop发条消息,正常来说,一切应该就通了。
总结
整理一下最终链路和涉及的配置:
Codex Desktop (Responses API) → litellm (:4000) → 智谱 GLM (Chat Completions)
涉及的配置文件汇总:
~/.claude/litellm-config.yaml— litellm网关配置(模型、API地址、Key)~/.codex/config.toml— Codex配置(模型、协议、网关地址)~/.codex/auth.json— Codex API Key~/.zshrc— Claude Code环境变量(直连GLM的那一套)- litellm
handler.py— 源码patch(两个bug修复)
核心思路其实就一句话:协议不兼容,就加个翻译。
CC Switch是配置管理工具,不是协议转换工具。Claude Code + GLM协议本身兼容,所以不需要翻译;Codex + GLM协议不兼容,所以必须靠litellm中间转一道。分清这两件事,配置起来就不会走弯路。
说到底,你想用国内的模型,对方又没有/v1/responses API协议的情况下,就这么玩。最后多说一句,最近Codex又被炒起来了,大家确实可以多看看——省token是真的省,输出质量也不受影响,毕竟并不是所有人都喜欢Claude Code那套命令行模式。