源码对照(三):DeepSeek Harness 怎么做 Agent,以及两套系统的十条共识

专栏:Agent 工程 · 第 18 / 18 篇
AgentDeepSeek HarnessCodex架构

前两篇拆了 Codex。这篇换主角:DeepSeek Harness(dsh)——本站已有 14 篇专栏逐行读过的 TypeScript 插件化 agent harness。这里先把它的架构浓缩成一页,然后做真正有意思的事:把 dsh 和 Codex 并排放,看两个团队在互不知情的情况下做了哪些相同的决定

dsh 架构速览

图表(dsh-vs-codex-agent-patterns.md)

dsh 的五个关键决定:一切皆插件(模型适配器、工具注册表、循环本身都可替换,Cordis fiber 保证副作用可逆);session 是唯一真源(12 种核心事件、“模型可见即已记录”有运行时不变量断言);工具执行是十道工序的流水线(审批/guard/环绕/改写各有其位);能力 seam 三角色(换一个文件系统提供方 = 换掉整个执行世界);审批 fail-closednever 策略在分发前确定性拒绝,审计事件对必须落在轮次边界内)。

十条共识:两个系统的同一批决定

把 Codex(Rust,OpenAI)与 dsh(TypeScript,DeepSeek)并排放,不约而同的地方远比分歧多。每一条都值得问自己:为什么所有认真做 agent 的团队都走到了这里?

1. 会话 = 仅追加的 JSONL 事件日志。 Codex 的 rollout-*.jsonl + RolloutItem 枚举(消息、turn 上下文、token 用量、压缩事件);dsh 的 session.v2.jsonl + 12 种会话事件。消息历史都是日志的投影(Codex 从 rollout 重建 InitialHistory,dsh 用 deriveMessages()),且都有运行时断言保证”模型可见即已记录”。

2. turn/step 两级生命周期。 Codex:Task → run_turn → sampling 请求;dsh:turn → step(一次模型请求 + 它的工具)。轮次有原因枚举地关闭(completed/aborted/error/…),边界在日志里永远闭合。

3. 运行中转向(steer)。 Codex 叫 start_or_steer_turn(pending input 每步领取进上下文);dsh 叫 steer()(next-step 队列 + 唤醒)。连名字都一样——长任务中途纠偏是刚需,不是噱头。

4. 上下文压缩是一等公民。 Codex:mid-turn auto compact、token 预算型压缩跳过总结直接换窗口;dsh:compaction 能力族 + replace 语义(遮蔽旧节点、日志永不删)。两者都把压缩做成可观测的生命周期事件而非静默行为。

5. 工具执行前必有关卡。 Codex:execpolicy 规则 → 审批 → 沙箱包装;dsh:tools/pre-execute waterfall → 单调 guard → tools/execute 环绕。策略一律在工具体之外,工具自己不管权限。

6. 审批策略是同一个小枚举。 Codex AskForApproval:untrusted / on-request(默认)/ granular / never;dsh:ask(默认)/ never + 沙箱模式三档。never 完全同义——确定性拒绝、绝不升级给用户。默认值都是”适度地问”。

7. OS 级沙箱,同一组机制。 Seatbelt(macOS)、bubblewrap+seccomp(Linux)、受限令牌/ACL(Windows)——两家连平台选择都一样,且都把”包装 argv + 按调用携带策略”作为统一接口。沙箱模式三档命名都相同:read-only / workspace-write / danger-full-access

8. 结构化的审批事件与审计。 两边审批请求都是类型化的结构化数据(Codex 的 ApprovalAction::ExecCommand 带 justification 与规则修正案;dsh 的 approval/asked/approval/decided 审计对),且都落在会话日志里可回放。

9. MCP 是工具生态的通用语。 Codex 用 codex-mcp+rmcp-client 连外部 server;dsh 的建议路径同样是每 server 一个插件。外部能力不再自研协议。

10. 子 agent 与委托是内建能力。 Codex 的 spawn_subagent / multi_agents handlers;dsh 的 ctx.subagents(进程内、ACP、甚至把轮次委托给别的产品)。上下文隔离 + 结果回收是共同动机。

图表(dsh-vs-codex-agent-patterns.md)

分歧同样有信息量

不同点主要在架构哲学而非能力清单:

  • 组装方式:Codex 是 Rust 静态 workspace + config.toml + AGENTS.md 分层;dsh 是 Cordis 动态插件树 + patch 按序叠加 + 热重载。dsh 把”可替换”推到极致(连循环都是插件),Codex 把”类型安全与单二进制分发”推到极致。
  • 模型协议:Codex 锁死 OpenAI Responses API(服务端压缩等深度耦合);dsh 的 ctx.llm 是适配器 seam,多提供方。
  • UI 路线:两者竟然都收敛到”终端 TUI + 无头 + 面向 IDE/程序的服务接口”三件套(ratatui vs Web GUI)。

收束:教科书循环之外,全是可靠性工程

专栏开篇画过那个十行的 agent 循环——两个系统当然都有它,但它只占代码量的 1%。剩下的 99% 是:会话录制与恢复、压缩、并发工具调度、审批与沙箱、扩展机制、可观测性。「智能体怎么做」的答案,一半在模型交互,另一半在这些”模型之外”的可靠性工程里——这也是为什么这个专栏的阶段三到六全部在讲后者。

沿这个思路继续深挖:Codex 系列第 16 篇第 17 篇;dsh 的逐行解读见「DeepSeek Harness」专栏全部 14 篇。

← 返回文章列表