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 不一样。Codex 强制使用 OpenAI 的 Responses API 协议(POST /v1/responses),而 GLM 只认 Chat Completions 协议(POST /v4/chat/completions)。

所以今天我们就聊一个事,那就是你既想用国内的模型,但是它又没有/v1/responses API协议的情况,该怎么搭配Codex使用

CC Switch 能帮你改 URL,但改不了协议。你把 Codex 的 Base URL 指向 GLM,Codex 发一个 Responses API 请求过去,GLM 直接返回 404。

cc-switch-vs-litellm.svg

一句话总结:CC Switch 是「换地址牌」,不是「翻译官」。Claude Code + GLM 协议本身兼容,换个地址就行;Codex + GLM 协议不兼容,换地址没用,得有人中间做翻译。

新方案:litellm 做协议翻译

既然 Codex 说 Responses API,GLM 听不懂,那就在中间放一个翻译:

Codex Desktop → litellm(协议翻译)→ 智谱 GLM

litellm 是一个开源的 LLM 代理网关,支持多种 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

注意看模型前缀是 custom_openai/ 不是 openai/。这个很关键——litellm 源码里 openai provider 被硬编码为支持原生 Responses API,用 openai/ 前缀的话 litellm 会把请求原样转发给 GLM,还是 404。custom_openai/ 没有注册 Responses API 配置,litellm 才会走翻译路径。

配置写好后启动 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"

几个关键点:

  1. model 设成 glm-5.1,要和 litellm 配置里的 model_name 对上
  2. wire_api 保持 "responses",告诉 Codex 用 Responses API(litellm 会负责翻译)
  3. base_url 指向本地 litellm http://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_searchcode_interpreterfile_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 发条消息,应该一切正常了。

image.png

 总结

整理一下最终链路和涉及的文件:

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 的命令行模式。

image.png