折腾把 Claude 塞进 Codex 后,我劝大家别再迷信“接口兼容”了

0 评论 34 浏览 0 收藏 19 分钟

把 Claude 塞进 OpenAI 的 Codex 里跑代码,接口调通了,体验却像戴着手套穿针。本文拆解 Codex 与 Claude Code 的底层交互机制,揭示大厂原生工具“模型与壳子联合设计”的隐藏门槛,并分析 DeepSeek 为何能无缝接入 Claude Code——打不过你的壳子,就去练熟你的题库。

平时做方案或者聊架构,大家很容易默认一个前提:既然现在的 API 都支持 OpenAI 兼容协议,那只要开放了自定义接口,底下接什么模型还不是由中转站或网关说了算?直到我试着把 Claude 塞进 OpenAI 的 Codex 里跑了一回代码,把几个主流框架的交互机制拆开对比后才发现:API 能翻译通信格式,但翻译不了模型骨子里的“肌肉记忆”。

一、从一个想当然的念头说起

平时自己折腾各种 AI 工具或者测模型的时候,我脑子里一直有个挺顺理成章的认知:现在的 API 基本都支持 OpenAI 兼容协议了,只要一个客户端或 Agent 框架支持自定义 API 接入,那它背后真正干活的是什么模型,完全由中转站或者网关的渠道映射说了算。

照这个逻辑,不管是 GPT、Claude 还是 DeepSeek,只要在配置里改个 base_url 和模型名字,就能在任何一个客户端壳子里无缝平替。

前两天我突然起意,想试试把 Claude 模型接进 OpenAI 的终端编程工具 Codex 里用。本来以为就是改两行配置的事,结果真正上手去配,发现到处都是拧巴的地方。

先是接口直接报 404。去翻了文档才反应过来,平时大家嘴里说的“兼容 OpenAI 格式”,绝大多数指的是最经典的 /v1/chat/completions 接口。不管是开源框架、第三方中转站,还是各家模型官方提供的兼容层,对齐的都是这个老标准。但 OpenAI 早就把自家的 Agent 工具链切到了新一代的 /v1/responses 协议上,现行版本的 Codex 更是直接移除了旧的 chat 模式,写死了只认 wire_api = “responses”。如果中转站还没支持这个新路由,请求连门都进不去。

等换了个支持 /v1/responses 的新版中转站把请求接住,聊到第二句又断了。因为 /v1/responses 默认是“有状态”的——Codex 发完第一轮请求,默认服务端已经把上下文存好了,到了第二轮对话或者回传工具结果时,只传一个 previous_response_id。但中转站和背后的 Claude 接口都是无状态的,并不会在云端替你存聊天记录,一到第二轮调工具就会报错找不到历史上下文。最后还是在 ~/.codex/config.toml 里加了一行 disable_response_storage = true,强制让 Codex 每次都把完整上下文发过去,才算把多轮对话跑通。

更有意思的是,在 Codex 里还不能随便搞“模型名字伪装”。很多人用中转站习惯在客户端里填 o3 或 gpt-5,然后在中转站后台映射到 claude-sonnet。但在 Codex 里这么干会直接报 400 错误。因为它的本地代码会“看名下菜”——一旦识别到你填的是 OpenAI 自家推理模型的名字,就会自动往请求体里塞入加密的推理控制字段和专属的内置工具类型。中转站要是没把这些专属参数清洗掉、直接透传给 Claude,上游接口根本不认识,立刻就会拒收。

为了不报错,只能在配置里老老实实填上非 OpenAI 的模型名,让 Codex 退回最基础的标准工具模式,或者靠网关在中间做一次工具格式降级。

但真正让我产生好奇的,是接口彻底调通之后的体验:虽然对话通了、也能调工具改文件了,但 Claude 在 Codex 壳子里的表现,明显不如它在自家 Claude Code 里那么干脆利落,改起代码来总像是戴着一副厚棉手套在穿针。

二、为什么大厂的壳子都在说“黑话”?

既然通信协议已经由中转站转译通了,为什么同一个模型换个壳子,干活的灵巧度还是会掉一截?

把 Codex 和 Claude Code 的底层请求抓出来对比了一遍,我才看明白一件以前经常忽略的事:像 Codex、Claude Code 这种大厂第一方出品的原生工具,从来就不是按“通用多模型外壳”去设计的。

既然官方团队本来就没打算接别家模型,他们在工程上最干脆的提效手段,就是搞“模型与壳子的联合设计(Model-Harness Co-Design)”——直接在模型出厂前的后训练(Post-training / RL)阶段,把自家框架的工具语法和交互习惯训进模型的权重里。

在通用的多模型框架里,为了让随便哪个模型接进来都能调工具,每次发请求都得在 tools 字段里塞一大段 JSON Schema,向模型解释参数名叫什么、数据类型是什么、有什么边界限制。

但在 Codex 原生模式的请求里,声明改代码工具只需要写一句空壳式的 tools=[{“type”: “apply_patch”}],连参数说明都省了。因为 GPT 模型在强化学习的沙箱里早就把这套动作练熟了,一看到 apply_patch 这个名字,权重直接激活内置的补丁语法(*** Begin Patch … *** Update File),直接输出纯文本补丁。

这种设计还顺手解决了一个工程痛点:绕开了 JSON 转义的泥潭。如果退回通用的标准 function_calling,模型必须把几百行代码塞进一个合法的 JSON 字符串字段里。要知道,代码本身就充斥着大量的双引号、反斜杠、换行符和缩进。让模型一边思考代码逻辑,一边分心去算这里该打一个反斜杠还是两个反斜杠,长代码生成时非常容易因为漏转义一个引号导致解析失败。

除了怎么调工具,“黑话”还藏在壳子怎么向模型报错里。

当补丁行号没对上、或者要替换的字符串在文件里不唯一时,壳子返回的报错文本格式,和自家模型在强化学习训练场里收到的反馈信号是一致的。自家模型一看到这串特定格式的报错,就像条件反射一样,知道下一步是该把修改范围拆小,还是先用检索工具重新读一下上下文。而通过中转站强行塞进来的外家模型,既用不上它在自家主场(如 Claude Code 的 Edit 工具)练熟的动作,又没在 Codex 的报错环境里刷过强化学习,遇到复杂冲突时往往要多花好几轮试错,甚至在原地反复提交同一种错误写法。

这就好比两个搭档了十年的汽修老手,一个眼神递过去就知道要几号扳手,根本不用多废话;突然把其中一个换成刚招来的高材生,就算他图纸看得再明白,光靠标准普通话一板一眼地沟通,干活的麻利劲儿也得掉一大截。

三、DeepSeek 的聪明账:打不过你的壳子,就去练熟你的题库

聊到这儿,身边一起折腾工具的朋友提了个问题:“那为什么现在把 DeepSeek 接进 Claude Code 里用,感觉挺顺手的,没怎么遇到你说的那种水土不服?”

这恰恰印证了前面的逻辑。DeepSeek 能在 Claude Code 里打出接近原生的配合,主要是因为 DeepSeek 从官方接口到模型训练,主动去对齐了 Claude Code 的这套规则。

由于 Claude Code 已经成了目前开发者最常用的终端 Agent 之一,它的那套工具组合(Bash、Read、Edit、Grep、Glob 以及 Task 子任务派发)实际上已经演变成了行业里的默认考场。与其等用户自己拿第三方中转站硬翻,DeepSeek 算了一笔很明白的账:自己下场把这条路修平。

去翻看 DeepSeek 的文档和技术报告就会发现,他们首先在官方服务端直接上线了 /anthropic 兼容端点。用户不需要在本地挂任何第三方转换代理,在环境变量里配好地址和模型名就能把 Claude Code 直连上去。因为是官方原生解析 Anthropic 的 /v1/messages 协议,像 tool_use 工具块和 thinking 思考链这些最容易在第三方中转站里被转丢的字段,都能原原本本地保留下来。

更关键的动作在模型训练层。在后训练的强化学习(Agentic RL)阶段,现在的国产头部模型普遍搭建了大量合成代码沙箱,里面的工具签名、文件行号展示、甚至是字符串替换失败的报错提示,都严格对齐了 SWE-bench 和 Claude Code 的习惯。针对高频连续调工具的场景,DeepSeek 还专门做了思考链保留机制——只要返回的是工具执行结果,模型就会保留之前的完整思考过程,不会每跑一次命令行就从头重新想一遍。

相比之下,几乎没有哪家第三方模型会专门去针对 OpenAI Codex 私有的 apply_patch 补丁语法做强化学习。结果可想而知:同一款第三方模型,放进它提前刷过题库的 Claude Code 壳子里配合顺畅;而通过中转站塞进它感到陌生的 Codex 壳子里,即便接口调通了,干活时的灵巧度也会明显打折。

四、别再简单算“1+1”了:模型不是 1,壳子也不是 1

别觉得这只是几个极客编程工具之间的事。现在国内做企业级 Agent 产品、搭内部智能体平台的团队,大多都在参考 Claude Code 和 Codex 的架构设计。把这两家的机制拆清楚,其实正好戳破了我们平时做 AI 产品设计时经常挂在嘴边的一个伪命题。

平时讨论模型(Model)和工程框架(Harness / 壳子)的关系时,大家习惯说“配得好就是 1+1>2,配不好就是 1+1<2”。但这个算式本身其实立不住——因为在实际工程里,不是所有的模型都等于 1,也不是所有的壳子都等于 1。

光看外面那层壳子,不同框架替模型分担的工程活就完全不在一个量级。

有的壳子做得很“厚”,自己本身就是一套严密的外骨骼。在调模型之前,它先通过语法树解析或固定规则把上下文嚼碎了喂到模型嘴边;用严格的状态机规定好第一步必须查什么、第二步必须改什么;模型输出后,外层代码自动跑静态检查或格式校验,不合规直接打回重来。这种厚壳子本身就在替系统兜底,往里注入确定性的工程逻辑。

而像现在的 Claude Code 和新版 Codex,走的则是“薄壳子”路线。它们把外层预设的条条框框越做越薄,甚至砍掉了早期常见的复杂向量检索流程,只给模型提供最基础的命令行、文件读写和搜索工具,再配上一套干净的上下文压缩机制。至于先查哪个目录、怎么定位问题、改完怎么验证,把探索路径的决策权完全交还给模型。

再看里面的模型。不同模型不仅基础能力有高低,脾气秉性也差得很多:有的模型单次深度推理很强,适合一口气解一道复杂的逻辑题;有的模型则强在耐造,连续调用二三十次小工具去翻目录、试错排查,依然条理清晰,不会聊着聊着就忘了最初的目标。

当你把厚薄完全不同的壳子,和脾气完全不同的模型拧在一起时,出来的根本不是简单的加减法。

如果业务受限于成本、延迟或私有化部署条件,只能用参数量较小、或者长程规划能力偏弱的 60 分模型,那把壳子做“厚”就是必须的。靠外层写死的业务流、精准的前置检索和严格的校验规则替弱模型补短板,能把一个原本不及格的模型托举到 80 分的可用水准。这时候如果盲目学大厂搞什么“极简薄壳子”,把流程约束全砍掉、只给弱模型开放底层工具权限,结果往往是一团糟——一个注意力容易涣散的模型,面对高自由度的环境,会在几十次无效查询中把上下文耗光,连问题出在哪儿都摸不清。

但反过来,现在更常见的痛点其实是拿 95 分的强模型去配早年留下的“厚壳子”。

早期模型能力有限、容易出幻觉的时候,我们在设计产品架构时,习惯用极其细碎的步骤把模型捆起来:强制先走意图分类节点、再走固定改写节点、再按死板的模板一步步执行。但当底座模型迭代到具备强推理与自主规划能力的新一代时,当初那些为了防弱模型犯傻而设计的厚重规则,反而变成了整个系统的天花板。

模型原本调两次基础工具、花几秒钟就能直接定位并解决的问题,却被外层写死的十几个步骤按着头走完;遇到稍微超纲的边缘情况,模型明明有能力自己写个脚本或换个思路绕过去,却被死板的预设规则当成异常直接卡死。当初为了替弱模型补短板而造的“拐杖”,在模型变强之后,不知不觉变成了锁死系统上限的“枷锁”。

五、换模型别只看裸分,升级时记得“拆拐杖”

折腾完这一圈跨模型接入,再回头看日常手头设计的 Agent 架构,我对“怎么选模型、怎么搭壳子”有了两个很具体的改观。

一个是选型和切换模型时,别太迷信公开榜单上的“裸分”,也别以为网关改个地址就万事大吉了。

公开排行榜上的分数,是模型在别人的标准靶场里跑出来的。真要在自己的产品里引入或替换一个底层模型,唯一靠谱的办法就是抽出业务里最真实的几十个复杂 Case,把候选模型直接接进你现有的代码框架、提示词和工具集里跑一遍“带壳测试”。因为不同模型家族对 System Prompt 的结构偏好、工具拆解的粗细粒度、甚至对报错文本的敏感度都不同。如果做多模型路由时只切 base_url 和 model 字段,而不配套切换对应的提示词模板与工具描述,线上效果大概率会出现明显波动。

另一个更重要的习惯,是跟着模型的水位定期去“拆拐杖”。

以前做传统软件,工程逻辑往往是越堆越厚的;但做 AI 产品,外层的壳子得跟着模型的能力一收一放。在模型能力顶不住的地方,老老实实用确定性的工程规则兜底;而每当底座模型迎来大版本升级时,除了测试新能力,最值得干的一件事其实是拿着剪刀去做减法——试着把半年前为了防模型犯傻而加的硬编码拆解步骤、繁琐的前置分类规则拿掉几个,换成更纯粹的原子工具和结果校验机制。

把不该管的过程交还给变聪明了的模型,只用工程手段守住输入输出的边界,系统往往能跑出比人工预设流程高得多的上限。

本文由 @Talen 原创发布于人人都是产品经理。未经作者许可,禁止转载

题图来自Unsplash,基于CC0协议

更多精彩内容,请关注人人都是产品经理微信公众号或下载App
海报
评论
评论请登录
  1. 目前还没评论,等你发挥!