【学习笔记】解剖 OpenAI Codex —— 百万行零手写代码的 Harness 工程-10/15
3 个工程师。5 个月。约 100 万行代码。约 1500 个自动 PR。零行手写代码。
这不是一个关于未来的预言,是 OpenAI 内部今年完成的事。
他们用 Codex 本身构建了 Codex。整个工程栈里没有人坐在那里一行一行敲代码——工程师在做 的事情,是设计让机器能安全、持续、高质量地写出这些代码的环境。
这个环境就是 Harness。
上一篇我们解剖了 Claude Code——Anthropic 的参考实现。这篇换个角度:OpenAI 内部是怎么做的?两套 Harness,两种哲学,放在一起看,你才能看清楚各自在哪里做了取舍。
一、100 万行代码背后的工程矛盾
先想一个问题:Codex 写第 50 万行代码的时候,第 1 万行已经被修改过几十次了。Agent 不知道这件事——它只有当前上下文窗口里那一小块视野。
这是大规模 Agent 工程绕不开的核心矛盾:Agent 的能力在局部,问题的复杂度在全局。
让模型更聪明解决不了这个问题。上下文窗口再大,也装不下一个活跃迭代中的百万行代码库。
OpenAI 的答案不是更强的模型,是更聪明的 Harness。

二、野马、缰绳、骑手
OpenAI 工程师用过一个比喻,我觉得说得很准。
野马是 AI Agent——原始的、强大的、充满能量,但没有方向感。缰绳是 Harness——不是为了让野马跑慢,是为了让它跑在正确的路上。骑手是工程师——但骑手的价值不在于替野马跑路,而在于掌握缰绳、设计路线。
3 个工程师产出 100 万行代码,他们不是在用 Codex 帮他们写代码。他们是在设计让 Codex 能持续写出高质量代码的整套环境。
这个角色转变很微妙,但很关键。很多人看到「AI 帮你写代码」,第一反应是「那工程师要失业了」。其实不是——工程师的工作从写代码变成了设计写代码的约束系统。这个工作可能更难,但也更有杠杆。
三、Codex Harness 的设计逻辑
3.1文档即真相
OpenAI 内部有一个核心原则:任何逻辑,如果无法被写进文档,就不应该存在。
这不是说文档要多详细,而是架构设计要以文档可描述性为约束。
每个模块有一个 SPEC.md,描述这个模块做什么、不做什么、对外接口是什么。Codex 在修改代码前必须读 SPEC.md,修改后必须更新它。文档不是代码的副产物,是代码的前置约束。
这个设计解决了大规模 Agent 工程里一个很实际的问题:Agent 没有长期记忆。 三个月前的设计决策,Codex 完全不记得。但只要文档准确,它在任何时间点都能"回忆"起系统全貌。
跟 Claude Code 的 CLAUDE.md 对比——两者在解决同一个问题,路径不同。CLAUDE.md 是项目级的全局记忆,Codex 的 SPEC.md 是模块级的局部记忆。粒度不同,底层逻辑一样:把装不进上下文窗口的知识,写进 Harness 层。
3.2 架构约束要写成代码,不要写成文档
这听起来有点绕,解释一下。
架构规则,比如「A 层不能导入 B 层」,很多团队会写进 Wiki 或者设计文档里。问题是没有人真的会去遵守——不是因为大家懒,是因为没有执行机制。
OpenAI 把架构规则写成了 Linter,在每次 PR 合并前自动运行:
- 模块间依赖方向检查
- 公共接口是否符合 SPEC.md 定义
- 新增代码是否有对应测试
- 文档是否随代码同步更新
这些规则本身不复杂,但关键在于它们变成了可执行的门控,不是写在某个 Wiki 页面里等着被遗忘的规范。
违规的代码过不了 CI,进不了主干。这让工程师可以放心地让 Codex 自主提 PR——因为再差的 PR 也只是被 CI 拦下来,不会污染代码库。
Martin Fowler 把这类工具叫 Computational Sensor(计算型传感器)——确定性检测,快速,无需人工判断。这是 Harness 里最划算的投资:一次配置,永久生效。
3.3 对抗熵增:后台巡逻 Agent
软件系统有一个自然规律:代码只会越来越乱。重复逻辑积累、过时文档堆积、临时方案变成永久方案。
3 个工程师管 100 万行代码,靠人工定期重构不现实。
Codex Harness 里有一类专门的后台 Agent,任务不是写新功能,而是持续清理:发现重复代码并合并,更新过时注释,删除无用测试,标记性能退化的模块。这些 Agent 在后台跑,产出 PR,经过 Linter 验证后自动合并。
OpenAI 把这个叫 Garbage Collection——用了 GC 的概念,很贴切。代码库的熵增就像内存泄漏,不主动处理只会越来越严重,总有一天爆掉。
这是我认为 Codex Harness 里最有前瞻性的设计。Agent 写代码的速度比人快 10 倍,技术债务的积累速度也是 10 倍。只有把清理工作自动化,系统才能长期健康。

3.4 测试的优先级高于功能
这是 Codex 内部一个有点反直觉的工作顺序。
Codex 开始每个新任务,第一件事不是写代码,而是读现有测试——理解系统当前的行为边界。完成后,最后一件事不是提 PR,而是跑完整测试套件,确认没有破坏已有行为。
CI/CD 流水线不只是「跑测试」,是整个 Harness 的自动验证层:单元测试、集成测试、架构 Linter、性能基准测试、文档同步检查——全部通过才能合并。
一个 Codex 自动提的 PR,要经历比很多人工团队更严格的审查。这是用确定性约束弥补 Agent 不确定性的核心逻辑。
四、一个容易被忽略的细节:模型-工具耦合
OpenAI 在工程博客里提到了一个细节,很多人跳过了,但影响很深远。
Codex 5.3 对 apply_patch 这个工具格式有深度依赖。不只是调用——它在训练中形成了对这种格式的"肌肉记忆"。如果改变这个工具的接口,模型性能会显著下降。
这是模型-工具耦合。工具接口一旦被模型内化,就不再是普通的 API——改动它,就像改一个已经发布的对外协议,代价极高。
Claude Code 处理这个问题的方式是:工具集尽量小且稳定,减少需要频繁改动的可能。OpenAI 的方式是在文档里明确记录这个耦合关系,作为工程约束。
两种应对方式,同一个认知:工具设计的决策,比代码设计更难回滚。
五、两套哲学的完整对照
这两篇读下来,Claude Code 和 Codex 的差异变得很清晰:
| 指标 | Claude Code | OpenAI Codex |
|---|---|---|
| 记忆载体 | CLAUDE.md 全局文件 + Compaction | SPEC.md 模块级文档 + 文档即真相 |
| 架构约束 | 权限系统 + Hooks 生命周期 | 架构 Linter + CI/CD 门控 |
| 熵减机制 | 手动 /compact 触发 | 后台巡逻 Agent 自动运行 |
| 工具哲学 | 小而稳定,15 个精选 | 深度内化,apply_patch 耦合 |
| 执行环境 | 本地终端 + DevContainer | 云端沙箱 |
| 规模验证 | 持续自迭代的生产级工具 | 100 万行代码,1500 个自动 PR |
哲学层面,两种路线分得很开:
5.1 Claude Code 把 Harness 做成产品——开箱即用,边界清晰,降低门槛。代价是你在它的框架内工作,扩展性有天花板。
5.2 OpenAI Codex 把 Harness 做成工程基础设施——灵活,可扩展,能支撑大规模长周期交付。代价是你需要有足够的 Harness 设计能力才能用好,上手不容易。
你选哪种,取决于你是一个需要快速产出的独立开发者,还是需要支撑团队持续交付的平台工程师。两条路都走得通,但要走清楚。
六、工程师在做什么
最后说一个更大的问题:当 Agent 能写 100 万行代码,工程师在做什么?
不是失业。是转型。
从前,工程师的核心输出是代码本身。现在,工程师的核心输出是让 Agent 能持续写出高质量代码的环境——约束、文档、测试、验证循环、熵减机制。
这需要三种新技能:
6.1 约束工程:把架构规则翻译成 Linter,把接口契约翻译成测试,把设计原则翻译成 CI 门控。这是把软件工程的「应该这样做」变成「必须这样做」。
6.2 反馈循环设计:Agent 需要持续的信号判断自己走没走偏。设计这些信号,测试通过率、文档同步状态、性能基准——是工程师最核心的决策之一。反馈循环设计好了,Agent 能自我纠正;设计差了,Agent 会在错误方向上一路跑下去。
6.3 熵减系统设计:Agent 速度越快,技术债务积累越快。工程师需要设计持续的自动清理机制,而不是等债务堆到不可管理时才动手。
这三件事,是接下来最值钱的 AI 工程能力。不是「会写 Prompt」,而是「会设计让 Agent 系统长期健康运行的环境」。
OpenAI 用 100 万行代码验证了这件事是可行的。剩下的问题,只是你什么时候开始设计你自己的缰绳。

参考文献:
更多推荐



所有评论(0)