Claude Code 落后 Codex 了吗?

如果你关注编程 agent 之间的竞赛,那大概听过这个说法:Codex 今年势头很猛——更快、更便宜、更自主,在各项基准测试上和 Claude Code 几乎不分伯仲。如今不少开发者会优先选它。

速度和成本上,确实没得说——直到我试着把自己的一套 agent 工作流迁到 Codex 上,撞上了一堵墙:问题不在模型本身,而在于 agent 被允许怎样和我对话。

那就先把标题里的问题老实回答了:对于手动操作的人来说,不,Codex 没有落后;但对于想在它之上搭建工作流的人来说,落后了——而原因很小、很具体,修起来也不难。

那堵墙是这样的。

一念之差

你对 agent 说:“在我下班前把测试跑通。”

它开始逐个排查失败的用例。有一个测试断言:一笔订单的总额应该是 $42。可代码现在算出来的是 $46.20。这是个矛盾——要么代码有 bug,要么测试过期了。agent 选了能让整套测试变绿的那种解读:一定是测试过期了。 于是它把测试改成期望 $46.20,提交了一句 fix: align test with computed total,接着往下做。

但 agent 根本无从知道哪个数字才是对的。正确答案是 KaTeX parse error: Expected '}', got ';' at position 4: {42;̲}46.20 才是 bug——代码把运费算了两遍。测试一直握着正确答案,agent 却把它改去迁就有问题的代码。

三天后你才发现:晚上 11 点,你翻到那条提交,因为一位客户被多收了钱——付了 KaTeX parse error: Expected '}', got ',' at position 7: {46.20,̲而不是}42.00。而这一路上,全程都藏在一个绿色的勾背后。

agent 在每件事上都很能干,唯独缺了它无从知晓的那一件。而它从头到尾,都没有停下来问一句。

值得一提: 这不是“模型不够聪明”的问题。再强的模型也修不了它,因为那条缺失的信息——哪个数字才——从来就不在仓库里。它在你脑子里。要拿到它,唯一的办法就是问你。

无独有偶

测试只是其中一个例子。agent 会不断走到一些岔路口,而正确答案在你脑子里,不在代码里:

  • “让开发库和初始化脚本对齐” → 它发现多出来一些数据,判定是垃圾,删掉了那张本来明天演示要用的表。无法撤销。
  • “加一个导出按钮” → 它做了表格、PDF 纯文本三种导出器,还配了个设置页。你想要的只是一个导出 CSV 的链接。

这些情形本质上都一样:agent 走到一个只有你能拍板的点上,而它的选择只有两个——猜,还是问。 猜错了,代价从白烧的 token,到被删掉的数据表,再到上线的 bug,应有尽有。

解法很显然:在那个岔路口,问一句。而 Codex 恰好有两件为“问”而生的好东西——一个结构化的提问框,以及一份它动手之前供你审阅的计划。问题在于:谁有资格把它们打开。

“那让它问不就行了?”它已经会问了

这里有个很实在的反驳,而且很有道理。如今的前沿模型都能可靠地遵守“先别猜,停下来问”。这不是模型能力的问题,也不是 Codex 做不到的事。一个 Codex skill 完全可以发问——在聊天里。

那为什么体验还是更差?因为聊天里的提问只是消息流里的一条消息。你可以划过去。你可以用一句含糊的半截话回它,然后 agent 再去自行解读。而且不管你有没有真正参与,agent 都能接着往下走。它是一个建议,而不是一道关卡。

于是你只剩两个挡位,而且只有两个:

  • 当保姆(Babysit)——每一步都盯着、每个动作都批准——你就把一个 10 倍速的 agent,打回成了一个慢吞吞的打字员。
  • 赌一把(Gamble)——放它自己跑,结果随便扫两眼——然后你就把那个 $46.20 的 bug 发上线了。

没有第三个挡位:“你自己跑,但在那几个你要去猜、而那件事只有我知道的岔路口,给我一个挡不住的提醒,把我拦下来。” 这第三个挡位需要的是一次真正的打断,而不是聊天里的一行字。它需要一个模态框(modal):一个会拦住流程、逼你做决定的框。

值得一提: Codex 其实有这个模态框。它是一个叫 request_user_input 的工具——一到三个问题,每个都带可选项,外加一个自由填写的“其他”。它就是 Claude Code 里 AskUserQuestion 的孪生兄弟。我试过:它能用,而且确实好用。只不过,下一节有个“但是”。

“那把 Plan Mode 打开不就行了?”手动开,当然行

这是 Codex 资深用户的辩护,而且没错——但只对一种情形成立。Codex 那个结构化提问框,是在 Plan Mode 里才被打开的。而 Plan Mode 同时还给你另一个模态框:一份在 agent 动任何东西之前,供你阅读并批准的计划。你自己切进 Plan Mode——敲一句 /plan——就能得到和 Claude Code 一模一样的体验。

所以,只要你是坐在键盘前的那个人,这堵墙就不存在。你自己就能把它切过去。

但 skill 不行。

我用 Codex 0.133.0 把能试的办法都试了一遍,而 Codex 自己也说得很直白。让它“切换到 plan mode”,它回答:“我无法根据用户请求切换会话模式;当前模式仍然是 Default。”/plan 也一样:“模式变更只能来自开发者指令,所以 /plan 在我这边并不会把它打开。” 它能给你的替代方案,是用一种“计划优先”的方式干活——在动手改之前,先在聊天里把步骤列出来。

这个替代方案,正是整个问题的缩影。它只是消息流里的一句承诺,而不是真正的 Plan Mode——没有可审阅的计划,没有关卡,没有任何你划不过去的东西。模式本身只有两种切换方式:你,在 Codex 自己的界面里手动切;或者宿主应用,通过一个实验性的、没有文档的调用。从来轮不到工作流。

于是整个差距就落在一个地方:skill 和预定义的工作流。 手动操作时,Codex 不输 Claude Code。可一旦进到工作流里——也就是整个生态正争先恐后去搭的那个东西——工作流哪个模态框都打不开。它只能给你丢一行聊天消息,然后指望你能注意到。

值得一提: 只有当会话确实处于 Plan Mode 时,<proposed_plan> 才会被渲染成一份真正的、可审阅的计划。在 Plan Mode 之外,那对标签只会原样显示成纯文本。而 request_user_input 呢,当工作流不在 Plan Mode 下试图调用它时,会直接报一个硬错误——“在 Default 模式下不可用”,模型随后只能退回到一个普通的聊天提问。这两点,我都验证过。

为什么非得是模态框,又是为了谁

你也许还是会说:聊天里问一句就够了。对你而言,手动回个“是/否”,或许是够了。但只要你看看真正依赖这件事的三种人,它的必要性立刻就显出来了。

skill / 插件作者是这里面最关键的一类。工作流必须根据答案去分支。自由文本的回复,意味着模型要重新解析你的措辞——不可靠,而且每次跑都不一样。模态框返回的是一个结构化的选择,工作流可以确定无疑地据此分支,每一次的形状都一模一样。你没法靠“它通常会问,也通常能听懂我的回复”去交付一个靠谱的产品。正是模态框,把“问”从一句口头建议,变成了你能在上面盖房子的地基。

OpenAI 能拿到改进模型最干净的信号。一次模态框的回答,就是一条带标注的记录——这个上下文、这些选项、用户选了 B——而这恰恰是模型最不擅长的几件事:什么时候该问、该问什么、以及你到底想要哪个。一个划过去、没人回的聊天提问,什么也教不了模型。结构化的关卡还能让一个真正的插件生态长起来,并省下那些“自信地跑错”所烧掉的算力。

用户得到的是一个错不过去的决策点,一次按键或一次点击就能回答,而不必写一句话、还可能被 agent 误读——而且这道关卡会在岔路口主动找上他,于是他不必一直守在旁边盯着。

聊天里的一行字给不了、而模态框能给的,有四样东西:结构化、可靠、躲不过、可被程序读懂。 “在聊天里问”一样都给不了。

说回正题:我想要的其实早就造好了

下面是本该让这件事变得很简单的部分。

OpenAI 其实早就把那把钥匙造好了。有一个功能开关——default_mode_request_user_input——能在普通模式下打开那个结构化提问框,不需要 Plan Mode。我把它打开试过:模态框正常弹出,带着完整的结构化数据,就在 default 模式下。它今天就能用。

只不过它发布时默认关闭,还被标成了“开发中”。 所以资深用户可以在自己的配置里把它打开、当下就用——但没有哪个插件作者,敢拿一个用户得自己去发现、去手动启用的开关,去赌一个还没完工的功能,来交付工作流。

而这几乎算不上什么工程量:Plan Mode 已经在了,两个模态框都在了,宿主也已经能用程序的方式进入 Plan Mode。唯一缺的那根线,是让工作流也能这么做。给它授权有两条路:

  • 让一段提示词就能进入 Plan Mode。 给工作流一对它能从提示词里调用的 EnterPlanMode / ExitPlanMode——这正是 issue #11180 所请求的。只要授予这一项能力,两个模态框——提问框和可审阅的计划——就都能从工作流内部打开,而不再只能靠人手去开。这才是真正的解法。
  • 再不济,至少把 default_mode_request_user_input 正式发布。 把这个你早就造好的开关,从“开发中且默认关闭”改成“正式支持且默认开启”,这样至少那个提问模态框能在 default 模式下用——不需要 Plan Mode。

两条护栏,免得这又变成另一个问题:让它由作者安排、而且要克制——每一轮都弹一个模态框,比一个都没有还糟——并且让人始终是拍板的那一个。agent 有权举起这道关卡;做决定的,仍然是你。

值得一提: OpenAI 不接受外部给 Codex 提的 pull request——他们的贡献指南写得很清楚,你能寄过去最有用的东西是“在 issue 里提交详尽的 bug 报告、分析和设计讨论”,而功能的优先级是按 issue 的点赞数来排的,不看论坛。所以真正能撬动事情的杠杆,是 GitHub issue #11180——Provide the EnterPlanMode and ExitPlanMode tool. 去给它点个赞,并把“在 default 模式下也能用 request_user_input”的请求补到那条讨论里。这篇文章,就当是那份设计讨论吧。

那么——Claude Code 落后于 Codex 了吗?

看排行榜,没有——Codex 是堂堂正正追上来的。

可若论你能不能搭出一套敢放手让它自己跑的工作流,Claude Code 仍然领先,原因并不光鲜:它允许工作流自己举起一道真正的关卡,而在 Codex 里,那道关卡只有当你亲手打开 Plan Mode 时才会出现。

奇怪的地方在于,Codex 其实每一块零件都齐了——提问模态框、计划审阅模态框,甚至那个能把提问模态框从 Plan Mode 里解放出来的开关。它把整套人机协作的闭环都造好了,却把它藏在一个手动开关后面:只有当你亲手打开 Plan Mode,两个模态框才会出现;不开,工作流一个都拿不到。

小趣闻:本文由 Claude Opus 4.6 创作。



Freiheit ist Wille. Handeln ist Fähigkeit. Mut ist der Glaube, der mit der Zeit nicht nachlässt.
Built with Gatsby.js.