Agent X-Ray
NotesSkillsAbout
Notes/源码拆解/Codex Harness/第15章

第15章:设计精华 —— 三种 harness 哲学对照

10 分钟 · 更新于 2026-09-01

第15章:设计精华 —— 三种 harness 哲学对照

本教程到这里拆完了 Codex 的十四个面。最后一章做三件事:把 Pi、dsh、Codex 三种哲学摆在一起;汇总前面散落的 26 条可迁移判断;说清楚哪些该抄、哪些不该。


一、三个问题,三个答案

三个 harness 其实在回答同一道题的不同问法:

PiDeepSeek HarnessCodex
它在问什么最少需要什么?最多能拆成什么?全都做完要付多少?
它的答案4 个包185 个包102 个 crate / 147 万行
优化目标可读完、可改动可替换可验证、可交付
质量保证代码少到能全读接口契约 + 每包文档14168 个测试
用户是谁会读源码的开发者要定制运行时的团队任何人
你能改它吗能,鼓励你改能,改配置就行基本不能
它给你的东西一个骨架一份能力接缝清单一份工程总账单

这张表最右一列的"基本不能改"不是缺点。Codex 不是给你改的,是给你用的——就像你不会去改 Chrome 的渲染引擎,但你会读它的沙箱策略。

三个"不做"的对照

Pi 教程列出了三件刻意不做的事。看看另外两家怎么处理:

Pi 不做的事Pi 的理由dshCodex
子 Agent用 tmux 就行四种委派机制两代实现 + 密码学身份(第 14 章)
权限弹窗"安全表演"approval seam四档策略 + Starlark 规则 + 模型判官(第 11 章)
计划模式写 plan.md 就行dsh-plan-mode 插件内置 plan 工具 + 计划流式渲染

Pi 的判断在它的定位下是对的。 一个给开发者改的 SDK,弹窗确实是负担;一个假设用户能对自己机器负责的工具,沙箱确实是过度设计。

差别在谁承担风险

  • Pi:用户是能读源码的开发者,风险自负
  • dsh:给你接缝,你决定怎么承担
  • Codex:用户可能是任何人,harness 必须兜住

这决定了三者的全部差异,包括代码量。


二、Codex 独有的五个观察

前面十四章里,有五件事是另外两个 harness 没有的,值得单独列出来。

2.1 协议先行导致的一切

第 3 章的 SQ/EQ 双队列是 Codex 全部架构特征的原点:多前端、可远程、可嵌入、可测试、事件即日志。

代价也是真实的:所有人机交互变成往返消息(EventMsg 里 5 个"要东西"的变体 + Op 里 5 个回应变体)、协议版本冻结(task_started/turn_started 双标签)、一个 Session 只能跑一个 Task。

2.2 系统提示词是数据不是代码

第 5、6 章:真正生效的系统提示词在 models-manager/models.json 里,随模型元数据远程下发,带 client_version 分版本。仓库里那 6 个 *_prompt.md 已经没人引用了。

这是"提示词工程"走向"提示词运维"的标志。 提示词有了版本、有了灰度、有了和模型能力的绑定关系。

2.3 用模型守模型,并公开判定标准

第 11 章的 Guardian。8281 字节的 policy.md 是目前公开的 agent 项目里少见的东西——一份可评审、可版本控制、可针对性测试的 LLM 判官策略

它的两个设计尤其值得记:二维判定(风险等级 × 用户授权)、一半篇幅在防误报

2.4 安全的纵深与成本

第 10、11 章加起来是四级防线 + 三套操作系统沙箱实现。跨平台成本比 Windows 19852 : Linux 9694 : macOS 1036

这个数据可以直接拿去做估算:给一个 CLI 工具加沙箱,Windows 那一份大概是 macOS 的 20 倍工作量。

2.5 为"agent 作为独立主体"做的准备

第 14 章的 agent-identity(Ed25519 + Curve25519 + JWT)+ workload-identity + 存储中立的 agent-graph-store + 第 9 章的远程执行环境。

这几条线指向同一个方向:分布式的、有身份的、可跨机器编排的 agent 集群。 目前还看不出完整形态,但基础设施在铺。


三、26 条可迁移的判断

按主题重排,★ 标记本教程认为最值得优先采纳的十条。

上下文工程

#判断
★⑨把环境状态当成可 diff 的结构化对象,每轮只把 diff(RFC 7386 merge patch)告诉模型6
★⑧每段注入的上下文带一对可识别标记 + 稳定分类 ID,便于事后剔除"哪些是系统注入的"6
★⑦让"这个模型该被怎么提示"和"这个模型有什么能力"住在同一份可远程刷新的元数据里5/6
把压缩写成"给下一个模型的交接"而不是"总结",并在压缩前后给出一致叙事7
长输出截断头尾各留一半,并明确告诉模型省略了多少9
来自模型训练分布的约束必须写成注释,否则会被"顺手优化掉"7

循环与状态

#判断
★④给每次模型请求冻结一份不可变的"世界视图"——广告出去的和实际执行的必须是同一份4
★②长耗时操作统一用 Begin / Delta / End 三段式事件3
把压缩、代码复核做成和普通对话平级的任务类型,而不是主循环里的 if 分支4
会话级与轮次级的客户端状态分成两个类型,把跨界复用的后果写在类型定义上5
append-only 日志要配一个反向读取器12

工具与执行

#判断
★⑬工具可见性不是布尔值:至少拆成"初始直出 / 可被检索 / 可代码化调用"三个维度8
★⑭需要模型产出结构化编辑时,设计一种"不数行号、靠内容定位、有明确边界"的格式,文法可放进提示词8
agent 的 shell 环境要么干净要么像用户,必须显式选一个9
把"以子进程方式调用自己"设计成显式的分发入口(arg0 技巧)2

安全

#判断
★⑲让权限/安全规则的定义格式自带示例断言,并在加载时执行(execpolicy 的 match/not_match11
★⑳LLM 判官的判定标准写成可读、可版本控制、可评审的策略文档,而不是提示词角落里的几句话11
★㉓区分「发现」和「启用」两个权限——仓库里的文件可以声明钩子,但启用必须在用户层,且内容哈希绑定13
★㉖委派权限单调收缩:子任务权限 ⊆ 父任务权限,无例外14
安全策略要有两份表达(给代码执行的、给模型阅读的),且同源6
安全相关的外部程序写死绝对路径,并在注释里声明威胁模型的边界10
拦截必须可观测——只会拒绝不说理由的安全层,会让模型反复重试烧完预算10

扩展与协作

#判断
★㉕多 agent 系统里"主 agent 派活之后该干什么"必须显式规定,否则它两边都做14
兼容别人的配置格式时只在"输入匹配"层兼容,不让别人的命名渗进自己的输出契约13
内部扩展平面要诚实命名("Contributor" 而不是 "Plugin"),传达"只能加不能换"13
模型差异从第一天就设计成配置而不是 match model_name 分支5

四、一个反复出现的模式:自由的策略 + 硬性的上限

这条单独拿出来,因为它在本教程里出现了至少五次:

场景自由的部分硬性上限
模型重试(第 5 章)provider 可配 stream_max_retrieshard cap,配不过天花板
自动压缩(第 5 章)用户可配 auto_compact_token_limitmin(用户值, 窗口 90%)
Guardian(第 11 章)模型自由判断风险连续拒绝 3 次熔断本轮
Guardian 上下文(第 11 章)转录内容由模型决定每一档都有独立 token 上限
多 agent(第 14 章)提示词鼓励"尽可能每步派一个"AgentRegistry 限制累计总数

模式是:把"做什么"交给策略(可能是用户配置,也可能是模型判断),把"最多做多少"写死在代码里。

这解决的是同一类问题:任何交给模型或用户的自由度,都需要一个它们够不到的兜底。 模型会陷入循环、用户会配错数值——上限是唯一不会失效的防线。

如果本章只带走一条 就带这条。它不需要你抄任何 Codex 的代码,只需要你在每次给出一个"可配置"或"由模型决定"的旋钮时,问一句:这个旋钮的最坏情况是什么?谁来兜?


五、哪些不该抄

诚实地列四条。

5.1 不要抄"只支持一种 wire 协议"

第 5 章的 WireApi 只有一个变体,是因为 Codex 是 OpenAI 的产品。如果你的产品需要接多家模型,这就是错误示范。

但要抄它背后的认知:"支持所有模型"意味着你只能用到所有 API 的交集能力。做这个决定时要清楚自己放弃了什么。

5.2 不要抄规模

147 万行、102 个 crate、14168 个测试,对应的是"每天几百万人用"和"跑在别人机器上执行任意命令"这两个前提。

如果你的 agent 跑在自己的服务器上、用户是内部同事,沙箱、四级审批、跨平台适配这些成本大部分可以省掉。Pi 的答案对你可能更合适。

5.3 不要抄"内部扩展平面比对外扩展点强"

ext/ 的 12 个 Contributor 是 Codex 自己用的,外部只能走五条受限通道。这个不对称对一个开源产品是合理的(他们要控制质量和安全边界),但对一个你希望社区参与的框架就是毒药。

dsh 的做法(对内对外同一套 seam)在那个语境下更对。

5.4 不要在没有测试基础的项目里抄它的复杂度

Codex 敢做四种压缩实现、六档工具可见性、三套沙箱,是因为有 14168 个测试兜着。同样的复杂度放在一个没有测试的项目里,就是一堆没人敢改的代码。

复杂度的准入条件是可验证性。这是第 2 章讲的"拆成 102 个 crate 是为了独立编译和测试"那句话的另一面。


六、对本仓的具体启示

这一节是本教程的落地部分。

6.1 技能系统

Codex 的 SKILL.md 和本仓用的是同一套 frontmatter(name + description),且都有"禁止模型自主调用"的机制(Codex 的 allow_implicit_invocation: false ≈ 本仓的 disable-model-invocation: true)。

可以直接借鉴的

  • Codex 的 description必填且缺失即报错(第 13 章)。本仓 35+ 个 skill 的 description 质量直接决定触发准确率,值得做一次审计
  • Codex 对第三方技能的非法 YAML 做行级修复但保留边界——本仓如果要接收外部 skill,这是现成的处理范式
  • Codex 的六档工具可见性(第 8 章)本质上在解决"35+ 个 skill 全塞进上下文太贵"的同一个问题。Deferred + BM25 检索是一条本仓还没走的路

6.2 供应链安全

第 13 章那条"项目层可以发现钩子,但无权启用"直接适用于本仓:

  • .claude/settings.json 的 permissions / hooks 是入库的,git pull 能改变它
  • .claude/skills/ 同理
  • 本仓的 CLAUDE.md 本身就是"仓库里的文件改变 agent 行为"

Codex 的两道防线——权限分离 + trusted_hash 内容绑定——是现成的答案。

6.3 规则要能自测

第 11 章的 execpolicy match / not_match 加载时断言,对本仓的 permissions 列表直接适用。现在的 Bash(git *) 这类模式,写错了没有任何反馈,只能等到被拦或没被拦时才发现。

6.4 长输出与上下文

  • 头尾各留一半(第 9 章)——本仓的脚本输出、BI 查询结果、codescope 回答都适用
  • World State 的增量 diff(第 6 章)——本仓的 wiki 两跳导航、sessions/ 归档在概念上同源:只告诉下游"变了什么"比"全量重发"省得多

6.5 会话过程的价值

第 12 章末尾的引申:本仓的 sessions/(Codescope 问答留存)和 GBrain/(研究摘要留存)与 Codex 的 rollout 解决的是同一类需求——agent 的价值有相当一部分在它跑过的过程里,不只在最终答案里

差别在粒度和消费者:Codex 存给机器分析,本仓存给 GBrain 检索和人阅读。两者可以互相借鉴——比如本仓的 sessions/ 目前只记 Q&A,不记"为什么问这个""中间试错了什么"。


七、这套教程没讲的

诚实列出盲区,供后续补充:

没讲在哪为什么跳过
TUI 的 27 万行tui/终端渲染,和 agent 架构无关
实时语音会话core/src/realtime_conversation.rs独立子系统,值得单独一篇
云端任务cloud-tasks*需要服务端配合才能验证
遥测与分析otel / analytics8121 + 13720 行,工程价值高但不影响架构理解
登录与认证login / chatgpt / aws-auth16041 行,产品化细节
Code Mode 的 V8 细节code-mode-runtime只讲了它在工具系统里的位置
网络代理的实现network-proxy(18491 行)只讲了它的定位
Bazel 构建bazel/ / *.bazelCI 基础设施

另外三个天然盲区(第 1 章提过):

  1. OpenAI 内部的设计文档与决策记录 —— 只能从代码和注释里反推
  2. 服务端行为 —— 远端压缩、模型元数据下发的服务端逻辑都在 API 那一侧
  3. 真实遥测数据 —— 那些常量(重试次数、token 上限、熔断阈值)背后的调优过程看不到

八、结语

本教程从"147 万行"这个数字开始,到这里可以给它一个更准确的解读:

它不是一个 agent 架构的复杂度,是一个 agent 产品的完整账单。

  • 循环本身很简单(run_turn 的核心只有 20 行)
  • 复杂度来自横切关注点(钩子、压缩、MCP、技能、世界状态、插话时序)
  • 更大的复杂度来自"跑在别人机器上"(三套沙箱、四级审批、shell 环境、远程执行)
  • 最大的复杂度来自"任何人都能用"(doctorupdate、四条分发渠道、协议向后兼容、14168 个测试)

Pi 问"最少需要什么",答案是四个包;dsh 问"最多能拆成什么",答案是 185 个可替换位置;Codex 问"全都做完要付多少",答案摆在那里,每一行都能查证。

三个答案都对。你的项目该站在哪个位置,取决于你的用户是谁、风险由谁承担。

而不管你站在哪,这份账单都有用——它告诉你,你现在欠着哪些账。


九、动手复核

bash
cd codex/codex-rs

# 把本章的"自由 + 上限"模式全找出来
grep -rn 'Hard cap\|hard cap\|MAX_\|_MAX\b' --include=*.rs \
  model-provider-info/src/lib.rs \
  core/src/guardian/mod.rs \
  core/src/agent/registry.rs \
  core/src/unified_exec/mod.rs | head -30

# 三个 harness 的规模对照(如果你也 clone 了 pi 和 dsh)
find codex-rs -name '*.rs' -print0 | xargs -0 cat | wc -l

  • 第14章-多Agent委派-从子进程到协作图
  • README-教程总览
  • Codex Harness 研究摘要
  • Pi 教程第 13 章 —— 减法哲学的总结
  • dsh 教程第 13 章 —— 全插件化的总结
  • Harness Engineering 研究报告 —— 行业方法论背景

本章目录
一、三个问题,三个答案二、Codex 独有的五个观察三、26 条可迁移的判断四、一个反复出现的模式:自由的策略 + 硬性的上限五、哪些不该抄六、对本仓的具体启示七、这套教程没讲的八、结语九、动手复核Related Documents
苏ICP备2025204887号-2