驾驭工程:在「智能体优先」的世界里借力 Codex
Ryan Lopopolo
过去五个月,我们团队开展了一项实验:构建并发布一款软件产品的内部 Beta 版,其中 0 行代码由人工编写。
这款产品既有内部日活用户,也有外部 Alpha 测试者。它照常发布、部署,会崩溃,也能修复。 唯一不同的是,每一行代码——从应用逻辑、测试、CI 配置,到文档、可观测性监控和内部工具——皆由 Codex 编写。据估算,我们完成这一切的时间,仅为纯手工编码的十分之一。
人类掌舵,智能体执行。
我们刻意选择这一限制,旨在倒逼自己构建必要的体系,将工程速度提升数个量级。要在几周内交付最终达百万行代码的系统,我们需要搞清楚:当软件工程团队的主要工作不再是写代码,而是设计环境、明确意图、建立反馈循环,以便让 Codex 智能体 (Agents) 可靠地工作时,一切会发生什么变化。
本文记录了我们依靠智能体团队构建全新产品的经验教训——什么崩溃了,什么产生了复利,以及如何最大化利用唯一真正稀缺的资源:人类的时间和注意力。
我们从一个空的 Git 仓库开始
2025 年 8 月下旬,空仓库迎来了第一次提交。
最初的脚手架——包括仓库结构、CI 配置、格式化规则、包管理器设置和应用框架——均由 Codex CLI 在 GPT-5 的驱动下,依据少量现有模板生成。甚至连指导智能体如何在仓库中工作的初始 AGENTS.md 文件,也是 Codex 写的。
系统没有任何预存的人类代码作为锚点。从一开始,这个仓库就是由智能体塑造的。
五个月后,仓库已积累约一百万行代码,涵盖应用逻辑、基础设施、工具链、文档和内部开发实用程序。期间,仅三名工程师驱动 Codex,就处理并合并了约 1,500 个 PR(Pull Requests)。折算下来,每位工程师每天平均处理 3.5 个 PR。令人惊讶的是,随着团队扩至七人,吞吐量反而提升了。重要的是,这并非为了刷数据:数百名内部用户正在使用该产品,其中不乏每天重度使用的核心用户。
整个开发过程中,人类从未直接贡献过任何代码。这成了团队的核心信条:绝不手动写代码。
重新定义工程师的角色
不再亲手写代码,催生了一种侧重于系统、脚手架和杠杆效应的新型工程工作。
早期进展比预期慢。并非 Codex 能力不足,而是环境定义不够具体。智能体缺乏推进高层目标所需的工具、抽象层和内部结构。工程团队的首要任务变成了“赋能智能体”,让它们开展有价值的工作。
具体来说,我们要采取“深度优先”的策略:将大目标拆解为更小的积木(设计、编码、评审、测试等),通过提示词 (Prompting) 引导智能体构建这些积木,再利用它们解锁更复杂的任务。当任务失败时,修复办法绝不是“再试一次”。既然推进工作的唯一途径是让 Codex 动手,人类工程师总要介入并反问:“缺少什么能力?如何让这种能力对智能体既可读又可执行?”
人类几乎完全通过提示词与系统交互:工程师描述任务,运行智能体,让它提交 PR。为了完成 PR,我们指示 Codex 在本地评审自己的变更,请求特定的云端或本地智能体复审,响应人类或智能体的反馈,并循环迭代直到所有智能体评审员都满意(本质上就是个 Ralph Wiggum 循环)。Codex 直接使用我们的标准开发工具(gh、本地脚本和仓库内置技能)获取上下文,无需人类在 CLI 中复制粘贴。
人类可以评审 PR,但非必须。随着时间推移,我们将绝大部分评审工作都推给了“智能体对智能体”的互评模式。
提升应用的“可读性”
随着代码吞吐量提升,瓶颈变成了人类 QA(质量保证)的精力。既然限制因素是人类的时间和注意力,我们就致力于增强智能体对系统的感知能力,让应用程序的 UI、日志和指标能被 Codex 直接“读懂”。
例如,我们让应用支持在每个 Git Worktree 中独立启动,这样 Codex 就能为每次变更启动并驱动一个实例。我们还将 Chrome DevTools 协议接入智能体运行时,并创建了处理 DOM 快照、截图和导航的技能。这使得 Codex 能够重现 Bug、验证修复并直接推理 UI 行为。

在可观测性工具上也如法炮制。日志、指标和链路追踪都通过一个本地的可观测性栈暴露给 Codex,该栈对每个 Worktree 都是临时的。Codex 在一个完全隔离的应用版本上工作——任务完成后,相关的日志和指标也会随之销毁。智能体可以用 LogQL 查询日志,用 PromQL 查询指标。有了这些上下文,像“确保服务启动时间低于 800ms”或“这四个关键用户路径中的链路跨度不超过 2 秒”这样的提示词就变得易于处理 (Tractable) 了。

我们经常看到单次 Codex 运行持续处理一个任务长达六个多小时(通常是在人类睡觉的时候)。
将仓库知识打造为“单一事实来源”
上下文工程 (Context Engineering) 是让智能体有效处理庞大复杂任务的最大挑战之一。我们最早学到的一个简单教训是:给 Codex 一张地图,而不是一本 1000 页的说明书。
- 上下文资源稀缺。 巨大的说明文件会挤占任务描述、代码和相关文档的空间——导致智能体要么忽略关键约束,要么优化了错误的目标。
- 过多的指导等于没有指导。 当一切都“重要”时,就没什么是重要的了。智能体最终会陷入局部模式匹配,而不是有意识地进行全局导航。
- 文档即刻腐烂。 单体式的说明书会变成过时规则的坟场。智能体分不清什么是对的,人类不再维护,文件就变成了一个诱人的麻烦。
- 难以验证。 一个巨大的文本块难以进行机械化检查(如覆盖率、新鲜度、所有权、交叉链接),因此偏离现实在所难免。
因此,我们不把 AGENTS.md 当作百科全书,而是把它当作目录。
仓库的知识库主要存在于结构化的 docs/ 目录中,这里被视为“单一事实来源”。注入上下文的 AGENTS.md 很短(约 100 行),主要作为一张地图,指向其他更深层的真相。
AGENTS.md
ARCHITECTURE.md
docs/
├── design-docs/
│ ├── index.md
│ ├── core-beliefs.md
│ └── ...
├── exec-plans/
│ ├── active/
│ ├── completed/
│ └── tech-debt-tracker.md
├── generated/
│ └── db-schema.md
├── product-specs/
│ ├── index.md
│ ├── new-user-onboarding.md
│ └── ...
├── references/
│ ├── design-system-reference-llms.txt
│ ├── nixpacks-llms.txt
│ ├── uv-llms.txt
│ └── ...
├── DESIGN.md
├── FRONTEND.md
├── PLANS.md
├── PRODUCT_SENSE.md
├── QUALITY_SCORE.md
├── RELIABILITY.md
└── SECURITY.md
仓库内知识库的目录结构
设计文档会被编目和索引,包含验证状态和定义“智能体优先”操作原则的核心信念。架构文档 提供了领域和包分层的顶层地图。质量文档则对每个产品领域和架构层级进行评分,并追踪随时间推移的差距。
“计划”被视为一等公民。临时的轻量级计划用于小变更,而复杂工作则记录在 执行计划 (Execution Plans) 中,包含进度和决策日志,并签入仓库。活跃计划、已完成计划和已知的技术债务都被版本化并放在一起,让智能体无需依赖外部上下文即可操作。
这实现了渐进式披露:智能体从一个小的、稳定的入口点开始,被教导下一步去哪里看,而不是一开始就被信息淹没。
我们通过机械化手段强制执行这一点。专用的 Linter 和 CI 任务会验证知识库是否最新、交叉链接是否正确、结构是否合规。还有一个定期的“文档园丁”智能体,负责扫描那些不能反映真实代码行为的过时文档,并提交修复 PR。
目标:让智能体“读懂”
随着代码库的演进,Codex 的设计决策框架也必须随之进化。
由于仓库完全由智能体生成,它首先是为 Codex 的可读性 优化的。就像团队为了新入职工程师能看懂代码而优化一样,我们人类工程师的目标是让智能体能够直接从仓库本身推导整个业务领域的逻辑。
在智能体看来,凡是无法在运行时从上下文中获取的信息,实际上都不存在。存储在 Google Docs、聊天记录或人们脑子里的知识,系统是访问不到的。它只能看到仓库本地的、版本化的工件(如代码、Markdown、Schema、可执行计划)。

我们意识到,必须随着时间推移将越来越多的上下文推入仓库。比如团队在 Slack 上对某个架构模式达成的共识,如果不让智能体可发现,那就像新员工入职三个月后还不知道这件事一样无效。
给 Codex 更多上下文,意味着组织并暴露正确的信息,让智能体能够基于此进行推理,而不是用临时的指令淹没它。就像你向新队友介绍产品原则、工程规范和团队文化(甚至包括表情符号的偏好)一样,给智能体提供这些信息能带来更一致的产出。
这种框架澄清了许多权衡。我们更倾向于那些可以在仓库内完全内化和推理的依赖项和抽象。那些常被称为“枯燥”的技术,往往因为可组合性强、API 稳定且在训练集中出现频率高,而更容易被智能体建模。某些情况下,让智能体重新实现部分功能,比绕过公共库中不透明的上游行为成本更低。例如,我们没有引入通用的 p-limit 类包,而是实现了自己的带并发控制的 map 辅助函数:它与我们的 OpenTelemetry 仪表盘紧密集成,拥有 100% 的测试覆盖率,并且行为完全符合我们运行时的预期。
将更多系统部分转化为智能体可以直接检查、验证和修改的形式,不仅增加了 Codex 的杠杆作用,也惠及了其他在代码库上工作的智能体(例如 Aardvark)。
强制架构与“品味”
光靠文档无法保持一个完全由智能体生成的代码库的连贯性。通过强制执行不变性 (Invariants),而不是微观管理实现细节,我们让智能体在不破坏地基的前提下快速交付。 例如,我们要求 Codex 在边界解析数据形状,但不规定具体怎么做(模型似乎喜欢 Zod,但我们并没有指定这个库)。
在拥有严格边界和可预测结构的环境中,智能体最为高效。因此,我们围绕严格的架构模型构建应用。每个业务领域被划分为固定的层级,具有严格验证的依赖方向和有限的允许边缘。这些约束通过自定义 Linter(当然也是 Codex 生成的!)和结构测试进行机械化强制。
下图展示了这一规则:在每个业务领域(如应用设置)内,代码只能“向前”依赖于一组固定的层(Types → Config → Repo → Service → Runtime → UI)。横切关注点(认证、连接器、遥测、功能标志)通过唯一的显式接口进入:Providers。其他任何依赖都被禁止,并由机器强制执行。

这种架构通常要等到你有数百名工程师时才会实施。但对于编码智能体来说,这是早期的先决条件:正是这些约束使得我们在保持速度的同时,避免了腐化或架构漂移。
实际上,我们通过自定义 Linter 和结构测试,加上少量“品味不变性”来执行这些规则。例如,我们静态强制执行结构化日志记录、Schema 和类型的命名约定、文件大小限制以及特定平台的可靠性要求。由于 Linter 是自定义的,我们编写报错信息时会直接将修复指令注入到智能体的上下文中。
在以人类为主的工作流中,这些规则可能显得迂腐或受限。但对智能体而言,它们变成了倍增器:一旦编码,它们就同时适用于所有地方。
同时,我们明确区分哪里约束重要,哪里不重要。这很像领导一个大型工程平台组织:在中央强制边界,在地方允许自治。你深切关注边界、正确性和可复现性;在这些边界内,你允许团队——或智能体——在解决方案的表达方式上有很大的自由度。
生成的代码并不总是符合人类的风格偏好,但这没关系。只要产出是正确的、可维护的,并且对未来的智能体运行是“清晰可见”的,它就达标了。
人类的“品味”会被持续反馈回系统。评审评论、重构 PR 和面向用户的 Bug 会被捕捉为文档更新或直接编码进工具中。当文档不足以规范行为时,我们就把规则升级为代码。
吞吐量改变了合并哲学
随着 Codex 吞吐量的增加,许多传统的工程规范变得适得其反。
仓库运作时尽量减少阻塞性的合并门槛。PR 存活时间很短。测试的不稳定 (Flakes) 通常通过后续运行来解决,而不是无限期阻碍进度。在一个智能体吞吐量远超人类注意力的系统中,修正很廉价,等待却昂贵。
在低吞吐量环境中,这种做法是不负责任的。但在这里,这通常是正确的权衡。
“智能体生成”到底意味着什么
当我们说代码库是由 Codex 智能体生成时,我们指的是代码库里的一切。
智能体产出:
- 产品代码和测试
- CI 配置和发布工具
- 内部开发者工具
- 文档和设计历史
- 评估工具 (Evaluation harnesses)
- 评审评论和回复
- 管理仓库本身的脚本
- 生产环境仪表盘定义文件
人类始终在环,但我们在比过去更高的抽象层面上工作。我们负责确定优先级,将用户反馈转化为验收标准,并验证结果。当智能体挣扎时,我们将其视为信号:识别缺少了什么——工具、护栏、文档——并将这些反馈回仓库,当然,修复工作依然由 Codex 自己编写。
智能体直接使用我们的标准开发工具。它们拉取评审反馈,在行内回复,推送更新,并经常自行压缩合并 (Squash and merge) 自己的 PR。
不断提升的自主权等级
随着越来越多的开发循环(测试、验证、评审、反馈处理和恢复)被直接编码进系统,仓库最近跨越了一个有意义的门槛:Codex 可以端到端地驱动一个新功能。
给定一个提示词,智能体现在可以:
- 验证代码库的当前状态
- 重现报告的 Bug
- 录制演示故障的视频
- 实施修复
- 通过驱动应用程序验证修复
- 录制演示修复效果的第二个视频
- 开启 PR
- 响应智能体和人类的反馈
- 检测并修复构建失败
- 仅在需要判断力时升级给人类
- 合并变更
这种行为严重依赖于该仓库特定的结构和工具,目前还不能假设无需类似投入就能在其他地方复用。
熵与垃圾回收
完全的智能体自主性也引入了新问题。 Codex 会复制仓库中已有的模式——即使是那些不均匀或次优的模式。随着时间推移,这必然导致漂移。
最初,人类手动处理这个问题。我们团队过去每周五(即每周 20% 的时间)都要清理“AI 垃圾代码 (AI slop)”。不出所料,这无法扩展。
取而代之的是,我们开始将所谓的“黄金原则”直接编码进仓库,并建立了一个循环清理流程。这些原则是独断的、机械的规则,旨在保持代码库对未来智能体运行的清晰和一致。例如:(1) 我们更倾向于共享的工具包,而不是随手写的辅助函数,以保持不变性的集中;(2) 我们不以“YOLO 风格”试探数据——我们要么验证边界,要么依赖类型化的 SDK,这样智能体就不会基于猜测的形状意外构建代码。按照固定的节奏,我们有一组后台 Codex 任务扫描偏差,更新质量评分,并开启针对性的重构 PR。大多数 PR 可以在一分钟内完成评审并自动合并。
这就像垃圾回收机制。技术债务就像高利贷:持续小额偿还总是比让它利滚利然后痛苦地一次性解决要好。人类的品味被捕捉一次,然后在每一行代码上持续强制执行。这也让我们能按日发现并解决不良模式,而不是让它们在代码库中蔓延数天或数周。
我们仍在学习的东西
这一策略在 OpenAI 内部发布和采用阶段效果良好。为真实用户构建真实产品,帮助我们将投资锚定在现实中,并引导我们走向长期的可维护性。
我们尚不知道的是,在一个完全由智能体生成的系统中,架构的一致性在数年内会如何演变。我们仍在学习人类判断力在何处能增加最大杠杆,以及如何编码这种判断力使其产生复利。我们也不知道随着模型能力随时间不断增强,这个系统将如何进化。
目前已明确的是:构建软件依然需要纪律,但这种纪律更多地体现在“脚手架”而非代码本身。保持代码库连贯性的工具、抽象和反馈循环变得日益重要。
我们现在最艰巨的挑战集中在设计环境、反馈循环和控制系统上,以帮助智能体实现我们的目标:大规模构建和维护复杂、可靠的软件。
随着像 Codex 这样的智能体承担起软件生命周期中更大的部分,这些问题将变得愈发重要。我们希望分享的这些早期经验能帮助你思考应该在何处投入精力,以便你只管去创造 (just build things)。