乐于分享
好东西不私藏

三套 Agent 源码摆在一起,我看到的不是竞争,是三种世界观

三套 Agent 源码摆在一起,我看到的不是竞争,是三种世界观

前两篇我说 Agent 竞争争的是控制面,然后说控制面只是中间站、终局是模型自进化的实验室。这一篇要再改一次:把第三套源码摆上桌之后,我发现三家争的根本不是同一个东西。

先说一件我差点写错的事。

OpenAI 在 8 月 21 日发了篇公告,叫《Codex as a platform: build on the open agent harness》。消息传到我这儿的时候,说法是"OpenAI 的 Codex Harness 开源了"。

我按老流程动手:拉源码、固定 commit、算行数、跑结构。然后卡在第一步。

openai/codex 这个仓库不是这几天开源的。它 2025 年 4 月 13 日就创建了,Apache-2.0,Rust 实现在 4 月 24 日就以 codex-rs/ 首次导入,commit message 写得很清楚:feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)。到我拉代码的这天,它已经有 9,683 个 commit、11.1 万 stars、1.7 万 forks。

那这几天到底发生了什么?

发生的是改名。 OpenAI 第一次用 "open agent harness" 这个词来定义这个仓库,同时划了一条边界,原话是:

"The open-source layer is the harness and integration surface; model access and managed services remain separate."

配套上线了一张开源清单:CLI、SDK、app-server、Security CLI、Skills、Plugins、云环境镜像都开源;IDE 扩展和 Codex cloud 不开源。

所以这不是代码从闭源变开源,是叙事从"我们做了个终端编码工具"切换到"我们提供一套可嵌入的 Agent 运行时"

这个区别不是抠字眼。它直接解释了我后面看到的很多东西:Codex 的架构不是为开源设计的,它是一套按闭源产品节奏演进了 16 个月的代码库,然后被重新贴了个标签。它身上那些"不彻底",全都能从这个出身上找到解释。

把它和前两篇拆过的 Claude Code、DeepSeek Harness 摆在一起,我原本以为会看到一场三家争抢同一块地的竞争。

拆完之后,我改了判断。

三家不在抢同一块地。它们在回答三个不同的问题。


一、先把家底摊开

三个基线,全部固定到具体 commit。

Codex970b7f2ff4f612b8e8cd340eb6b6d789d7141dd2,2026-08-21 23:14 UTC,最后一条 commit 是 Preserve strict MCP auto-review outcomes (#40031)。3,271 个 Rust 文件,145.6 万行,其中测试约 62 万行(占 43%),产品实现约 83 万行。102 个 crate 目录,135 个 Cargo workspace member。14,118 个测试注解,741 个 snapshot 文件。

Claude Code:2026-03-31泄露的源码快照。这次我做了一件前两篇没做的事——把它对应回具体 npm 版本。答案是 2.1.88,发布于 2026-03-30 22:36 UTC。1,884 个 TS/TSX 文件,51.27 万行,无测试、无构建配置、无许可。

DeepSeek Harness:主基线仍是 0.1.0-rc.5 / commit 47f943859b,但这次核对了一周后的 0.1.1-rc.2(2026-08-21)。

先说一个规模上的反直觉结论:Codex 是三家里代码量最大的一套,产品实现行数约是 Claude Code 快照的 1.6 倍、DSH 产品源码的 3.6 倍。而且它的开发速度也最猛——8 月 12 日到 21 日这十天,542 个 commit,单日峰值 99 个。

一个日均五六十次提交的仓库,你很难说它是"发个公告"的产物。

再说两个我在核对过程中意外挖到的东西,我认为它们比公告本身更有信息量。

第一个:Claude Code 已经在四月堵上了那个洞

3 月31日那次泄露,走的是 npm 包里 cli.js.map 的 sourcesContent 字段。

我顺着版本号往后查 unpackedSize:

  • • v2.1.112:49,328,681 字节(一个巨大的 JS bundle)
  • • v2.1.113:132,292 字节

一夜之间掉了 99.7%。查下去,bin 改成了 bin/claude.exe,通过 8 个平台的 optionalDependencies 分发原生二进制。发布日期 2026-04-17——距离泄露 17 天。

今天最新的 2.1.239(8 月 21 日)npm 包只有 26KB,只剩一个 wrapper 和 installer,一行 sourcemap 都没有

这件事有两层含义。第一层是 Anthropic 在两周半内做完了一次分发架构改造,速度值得尊重。第二层对我这种做源码分析的人更要紧:从 2.1.88 到 2.1.239,中间隔了 151 个版本、近五个月。 我前两篇里所有 Claude Code 的结论,都必须理解成"2026 年 3 月 31 日的架构切片",不是今天的产品。这个偏差还在每天扩大,而且再也补不上了。

我在这篇里对 Claude Code 的所有评价,请都按这个口径读。

第二个:DSH 一周加了 5.2 万行,但那个数字没变

一周增量对比:

0.1.0-rc.5
0.1.1-rc.2
包数量
219
227
TS/TSX 行数
564,122
616,345
SESSION_FORMAT_VERSION
0
0

一周 5.2 万行、8 个新包,还多了个 experimental 目录。节奏一点不慢。

持久化格式版本号还是 0

前两篇我说 DSH 的存储兼容性没进成熟期,一周之后这句话依然成立。这不是批评——preview 期不锁格式是对的。我记这一笔是因为:如果你打算基于 DSH 做企业底座,那条会话日志现在还不能当长期资产。


二、三个不同的问题

好,家底摊完。现在说我拆完之后最大的那个判断修正。

我原本准备写的是一篇三方评测:谁的 loop 更先进、谁的工具更多、谁的多 Agent 更强。评分矩阵我甚至都列出来了,19 个维度。

然后我发现那张表最有意思的不是分数高低,是三家的高分区完全不重叠

  • • Codex 高分在:对外集成面、Agent 可治理性、安全架构、远端执行、工程可验证性
  • • Claude Code 高分在:长期记忆、编码体验
  • • DSH 高分在:核心可组合性、状态可回放性、模型中立性、生产语义严谨性

不重叠到这个程度,说明它们不是在同一道题上分出高下,是在答不同的题。

我把三家的问题翻译成人话:

Claude Code 在答:怎么让一个人在终端里获得最好的编码体验?

Codex 在答:怎么让别的产品把 Agent 用起来?

DeepSeek Harness 在答:怎么让 Agent 的形态本身可以被改写?

下面三节,我用源码证据说明这三个答案分别长什么样,以及它们各自付出了什么代价。


三、Codex:把 Agent 藏到界面背后

如果只让我从 Codex 里挑一个设计说,我不会挑它的沙箱,也不会挑它的 Guardian,我会挑 app-server 协议

这套协议是类 JSON-RPC(源码注释很坦率:We do not do true JSON-RPC 2.0, as we neither send nor expect the "jsonrpc": "2.0" field.),v2 版本下有 37 个命名空间:

thread / turn / item / thread_usage          会话与轮次permissions / review / hook                  权限、审查、钩子mcp / plugin / apps                          扩展与工具model / bedrock / environment                模型与环境realtime / remote_control                    实时与远控command_exec / process / fs                  执行与文件系统browser_use_config / computer_use_config     浏览器与计算机操作

最后那两个是最近一周才加的。也就是说,浏览器操作和 computer use 也正在被塞进这个协议面。

配套是 Python 和 TypeScript 官方 SDK,Python 那边 15 个示例,从 quickstart 一路到 turn controls、login。

这套东西的技术难度不高。JSON-RPC 谁都会写。

它真正领先的是公告里的一句话。OpenAI 说,这套东西的目标不是让你"reproduce the Codex app with a different logo",也不是"replace those interfaces with a universal chat box",而是让 dashboard、timeline、地图、工单记录——人真正用来理解和控制工作的那些界面——成为 Agent 的宿主。

他们放了个示范应用叫 Relay,一个虚构的物流看板。用户要做的事是点一个叫"Compare recovery"的按钮,不是写 prompt。数据是假的,但这个交互细节比整套协议更能说明问题。

我做了十几年 AI 机器人,这个判断我认得出来它对在哪儿。

大部分真实业务场景里,人需要的不是一个更好的聊天框,而是原有工作界面背后多了一个会干活的东西。

产线主管要的不是一个能聊工艺的 AI,是他每天看的那张看板上,异常项旁边多了个"分析原因"的按钮。财务要的不是一个能算 DCF 的机器人,是她的表格里多了一列自动填好并标注了依据的数据。销售要的不是能写话术的助手,是 CRM 里那个客户卡片下面自己长出了一段"上次沟通后发生了什么"。

聊天框是 AI 从业者的舒适区,不是用户的。

DSH 的 Web/Headless bundle 技术上也能干这件事——它的 UI 层本来就可替换。但两家的叙事差一个层次:DSH 说"你可以换 UI",Codex 说"你的产品才是主体,Agent 是后台"。

前者是把 UI 当成一个可配置项,后者是把 Agent 当成一个被消费的服务。

除了协议,Codex 还有三个设计我认为其他两家没对手。

第一是 Agent 的密码学身份。agent-identity crate 用 Ed25519 密钥对,向 OpenAI 注册获取 JWT。三家里只有它给 Agent 一个独立身份,而不是让 Agent 借用人的 token。

方向完全正确。Agent 干的事应该归因到 Agent 自己——出了事你要能说清"是哪个 Agent、在哪个授权下、动了什么",而不是"张三的账号干的"。

第二是跨子树成本核算。 源码里那行注释一看就懂:

/// Shared accounting and reminder state for one root-thread session tree.

作用域是整棵 session tree,不是单轮、不是单线程。子 Agent 派生出去的消耗算进同一个池子。加权公式还区分输入输出:output_tokens × 采样权重 + 非缓存input × 预填权重。超了直接抛 SessionBudgetExceeded。还有阈值提醒,会把"你还剩多少预算"注入给模型。

三家里只有它考虑了"子 Agent 递归派生把钱烧光"这个场景。 Claude Code 有 maxTurns 和 maxBudgetUsd,但作用域是单次 query;DSH 干脆没有内建预算,得自己写插件。

我自己那套多 Agent 系统上个月就吃过这个亏——一个子 Agent 在循环里反复调工具,我是从账单上发现的。

第三是工具曝光面分级。ToolExposures 三个 bitflag:DIRECT | DEFERRED | CODE_MODE。标 DEFERRED 的工具不出现在初始工具列表里,模型要通过一个搜索工具才能发现它。

这直接怼着一个真问题:工具越加越多,每次请求的 token 越贵,而且大部分工具在大部分任务里都用不上。分级之后,工具数量增长不再线性推高上下文成本。

我自己的 Agent 系统的 skill 已经几十个,撞墙是必然的。这个设计我准备直接抄。

那 Codex 的代价是什么?

两个,都很硬。

第一,内核不可替换。 它的核心 loop 在 core/src/session/turn.rs,函数叫 run_turn单文件 2,791 行。权限、压缩决策、重试、遥测、stop hook 全部内联在里面。压缩要不要触发是在 loop 里内联算的,重试判断在采样内层 loop 里,遥测直接嵌在 task 生命周期上。

它的扩展体系确实丰富——13 类 typed contributor trait、11 类 hook 时机、npm 形态的插件、MCP。但你看它的注册表实现:

thread_lifecycle_contributors: Vec<Arc<dyn ThreadLifecycleContributor<C>>>,turn_lifecycle_contributors:   Vec<Arc<dyn TurnLifecycleContributor>>,tool_contributors:             Vec<Arc<dyn ToolContributor>>,approval_review_contributors:  Vec<Arc<dyn ApprovalReviewContributor>>,...

全是 append-only 的 Vec。 你能往里加,不能替换已有的,更不能换掉 run_turn

这是钩子注册表,不是 DSH 那种"后加载层可以按 id 替换前层整份配置"的插件树。

第二,也是更关键的:开源了 harness,但 harness 的一半能力在闭源服务里。

公告里唯一的量化论据是:ARC-AGI-3 上,保留 reasoning + 上下文压缩,让 GPT-5.6 Sol 从 13.3% 提到 38.3%,同时输出 token 降到六分之一。OpenAI 用这个数字论证 "Harness design can materially change results"。

我去查了这个"压缩"在源码里怎么实现的。答案是四条路径,其中两条叫 Remote Compaction——把整段历史发到 OpenAI 后端,由服务端做摘要

而 ProviderCapabilities 里写得很清楚:Ollama、LM Studio 这些第三方 provider 的默认值是 RemoteCompactionSupport::Unsupported

换句话说:那个用来证明"harness 决定结果"的提升,恰好来自开源部分之外。

同样的模式还有 Guardian 评分(依赖特定模型)、Agent Identity 注册(硬编码 auth.openai.com)、reasoning item 保留(OpenAI 推理模型专有字段)。

所以 Codex 的模型中立性我给 5.5 分——框架层是中立的,能连上就能对话;但一旦你要用它区别于普通 chat 客户端的那些能力,就必须回到 OpenAI 后端。

Amazon Bedrock 是唯一的例外,有近对等支持(含 Remote Compaction V2)。但 Bedrock 上跑的还是 GPT。这是部署中立,不是模型中立。


四、Claude Code:唯一还把人当主角的那个

这一节会短,原因我前面说过——我手上的快照落后五个月,说多了不负责任。

但有两个结论我认为跨版本仍然成立。

第一,长期记忆仍然没有对手。 三层记忆 + 自动提炼 + Side-query 这套组合,Codex 有个功能相近的东西(两阶段自动提炼),但默认关闭;DSH 至今没有同等级的产品化记忆。

第二,maxTurns 和 maxBudgetUsd 这类护栏,只有它内建在核心里。 无人值守场景下这不是加分项,是准入项。

我保留前两篇的推荐不变:如果今天要给一个团队推荐直接干活的编码 Agent,我仍然先看 Claude Code。

但我要加一条这次才想清楚的东西。

Claude Code 的架构里,人始终在驾驶座上。QueryEngine 集中承担产品语义,Tool 抽象连终端渲染都耦合进去了——这在架构纯洁性上是缺点,但它暴露了一个设计前提:这个工具假设有一个人正在看着它。

Codex 假设 Agent 在界面背后运行,人只在审批点介入。DSH 假设形态可以被人或模型在运行时改写。

只有 Claude Code 假设:有一个人,坐在终端前,一直看着。

这个假设今天成立。三年后成不成立,我不确定。


五、DeepSeek Harness:唯一把方向盘交出去的

前两篇写了很多,这里只补三点新观察。

第一点,那个"工具结果未知"的语义,我这次才真正理解它的分量。

三家崩溃恢复的做法对比:

  • • Codex:turn 被打断时,drain_in_flight 收口所有 in-flight future,成功的写历史,失败的报错。然后在历史里留一条"上一轮被打断了"的 marker。
  • • DSH:如果发现工具调用已记录但结果没记录,合成一条 TOOL_OUTCOME_UNKNOWN,明确告诉模型:只读或幂等操作可以考虑重试,有外部副作用的操作必须先核验状态或者问人,不许盲目重试

Codex 的做法在编码场景问题不大——大不了重新读一遍文件。

但你把这套东西用到"发邮件、改数据库、调支付接口"的场景,"进程崩溃"和"外部动作未发生"从来不是同一件事。

我做硬件的时候,产线上有个规矩:设备重启后不能假设上一条指令没执行,必须先读状态。这条规矩是拿事故换来的。

DSH 这个设计是三家里唯一把这条规矩写进协议的。

第二点,DSH 至今仍是唯一能把别人家 Agent 当工人的。

它的 Subagent Provider 支持五种执行者:进程内 spawn/fork、ACP、DSH SDK、Claude Code、Codex

Codex 这边有个 crate 叫 external-agent-migration,我一开始以为是对等能力。读完发现不是——它是配置迁移工具

pub(super) enum ExternalAgentSource {    Cla,  // Claude Code    Cur,  // Cursor}

迁 hooks、迁 MCP 配置、迁 memory 文件、把 Claude Code 的 subagent 定义改写成 Codex 格式。

这是"把你的配置搬过来",不是"把你当工人用"。 是竞争动作,不是互操作动作。

前两篇我说下一场竞争争的是异构执行控制权。加入 Codex 之后这句话更清楚了:Codex 明确选择不做这件事。 一年多、9,683 个 commit、102 个 crate,它没有往这个方向走一步。

第三点,DSH 的短板这一周没变。 格式版本号还是 0,还是没有内建预算闸门。

架构上限高不等于今天能用。这句话我写第三遍了。


六、三家独立收敛的四件事

到这里我想换个角度。

比较三家的差异是一种读法。另一种读法是:它们在哪些事上独立走到了同一个答案?

后者信息量更大。因为差异可能来自路径依赖、团队口味、历史包袱,而收敛往往意味着"这是被现实逼出来的"。

我数出四件。

收敛一:Code Mode——一次往返只调一个工具,是公认瓶颈

Codex 有 code-mode 系列四个 crate,工具名就叫 exec 和 wait。模型不再逐个调工具,而是写一段代码在持久 session 里跑,通过 wait 轮询。Session 以 cell 为单位,有堆大小和让出时间上限——就是 Jupyter cell 的语义。

DSH 也有 Code Mode,前两篇写过。

两家独立收敛到"让模型写程序而不是逐个调工具"。

顺带纠正一个我以为的事:Codex 的 Code Mode 运行时不是内嵌 V8。仓库里那个 v8-poc crate 第一行注释写着 proof-of-concept crate reserved for future V8 experiments,只验证了 V8 能链接,没有 Agent 功能。实际运行时走三种 provider:独立进程、WebSocket、gRPC。

收敛二:核心变薄、能力外置

Codex 这条线我是靠 git 时间戳挖出来的。它的 ext/ 目录下每个能力的首次提交:

2026-05-11  extension-api(typed 扩展接口)2026-05-13  memories2026-05-18  goal2026-05-26  web-search2026-05-28  image-generation2026-06-03  skills2026-06-09  mcp2026-06-24  connectors2026-07-08  items2026-07-14  agent2026-08-06  queue2026-08-13  guardian-v22026-08-21  history-notes  ← 我拉代码这天

四个月,13 项能力从 core 里搬出来。

这条时间线本身就是证据链:Codex 的扩展化改造不是为公告临时拆的,是一次持续四个月的架构演进。公告只是给它起了个名字。

DSH 从设计起就没有特权内核。Claude Code 有 Skill / Plugin / Hook。

三家都在往"核心变薄、能力外置"走。分歧只在拆到哪一层停。 Codex 拆到 extension-api 就停了——loop 和 session store 还在里面。DSH 一路拆到底。

收敛三:没人上向量检索

Codex 的记忆是平文件 + SQLite + git baseline,搜索是文件遍历,没有嵌入索引。Claude Code 是分层文件。DSH 没有同等系统。

三家都没上向量库。

在 Agent 场景里,"结构化文件 + 模型自己 grep" 目前打得过嵌入召回。

这件事挺反直觉的——RAG 讲了两年多,结果最前沿的三套 Agent 都不用。我的理解是:Agent 有工具,能自己决定查什么、查几轮、查不到换个词再查。这个能力比一次性的向量召回强,因为它是带反馈的检索,而不是一次性的相似度匹配。

Codex 里有一个记忆设计我要单独拎出来说:它用 git 做记忆 baseline。~/.codex/memories/.git 加一个 phase2_workspace_diff.md——每次记忆整合都是一个可审计、可回滚的 diff。

收敛四:上下文压缩是一等公民,不是优化项

三家都把压缩做进了核心机制,不是"内存紧了再说"的优化。

OpenAI 那个 13.3% → 38.3% 给了这件事一个量化锚点——虽然是厂商自述、未独立复现,但方向上足够。

Codex 还有个细节值得抄:它的上下文注入抽象叫 ContextualUserFragment,每个 fragment 带起止 marker,render 出来是 {start_marker}{body}{end_marker}

有 marker 意味着注入的内容能被后续识别和替换。压缩时可以精确区分:哪段是可重建的注入内容(记忆、项目指令、预算提醒),哪段是不可再生的真实对话。


七、最深的那个分歧

四件收敛说完了。现在说三家真正分歧在哪儿。

不在技术。技术上它们互相都能抄——JSON-RPC 谁都会写,事件溯源不是黑魔法,沙箱是现成的内核能力。

分歧在 "谁应该拥有改写 Agent 形态的权力"

Claude Code 的答案是:厂商。 我把产品打磨好,扩展点我给你留够。QueryEngine 里那些集中的产品语义,是"我替你想好了"的具体形态。

Codex 的答案是:宿主应用。 你的产品是主体,我把执行能力和治理能力交给你,但内核归我。app-server 协议是这个答案的具体形态——37 个命名空间对外全开,2,791 行的 run_turn 对外全闭。

DSH 的答案是:运行时的使用者,人或者模型。 连 loop 都是插件,形态在运行时决定。

前两篇我说下一场竞争争的是控制面——会话真源、权限边界、异构执行。

加入 Codex 之后我要往上补一层:控制面之上还有"集成主权"——Agent 到底是宿主产品里的一个组件,还是宿主产品要围着 Agent 转。

Codex 明确选了前者,而且是三家里唯一明确选的。

我认为这个选择在长期可能比它所有技术细节都重要。

理由很简单。我们这个行业过去两年默认了一个前提:AI 的入口是对话。所以所有人都在做更好的对话——更长的上下文、更强的多轮、更聪明的意图识别。

对话是 AI 从业者的舒适区,不是用户的舒适区。

一个用了十年 SAP 的财务,不想学怎么跟 AI 说话。她想要的是那个她闭着眼都能操作的界面里,某个字段旁边多了一个能点的东西。

一个每天看 20 张产线报表的主管,不想在聊天框里描述"帮我分析一下昨天二线的良率异常"。他想要的是那张报表上异常的数字变成可点击的,点下去出来的是分析过程和建议。

Agent 的最终形态,大概率不是聊天框,是原有界面背后多出来的那个执行层。

Codex 押的是这个。DSH 押的是"形态本身可改写",这个更远也更抽象。Claude Code 押的是"人还在驾驶座上",这个最保守也最实用。

三注都不算错。但它们赌的是三种不同的未来。


八、一个可以在 2027 年 12 月 31 日打脸我的预测

前两篇都留了可证伪的预测,这篇继续。

到 2027-12-31,我预测:Agent 的主流交付形态会从"独立的对话应用"转向"嵌入既有工作界面的执行层",而衡量这件事的指标不是有多少人在聊天框里用 AI,是有多少 Agent 调用来自非对话入口。

具体的可验证形态:至少两家主流 Agent 厂商会公开发布"嵌入式集成"的采纳数据——不是"我们的 API 调用量增长了多少倍",而是"通过宿主应用协议发起的会话占总会话的百分比"。而且这个数字会超过 30%。

如果到那天,主流 Agent 厂商披露的仍然是 DAU、对话轮次、token 消耗这些以对话为中心的指标,宿主应用集成始终是个边缘用例,那这篇就是错的:Agent 就是新一代的聊天应用,我把 Codex 那个协议想大了。


九、接住三个最常见的反驳

「Codex 早就开源了,你这不是新闻。」

对,这也是我这篇开头花那么多字纠正前提的原因。但"代码可见"和"被定位为可嵌入运行时"是两件事。前者 16 个月前就发生了,后者是这周才发生的。而且更重要的是,我在 git 时间戳里看到的那条四个月扩展化改造的线,说明这次改名有真实的架构变化在背后,不是纯营销。

「app-server 协议没什么了不起,就是个 JSON-RPC。」

技术上确实没什么了不起。我要说的从来不是技术难度,是产品判断。Anthropic 有 SDK,DSH 有 headless bundle,技术上三家都能做到同一件事。但只有 Codex 在公告里明确说"我们不要 universal chat box",只有它的示范应用让用户点按钮而不是写 prompt。判断的价值不在实现难度,在它敢不敢放弃什么。

「Guardian 那套用模型审模型,听起来很危险。」

同意,而且我在报告里写了三条具体风险:每次工具调用多一次模型评分,成本和延迟都要算;DEFAULT_REVIEW_THRESHOLD = 0.5 这个阈值是拍出来的,没公开 ROC 曲线;审查者自己是模型,会被 prompt injection 攻。

但反过来说,静态规则拦不住语义级危险。rm -rf $SOMEVAR 的规则匹配和它的实际危害,从来不是一回事。

"用模型守模型"是必然方向,但它把安全从确定性问题变成了概率问题。 企业采纳时要想清楚这笔交换:你从"规则漏了就是漏了"换成了"有个 AI 帮你看着,但它会看错"。

这不是一笔纯赚的交易,是一笔要评估的交易。


拆完第三套源码,我最大的收获不是又学了几个新词。

是我看 Agent 的顺序又变了一次。

第一篇我说:先看它归谁控制。

第二篇我说:再看它给谁留了改写的口子。

这一篇我想加一个更前面的问题:

它假设人在哪儿?

在驾驶座上,在审批点上,还是根本不在。

这个假设决定了后面的一切。