OpenAI 用 Codex 写到百万行代码后,真正遇到的 9 个工程问题
OpenAI 用 Codex 写到百万行代码后,真正遇到的 9 个工程问题
——从 Harness Engineering 看 AI 开发为什么不能只靠 Prompt
最近我在学习 OpenAI 的《Harness Engineering》。
一开始我以为这篇文章讲的会是:
- 怎么写 Prompt;
- 怎么让 Codex 一次写更多代码;
- 怎么选模型;
- 怎么让 Agent 更聪明。
但读完以后,我发现它真正讨论的其实是另一件事:
当 AI 已经很会写代码以后,怎样让它在一个越来越大的项目里长期、稳定、可控地工作。
OpenAI 在文章里介绍了一个内部实验:他们从一个空 Git 仓库开始,用 Codex 构建一个真实的软件产品。五个月后,仓库大约有一百万行代码,期间大约打开并合并了 1500 个 Pull Request。应用代码、测试、CI、文档、可观测性和内部工具都由 Codex 编写,人类主要负责方向、环境、意图和反馈机制。
真正值得学习的不是“一百万行代码”这个数字,而是:
代码量上去以后,他们连续遇到了一系列新的工程问题。
这些问题并不是换一个更强模型就会自动消失。
相反,他们需要不断改造整个开发环境。
我把这篇文章里的核心问题,加上整篇方法论最终形成的闭环,整理成 9 个问题。
问题一:Codex 明明会写代码,但项目就是推进得很慢
这是文章一开始就遇到的问题。
OpenAI 发现,早期进展比预期慢。
直觉上,我们可能会认为:
Codex能力不够
但他们发现真正的问题是:
环境不够明确
缺工具
缺抽象
缺内部结构
也就是说,模型可能完全有能力写出某个函数,却不知道:
应该从哪里开始?
应该改哪个模块?
项目里已有哪个能力可以复用?
完成以后该怎么验证?
一个简单例子
假设你告诉 AI:
给后台增加“删除用户”功能。
人类开发者可能会自然想到:
权限检查
↓
Service
↓
Repository
↓
Soft Delete
↓
Audit Log
↓
测试
但 Agent 不一定知道这些隐含信息。
它可能搜索到一个 UserTable.tsx,然后直接在 UI 里调用删除接口。
功能能跑。
但是整个项目结构可能已经被破坏。
OpenAI 怎么解决?
他们采用一种深度优先的方式,把大目标拆成更小的构建块:
设计
↓
代码
↓
Review
↓
测试
然后每次 Agent 推进不下去时,不再只说:
再试一次。
而是问:
到底还缺什么能力?
缺浏览器,就补浏览器。
缺内部工具,就补内部工具。
缺架构可读性,就补架构文档。
缺验证能力,就补测试和可观测性。
我认为这是整篇文章最重要的思维变化之一:
Agent 失败,不一定说明模型不够强,也可能说明环境没有给它足够的杠杆。
问题二:代码吞吐量提高以后,人工 QA 反而成了瓶颈
当 Codex 开始快速产出代码以后,新的问题出现了。
以前:
写代码
是慢的。
现在 AI 把写代码的速度提高以后:
验证代码
开始变慢。
比如每次修改 UI,人类都要:
启动应用
↓
打开页面
↓
点按钮
↓
复现 Bug
↓
检查修复
↓
查看日志
AI 一天能改很多东西。
但人的注意力是固定的。
于是:
人类 QA 成为了新的瓶颈。
OpenAI 怎么解决?
他们开始让应用本身对 Codex “可读”。
比如让 Agent 可以:
- 启动自己的应用实例;
- 使用 Chrome DevTools 相关能力;
- 获取 DOM 快照;
- 截图;
- 导航页面;
- 查询日志;
- 查询 Metrics;
- 查看 Trace。
于是流程变成:
Agent写代码
↓
Agent启动应用
↓
Agent复现问题
↓
Agent观察真实运行结果
↓
Agent修改
↓
Agent再次验证
这让我理解了一个很重要的区别。
错误做法:
Prompt:
“完成以后请仔细验证。”
更好的做法:
真的给Agent验证能力。
“提醒它验证”和“让它具备验证能力”不是同一回事。
问题三:AGENTS.md 越来越大,最后反而不好用了
项目做大以后,很自然会出现这种想法:
把所有规则都写进 AGENTS.md。
比如:
架构
编码规范
测试规范
安全规则
目录说明
工具说明
注意事项
历史经验
一开始可能很好用。
但随着项目增长:
100行
↓
500行
↓
2000行
↓
5000行
最后开始出现问题。
OpenAI 自己也试过“大型 AGENTS.md”,并明确说这是一次失败尝试。
主要有几个原因。
第一:Context 是有限资源
规则占得越多:
真正的任务
代码
相关文档
能占的空间就越少。
第二:所有东西都重要,就等于什么都不重要
如果文件里到处都是:
IMPORTANT
MUST
CRITICAL
Agent 反而不知道:
当前任务真正应该关注什么。
第三:文档会腐烂
项目已经变了。
旧规则还在。
新规则又不断加进去。
最后:
Agent无法判断哪条还是有效的。
第四:巨大文本很难机械检查
比如:
是否过期?
是否有Owner?
是否正确链接?
是否遗漏?
都很难自动检查。
OpenAI 怎么解决?
他们把:
AGENTS.md
从:
百科全书
改成:
地图
真正详细的知识放到结构化目录中,例如:
ARCHITECTURE.md
docs/design-docs/
docs/exec-plans/
docs/product-specs/
SECURITY.md
RELIABILITY.md
...
Agent 先看到一个小入口。
需要什么,再去读取什么。
这就是:
Progressive Disclosure,渐进式披露。
问题四:新的 Session 根本不知道以前发生过什么
如果你经常用 AI 开发,一定遇到过这个问题。
昨天你和 AI 讨论了两个小时。
终于确定:
以后这个模块只能这样调用。
今天开了一个新 Session。
新的 Agent:
完全不知道。
因为这些知识可能只存在于:
聊天记录
Slack
Google Docs
人的脑子
对于 Agent 来说:
它当前无法访问的信息,实际上就等于不存在。
OpenAI 怎么解决?
他们把 Repository 变成:
System of Record
真正重要的长期信息进入仓库:
代码
Markdown
Architecture
Design Docs
Execution Plans
Product Specs
Technical Debt
Schema
而且全部版本控制。
这样一个新的 Agent Session 进来以后:
不需要过去聊天历史
↓
读取Repository
↓
重新理解项目
这对 AI-first 开发非常重要。
因为未来很可能:
今天Codex
明天OpenCode
后天Claude Code
模型会换。
Session 会换。
但是:
Repository不能丢失项目记忆。
问题五:文档写得再好,Agent 还是会破坏架构
这是我认为整篇文章最关键的部分之一。
假设 ARCHITECTURE.md 里写:
UI不能直接调用Repo。
但 Agent 为了快速完成任务,还是写出了:
UI
↓
Repo
代码:
能编译
能运行
功能正常
这时候你不能再说:
AI不知道规则。
它可能知道。
真正的问题是:
系统允许它违反这个规则。
OpenAI 怎么解决?
他们建立严格的架构层级。
例如文章里的方向:
Types
↓
Config
↓
Repo
↓
Service
↓
Runtime
↓
UI
然后规定:
只能按照允许方向依赖。
再用:
Custom Linter
Structural Test
CI
机械执行。
于是:
文档:
“不要这样做。”
升级成:
这样做
↓
FAIL
这就是一个非常重要的升级:
Guideline
↓
Invariant
↓
Machine Enforcement
问题六:规则太多,又会把 Agent 束缚死
看到前面的内容以后,很容易走到另一个极端:
既然AI会乱写,
那我把所有事情全部规定死。
比如:
必须用这个库
必须用这种函数
必须建这个目录
必须写成这个模式
最后 Agent 可能变成一个非常笨的机械执行器。
OpenAI 没有这么做。
他们强调的是:
强制 Invariant,而不是微观管理 Implementation。
例如:
进入边界的数据必须验证
这是:
Invariant
但具体:
用Zod?
用自定义Parser?
用其他Schema工具?
可以让 Agent 自己决定。
我现在会把它理解成一句很简单的话:
WHAT
强约束
HOW
尽量给自由
也就是:
规定什么必须成立,不要过度规定具体怎么实现。
问题七:AI 写得太快,传统 Merge / Review 开始变成阻塞
传统软件开发流程通常是:
开发
↓
PR
↓
人工Review
↓
CI
↓
批准
↓
Merge
在人工开发速度下,这套流程很合理。
但是当 Agent 的代码吞吐量越来越高:
Agent一天能产生很多PR
人的注意力却没有增加。
于是:
Review队列
开始成为瓶颈。
OpenAI 怎么解决?
他们逐渐把大量 Review 变成:
Agent Review Agent
Codex 可以:
检查自己的修改
↓
请求其他Agent Review
↓
读取Review反馈
↓
继续修改
↓
处理Build失败
↓
重新验证
↓
推进PR
人类依然可以 Review。
但不再要求:
每一个PR都必须由人逐行检查。
人的角色逐渐变成:
决定目标
制定验收标准
处理异常
提供判断
注意,这不是:
人类不需要Review。
而是:
Review 的抽象层级发生了变化。
问题八:Agent 会复制代码库里的坏模式
Agent 有一个非常明显的特性:
它会模仿项目里已经存在的东西。
这是好事。
因为:
项目风格一致。
但也是坏事。
因为:
坏模式
也会被复制。
假设某一次为了赶进度写了:
一个临时helper
下一个 Agent:
看到这个模式
↓
继续复制
后来:
1个helper
↓
5个
↓
20个
技术债开始迅速扩散。
OpenAI 把这种现象称为:
Entropy
也就是代码库里的熵。
他们一开始怎么处理?
人类每周花时间清理所谓的:
AI slop
但很快发现:
不可扩展。
后来怎么解决?
他们建立:
Golden Principles
然后让后台 Codex 定期:
扫描偏差
↓
更新质量等级
↓
产生小型重构PR
↓
Review
↓
Merge
这更像:
Garbage Collection
不是:
几年后大重构一次。
而是:
不断偿还一点
不断偿还一点
不断偿还一点
不让坏模式积累成无法处理的大问题。
问题九:如果 Agent 每次失败都只修当前任务,同样的问题还会一直回来
这里我要特别说明:
这一条不是 OpenAI 原文单独列出的第九个章节标题,而是我从整篇文章的方法论中提炼出来的闭环。
文章里其实反复出现同一个模式:
Agent遇到困难
↓
人类判断缺了什么
↓
补工具 / 指导 / 约束 / 文档
↓
把它反馈到Repository
↓
以后Agent拥有新的能力
所以我认为整篇文章真正值得普通 AI 开发者学习的一条原则是:
不要只修 Agent 当前犯下的错误,还要研究为什么系统允许它犯这个错误。
例如:
Agent忘记验证UI
一次性处理:
提醒它“记得验证”。
Harness 处理:
给它浏览器和E2E。
再例如:
Agent绕过Scope。
一次性处理:
Prompt里加一句“不要越权”。
Harness 处理:
Runtime强制ScopeGuard。
再例如:
Agent又写了一套重复Graph流程。
一次性处理:
删掉重复代码。
Harness 处理:
Architecture Rule
+
Dependency Test
这个过程可以概括成:
Failure
↓
Root Cause
↓
Recurring?
↓
Harness Gap
↓
Docs / Tool / State / Guard / Test / CI
↓
Machine Verification
这其实把前面的 8 个问题全部串了起来。
这 9 个问题背后其实只有一条演化路线
把整个过程连起来以后,可以看到一个很有意思的模式:
Agent推进慢
↓
补工具和结构
Agent写快了
↓
人工QA跟不上
让Agent自己验证
↓
Context开始变复杂
巨大AGENTS.md失败
↓
Repository成为知识系统
知识有了
↓
Agent还是违反架构
架构规则机器化
↓
规则越来越多
只强制Invariant
↓
吞吐量继续上升
传统Review跟不上
↓
Agent Review Agent
代码越来越多
↓
Agent复制坏模式
持续Garbage Collection
↓
Agent仍然会暴露新问题
Failure → Harness
这让我意识到:
Harness Engineering 并不是第一天就设计出一套完美系统。
而是不断:
遇到真实问题
↓
分析根因
↓
把解决方案编码进环境
↓
获得更高自主性
↓
暴露新的瓶颈
↓
继续改Harness
对普通 AI 开发者来说,最应该学什么?
不是照抄 OpenAI 的:
目录结构
具体技术栈
具体Lint规则
因为你的项目和他们完全不同。
真正应该学的是他们的工作方式。
以后 AI 再做错时,不要只问:
这一次怎么修?
多问三句:
为什么会发生?
以后还会不会再发生?
如果会,
怎么让系统自动发现或阻止?
如果答案是:
以后很可能还会发生
那么这可能就不是一个普通 Bug。
它可能是:
Harness Gap
最终的解决方案可能不是 Prompt。
而是:
Documentation
Tool
State
Runtime
Guard
Test
E2E
Lint
CI
Observability
这就是我现在理解 Harness Engineering 最有价值的地方:
把 Agent 的失败,变成下一轮工程环境升级的输入。
参考资料
OpenAI,《工程技术:在智能体优先的世界中利用 Codex》
https://openai.com/zh-Hans-CN/index/harness-engineering/
注:本文按照初学者学习视角重新组织 OpenAI 原文。前 8 个问题对应原文明确讨论的工程问题;第 9 个“Failure → Harness”是作者基于原文多处方法论总结出的实践闭环,并非 OpenAI 原文单独列出的第九个问题标题。

浙公网安备 33010602011771号