2026年2月11日 工程 驾驭工程:在 Agent 优先的世界中利用 Codex 作者:Ryan Lopopolo,技术人员
在过去的五个月里,我们的团队一直在进行一项实验:构建并发布一个 0 行手动编写代码的软件产品内部测试版。
该产品拥有内部日活用户和外部 Alpha 测试者。它发布、部署、崩溃并得到修复。不同之处在于,每一行代码——应用逻辑、测试、CI 配置、文档、可观测性以及内部工具——都是由 Codex 编写的。我们估计,构建这个产品所花费的时间仅为手动编写代码的 1/10 左右。
人类掌舵。Agent 执行。
我们有意选择了这一限制,以便构建出能够将工程效率提升几个数量级的必要条件。我们只有几周的时间来发布最终达百万行规模的代码。为此,我们需要理解:当软件工程团队的主要工作不再是编写代码,而是设计环境、指定意图并构建反馈循环(让 Codex Agent 能够可靠地工作)时,一切会发生怎样的变化。
这篇文章记录了我们通过 Agent 团队构建全新产品的所思所得——哪些地方出了问题,哪些地方产生了复利,以及如何最大化我们唯一真正稀缺的资源:人类的时间和注意力。
我们从一个空的 Git 仓库开始
2025 年 8 月底,空仓库迎来了第一次提交。
初始脚手架——包括仓库结构、CI 配置、格式化规则、包管理器设置和应用框架——是由 Codex CLI 使用 GPT-5 在一小组现有模板的指导下生成的。甚至引导 Agent 如何在仓库中工作的初始 AGENTS.md 文件本身也是由 Codex 编写的。
系统中没有任何预先存在的人类编写的代码。从一开始,仓库就是由 Agent 塑造的。
五个月后,该仓库包含了应用逻辑、基础设施、工具、文档和内部开发实用程序,代码量约为百万行。在此期间,一个仅由三名工程师组成的团队驱动 Codex 打开并合并了大约 1,500 个拉取请求(PR)。这相当于每位工程师每天平均产出 3.5 个 PR,令人惊讶的是,随着团队扩大到现在的七名工程师,吞吐量还在继续增加。重要的是,这并非为了产出而产出:该产品已被数百名内部用户使用,包括每日使用的内部核心用户。
在整个开发过程中,人类从未直接贡献过任何代码。这成了团队的核心哲学:绝不手动编写代码。
重新定义工程师的角色
由于缺乏亲自动手的人类编码,工程工作转向了另一种模式,重点在于系统、脚手架和杠杆作用。
早期的进展比我们预想的要慢,不是因为 Codex 能力不足,而是因为环境规格说明不足。Agent 缺乏实现高层目标所需的工具、抽象和内部结构。我们工程团队的首要任务变成了赋能 Agent 去做有用的工作。
在实践中,这意味着采用深度优先的工作方式:将大目标分解为较小的构建块(设计、代码、评审、测试等),提示 Agent 构建这些块,并利用它们解锁更复杂的任务。当某些环节失败时,修复方法几乎从来不是“再努力一点”。因为取得进展的唯一方法是让 Codex 完成工作,所以人类工程师总是会介入任务并询问:“缺失了什么能力?我们如何让它对 Agent 既清晰可见又可强制执行?”
人类几乎完全通过提示词(Prompt)与系统交互:工程师描述任务,运行 Agent,并允许其开启一个拉取请求。为了推动 PR 完成,我们指示 Codex 在本地检查自己的更改,请求本地和云端的其他特定 Agent 进行评审,回应人类或 Agent 给出的任何反馈,并在循环中迭代,直到所有 Agent 评审员都满意为止(实际上这就是一个 Ralph Wiggum 循环)。Codex 直接使用我们的标准开发工具(gh、本地脚本和仓库嵌入式技能)来获取上下文,无需人类手动复制粘贴到 CLI 中。
人类可以评审拉取请求,但并非必须。随着时间的推移,我们已经将几乎所有的评审工作都交给了 Agent 对 Agent 的处理模式。
提升应用的可读性
随着代码吞吐量的增加,我们的瓶颈变成了人类的 QA 能力。由于固定约束一直是人类的时间和注意力,我们努力通过让应用 UI、日志和应用指标本身能被 Codex 直接“读懂”,来为 Agent 增加更多能力。
例如,我们使应用可以根据每个 git 工作树(worktree)启动,这样 Codex 就可以针对每次更改启动并驱动一个实例。我们还将 Chrome DevTools 协议接入了 Agent 运行时,并创建了处理 DOM 快照、截图和导航的技能。这使得 Codex 能够复现 bug、验证修复方案并直接推理 UI 行为。
对于可观测性工具,我们也做了同样的处理。日志、指标和追踪通过一个针对特定工作树的临时本地可观测性栈暴露给 Codex。Codex 在一个完全隔离的应用版本上工作——包括其日志和指标,这些内容在任务完成后会被销毁。Agent 可以使用 LogQL 查询日志,使用 PromQL 查询指标。有了这些上下文,诸如“确保服务启动在 800ms 内完成”或“这四个关键用户路径中不得有超过两秒的 Span”之类的提示词就变得可行了。
我们经常看到单个 Codex 运行单项任务的时间超过六个小时(通常是在人类睡觉的时候)。
我们将仓库知识作为权威数据源
上下文管理是使 Agent 在处理大型复杂任务时发挥效用的最大挑战之一。我们学到的最早教训之一非常简单:给 Codex 一张地图,而不是一本 1000 页的说明手册。
我们尝试过“一个大的 AGENTS.md”方法,但它以预料之中的方式失败了:
- 上下文是稀缺资源:巨大的指令文件会挤占任务代码和相关文档的空间——导致 Agent 要么错过关键约束,要么开始针对错误的约束进行优化。
- 过多的指导等同于没有指导:当一切都是“重要”的时,就没有什么是重要的。Agent 最终会进行局部的模式匹配,而不是有意识地导航。
- 内容会迅速过时:单体手册会变成陈旧规则的坟墓。Agent 无法判断哪些仍然有效,人类停止维护它,该文件悄然变成了“诱人的麻烦”。
- 难以验证:单一的大块文件不便于进行机械检查(覆盖率、新鲜度、归属权、交叉链接),因此偏差不可避免。
所以,我们没有把 AGENTS.md 当作百科全书,而是把它当作目录。
仓库的知识库存储在结构化的 docs/ 目录中,被视为权威数据源(system of record)。一个简短的 AGENTS.md(约 100 行)被注入到上下文中,主要充当地图,指向其他地方更深层的真相来源。
(仓库内知识存储布局)
设计文档被编目和索引,包括验证状态和一套定义 Agent 优先操作原则的核心理念。架构文档提供了领域和包分层的顶层地图。质量文档对每个产品领域和架构层进行评分,追踪随时间推移产生的差距。
计划被视为一等公民产物。临时的轻量级计划用于微小更改,而复杂的工作则记录在包含进度和决策日志的执行计划中,并提交到仓库。活动计划、已完成计划和已知的技术债都进行版本化并共处一地,允许 Agent 在不依赖外部上下文的情况下运行。
这实现了“渐进式披露”:Agent 从一个微小、稳定的入口点开始,并被告知下一步该看哪里,而不是预先被海量信息淹没。
我们通过机械手段强制执行这一点。专门的 Linter 和 CI 任务会验证知识库是否最新、是否建立了交叉链接以及结构是否正确。一个定期运行的“文档园艺”Agent 会扫描那些不能反映真实代码行为的陈旧或废弃文档,并打开修复拉取请求。
目标是 Agent 的可读性
随着代码库的演进,Codex 进行设计决策的框架也需要随之演进。
由于仓库完全由 Agent 生成,它首先针对 Codex 的可读性进行了优化。就像团队致力于为新入职的工程师提高代码的可导航性一样,我们人类工程师的目标是让 Agent 能够直接从仓库本身推理出完整的业务领域。
从 Agent 的角度来看,任何它在运行时无法访问的上下文实际上都不存在。存在于 Google Docs、聊天记录或人们大脑中的知识是系统无法触及的。它能看到的只有仓库本地的、版本化的产物(例如代码、Markdown、Schema、可执行计划)。
我们发现,随着时间的推移,我们需要将越来越多的上下文推送到仓库中。那次让团队在架构模式上达成一致的 Slack 讨论?如果它对 Agent 不可见,那么它就是不可读的,就像三个月后入职的新员工不知道它一样。
给 Codex 更多上下文意味着组织和暴露正确的信息,以便 Agent 对其进行推理,而不是用临时指令淹没它。就像你会向新队友介绍产品原则、工程规范和团队文化(包括对 Emoji 的偏好)一样,给 Agent 这些信息会带来一致性更好的产出。
这种框架清晰化了许多权衡。我们偏好那些可以在仓库内完全内化和推理的依赖项和抽象。通常被称为“无聊”的技术往往更容易被 Agent 建模,因为它们具有组合性、API 稳定性以及在训练集中的高表达。在某些情况下,让 Agent 重新实现部分功能比绕过公共库中不透明的上游行为成本更低。例如,我们没有引入通用的 p-limit 风格的包,而是实现了我们自己的并发映射助手:它与我们的 OpenTelemetry 仪表紧密集成,拥有 100% 的测试覆盖率,并且行为完全符合我们运行时的预期。
将系统的更多部分转化为 Agent 可以直接检查、验证和修改的形式,不仅增加了 Codex 的杠杆作用,也增加了同样在该代码库上工作的其他 Agent(例如 Aardvark)的杠杆作用。
强制执行架构和审美
单靠文档无法保持全 Agent 生成的代码库的一致性。通过强制执行不变量(Invariant)而不是微观管理实现细节,我们让 Agent 在不破坏基础的前提下快速发布。例如,我们要求 Codex 在边界处解析数据形状,但不规定如何实现(模型似乎喜欢 Zod,但我们并没有指定这个特定的库)。
Agent 在具有严格边界和可预测结构的物理环境中最高效,因此我们围绕僵化的架构模型构建了应用。每个业务领域都被划分为一组固定的层,具有严格验证的依赖方向和有限的允许边缘。这些约束通过自定义 Linter(当然也是 Codex 生成的!)和结构测试进行机械式强制执行。
这种架构通常是你拥有数百名工程师时才会推迟进行的。对于编码 Agent 来说,这是早期先决条件:约束条件是允许速度而不会导致腐烂或架构漂移的关键。
在实践中,我们使用自定义 Linter、结构测试以及一小部分“审美不变量”来执行这些规则。例如,我们静态地强制执行结构化日志、Schema 和类型的命名约定、文件大小限制,以及通过自定义 Lint 强制执行平台特定的可靠性要求。由于 Lint 是自定义的,我们可以编写错误消息,将修复指令直接注入到 Agent 的上下文中。
在人类优先的工作流中,这些规则可能显得琐碎或具有约束性。对于 Agent 来说,它们变成了乘法器:一旦编码,它们就会立即应用到所有地方。
同时,我们明确哪些地方约束很重要,哪些地方不重要。这类似于领导一个大型工程平台组织:集中强制执行边界,局部允许自主。你深切关注边界、正确性和可复现性。在这些边界之内,你允许团队——或 Agent——在解决方案的表现形式上拥有极大的自由。
生成的代码并不总是符合人类的审美偏好,这没关系。只要产出是正确的、可维护的,并且对未来的 Agent 运行具有可读性,它就达到了标准。
人类的审美会持续反馈到系统中。评审评论、重构拉取请求和用户反馈的 bug 会被捕获为文档更新,或直接编码到工具中。当文档不足以约束时,我们就将规则提升为代码。
吞吐量改变了合并哲学
随着 Codex 吞吐量的增加,许多传统的工程规范变得适得其反。
仓库运行时的阻塞合并门槛降到了最低。拉取请求的生命周期很短。测试抖动(Flake)通常通过后续运行来解决,而不是无限期地阻塞进度。在一个 Agent 吞吐量远超人类注意力的系统中,纠错成本很低,而等待成本很高。
在低吞吐量环境中,这样做是不负责任的。但在这种环境下,这通常是正确的权衡。
“Agent 生成”的真正含义
当我们说代码库是由 Codex Agent 生成时,指的是代码库中的一切。
Agent 产出:
- 产品代码和测试
- CI 配置和发布工具
- 内部开发工具
- 文档和设计历史
- 评估框架
- 评审评论和回复
- 管理仓库本身的脚本
- 生产环境仪表盘定义文件
人类始终处于循环中,但工作在与以往不同的抽象层。我们划分工作的优先级,将用户反馈转化为验收标准,并验证结果。当 Agent 遇到困难时,我们将其视为一种信号:识别缺失了什么——工具、护栏、文档——并将之反馈回仓库,而且始终是通过让 Codex 自己编写修复方案来完成。
Agent 直接使用我们的标准开发工具。它们拉取评审反馈、内联回复、推送更新,并且经常自行压缩并合并(squash and merge)自己的拉取请求。
提升自治水平
随着越来越多的开发闭环被直接编码到系统中——测试、验证、评审、反馈处理和恢复——仓库最近跨越了一个有意义的阈值:Codex 可以端到端地驱动一个新功能的开发。
给定一个提示词,Agent 现在可以:
- 验证代码库的当前状态
- 复现报告的 bug
- 录制演示失败的视频
- 实现修复方案
- 通过驱动应用来验证修复
- 录制第二个演示解决后的视频
- 开启拉取请求
- 回应 Agent 和人类的反馈
- 检测并修复构建失败
- 仅在需要判断力时上报给人类
- 合并更改
这种行为严重依赖于该仓库特定的结构和工具,不应假设在没有类似投入的情况下可以泛化——至少现在还不行。
熵与垃圾回收
完全的 Agent 自治也引入了新问题。Codex 会复制仓库中已有的模式——即使是不平衡或次优的模式。随着时间的推移,这必然导致偏差。
最初,人类手动处理这个问题。我们的团队以前每周五(周工作时间的 20%)都在清理“AI 垃圾(slop)”。不出所料,这无法规模化。
相反,我们开始将所谓的“黄金原则”直接编码到仓库中,并构建了定期清理流程。这些原则是固执己见的、机械的规则,旨在保持代码库对未来 Agent 运行的可读性和一致性。例如:(1) 我们偏好共享的实用工具包而不是手写的助手函数,以保持不变量集中;(2) 我们不进行“YOLO 式”的数据探测——我们会验证边界或依赖类型化的 SDK,这样 Agent 就不会意外地构建在猜测的数据形状上。我们有一组后台 Codex 任务定期运行,扫描偏差、更新质量等级并开启针对性的重构拉取请求。其中大多数可以在一分钟内评审完毕并自动合并。
这起到了类似垃圾回收的作用。技术债就像高利贷:连续进行小额偿还,几乎总是比让它复利堆积然后进行痛苦的突击清理要好。人类的审美被捕获一次,然后持续强制执行到每一行代码中。这还让我们能够每天捕捉并解决坏模式,而不是让它们在代码库中扩散数天或数周。
我们仍在探索
到目前为止,这种策略在 OpenAI 的内部发布和采用过程中表现良好。构建面向真实用户的真实产品有助于将我们的投入锚定在现实中,并引导我们走向长期可维护性。
我们尚不清楚在一个完全由 Agent 生成的系统中,架构连贯性在数年内会如何演进。我们仍在学习人类判断在何处能产生最大的杠杆作用,以及如何对这种判断进行编码以产生复利。我们也不知道随着模型能力持续增强,这个系统会如何演化。
已经明确的是:构建软件仍然需要纪律,但这种纪律更多地体现在脚手架上,而非代码本身。保持代码库连贯性的工具、抽象和反馈循环变得越来越重要。
我们现在最艰巨的挑战集中在设计环境、反馈循环和控制系统上,以帮助 Agent 实现我们的目标:规模化地构建和维护复杂、可靠的软件。
随着像 Codex 这样的 Agent 承担起软件生命周期的更大份额,这些问题将变得更加重要。我们希望分享这些早期教训能帮助你思考应该在何处投入精力,从而让你能够单纯地去“构建”。