摘要

1) 一句话摘要 OpenAI 团队通过一项为期五个月的实验,在人类零手动编写代码的约束下,完全依靠 Codex 智能体构建并发布了一款包含百万行代码的软件产品,证明了未来工程的重心将从编写代码转向系统设计、上下文管理与反馈循环构建。

2) 核心要点

  • 零手动编码与高效率:3名(后增至7名)工程师在5个月内通过 Codex 生成了约 100 万行代码,合并了约 1,500 个 PR(每人每天 3.5 个),开发时间预估仅为人工编写的 1/10。
  • 工程角色重定义:人类负责“掌舵”(设计环境、明确意图、提供提示词),智能体负责“执行”(产出产品代码、测试、CI 配置、文档、内部工具等所有内容)。
  • 赋予智能体可观测性:将 Chrome DevTools 协议及本地临时可观测性技术栈(LogQL、PromQL)接入智能体运行时,使 Codex 能直接读取 UI、日志和指标,自主复现错误并验证修复,单次任务运行可长达 6 小时。
  • 上下文管理(渐进式披露):废弃了庞大的单一指令文件,将结构化的 docs/ 目录作为记录系统,仅保留约 100 行的 AGENTS.md 作为指向深层事实来源的“地图”。
  • 面向智能体的可读性:代码库优先针对 Codex 的可读性进行优化;所有隐性知识(如聊天记录、文档)必须转化为仓库内受版本控制的产物,并倾向使用易于智能体建模的“无聊”且稳定的技术栈。
  • 机械化强制执行架构:通过自定义 linter 和结构测试来强制执行严格的分层领域架构和代码规范,在边界处严格把控,在内部给予智能体实现自由。
  • 高吞吐量合并策略:采用最少的阻塞性合并门控;在智能体高吞吐量系统中,纠错成本极低,而等待成本极高。
  • 端到端自治闭环:Codex 目前已能独立完成从复现 Bug、录制演示视频、实施并验证修复,到响应审查反馈和合并 PR 的全流程。

3) 风险与缺口

  • 早期环境规范不足:由于缺乏高层次目标所需的工具和抽象结构,项目早期进展慢于预期。
  • 单一庞大上下文的失效:过长的全局指令文件(如庞大的 AGENTS.md)会挤占上下文空间、导致智能体针对错误约束进行优化、迅速过时且难以验证。
  • 代码库熵增与模式偏离:完全自治会导致 Codex 复制仓库中已有的次优或参差不齐的代码模式(产生“AI 废料”),必须依赖定期运行的后台清理任务(类似垃圾回收)来维持代码库质量。
  • 长期架构连贯性未知:目前尚不清楚在完全由智能体生成的系统中,架构的连贯性在几年后会如何演变。
  • 控制系统设计挑战:目前最困难的挑战集中在如何设计环境、反馈循环和控制系统,且仍在探索如何将人类的判断力编码到系统中以产生复利。

正文

============================================================= 驾驭工程:在智能体优先的世界中发挥 Codex 的杠杆作用

作者:Ryan Lopopolo,技术团队成员

在过去的五个月里,我们的团队一直在进行一项实验:构建并发布一款软件产品的内部测试版,且手动编写的代码量为 0 行

该产品拥有内部的日常用户和外部的 Alpha 测试人员。它经历了发布、部署、崩溃和修复的过程。不同之处在于,每一行代码——应用逻辑、测试、CI 配置、文档、可观测性以及内部工具——都是由 Codex 编写的。我们估计,构建这个产品所花的时间大约是手动编写代码所需时间的 1/10。

人类负责掌舵。智能体负责执行。

我们有意选择了这一约束条件,以便构建必要的基础设施,从而将工程速度提高几个数量级。我们只有几周的时间来发布最终高达百万行代码的产品。为了做到这一点,我们需要了解当软件工程团队的主要工作不再是编写代码,而是设计环境、明确意图并构建反馈循环以使 Codex 智能体能够可靠地工作时,情况会发生怎样的变化。

本文讲述了我们在与智能体团队共同构建全新产品的过程中学到的经验——什么会崩溃,什么会产生复利,以及如何最大化我们真正稀缺的资源:人类的时间和注意力。

我们从一个空的 git 仓库开始

第一次提交到空仓库是在 2025 年 8 月底。

初始的脚手架——仓库结构、CI 配置、格式化规则、包管理器设置和应用框架——是由 Codex CLI 使用 GPT‑5 生成的,并由少量现有模板提供指导。甚至连指导智能体如何在仓库中工作的初始 AGENTS.md 文件本身也是由 Codex 编写的。

没有任何预先存在的人工编写的代码来作为系统的锚点。从一开始,这个仓库就是由智能体塑造的。

五个月后,该仓库包含了大约一百万行代码,涵盖应用逻辑、基础设施、工具、文档和内部开发者实用程序。在此期间,一个仅由三名工程师组成的小团队驱动 Codex,开启并合并了大约 1,500 个 Pull Request (PR)。这意味着平均每位工程师每天处理 3.5 个 PR,令人惊讶的是,随着团队现在扩大到七名工程师,吞吐量反而增加了。重要的是,这并不是为了产出而产出:该产品已被数百名内部用户使用,包括内部的日常重度用户。

在整个开发过程中,人类从未直接贡献过任何代码。这成为了团队的核心理念:零手动编写代码

重新定义工程师的角色

缺乏人类亲手编写代码的过程,引入了一种不同类型的工程工作,其重点在于系统、脚手架和杠杆作用

早期的进展比我们预期的要慢,这不是因为 Codex 能力不足,而是因为环境规范不够明确。智能体缺乏实现高层次目标所需的工具、抽象和内部结构。我们工程团队的主要工作变成了赋能智能体去做有用的工作。

在实践中,这意味着采用深度优先的工作方式:将较大的目标分解为较小的构建块(设计、代码、审查、测试等),提示智能体构建这些模块,并利用它们来解锁更复杂的任务。当出现故障时,修复方法几乎从来都不是“再试一次(try harder)”。因为取得进展的唯一方法是让 Codex 去完成工作,所以人类工程师总是会介入任务并思考:“缺少了什么能力?我们如何让这种能力对智能体既清晰可读又可强制执行?”

人类几乎完全通过提示词(prompts)与系统交互:工程师描述一个任务,运行智能体,并允许它开启一个 Pull Request。为了推动 PR 完成,我们指示 Codex 在本地审查自己的更改,请求在本地和云端进行额外的特定智能体审查,响应任何人类或智能体给出的反馈,并在循环中迭代,直到所有智能体审查者都满意为止(实际上这是一个 Ralph Wiggum 循环⁠(在新窗口中打开))。Codex 直接使用我们的标准开发工具(gh、本地脚本和嵌入仓库的技能)来收集上下文,而无需人类在 CLI 中复制和粘贴。

人类可以审查 Pull Request,但这不是必须的。随着时间的推移,我们已经将几乎所有的审查工作推向了智能体对智能体(agent-to-agent)的处理方式。

提高应用程序的可读性

随着代码吞吐量的增加,我们的瓶颈变成了人类的 QA(质量保证)能力。因为固定的约束条件是人类的时间和注意力,所以我们致力于通过让应用程序 UI、日志和应用指标本身对 Codex 直接具有可读性,从而为智能体添加更多能力。

例如,我们让应用程序可以在每个 git 工作树(worktree)上启动,这样 Codex 就可以为每次更改启动并驱动一个实例。我们还将 Chrome DevTools Protocol(Chrome 开发者工具协议)接入到智能体运行时中,并创建了处理 DOM 快照、屏幕截图和导航的技能。这使得 Codex 能够直接复现错误、验证修复并推理 UI 行为。

图片 1:图表标题为“Codex 使用 Chrome DevTools MCP 驱动应用程序以验证其工作”。Codex 选择一个目标,在触发 UI 路径前后对状态进行快照,通过 Chrome DevTools 观察运行时事件,应用修复,重启,并循环重新运行验证,直到应用程序干净无误。

我们对可观测性工具也做了同样的处理。日志、指标和追踪(traces)通过本地可观测性技术栈暴露给 Codex,该技术栈对于任何给定的工作树都是短暂存在(ephemeral)的。Codex 在该应用程序的一个完全隔离的版本上工作——包括其日志和指标,一旦任务完成,这些就会被销毁。智能体可以使用 LogQL 查询日志,使用 PromQL 查询指标。有了这些可用的上下文,像“确保服务启动在 800 毫秒内完成”或“在这四个关键用户旅程中,没有任何 span 超过两秒”这样的提示词就变得易于处理了。

图片 2:图表标题为“在本地开发中为 Codex 提供完整的可观测性技术栈”。应用程序将日志、指标和追踪发送到 Vector,Vector 将数据分发到包含 Victoria Logs、Metrics 和 Traces 的可观测性技术栈中,每个都通过 LogQL、PromQL 或 TraceQL API 进行查询。Codex 使用这些信号进行查询、关联和推理,然后在代码库中实施修复,重启应用程序,重新运行工作负载,测试 UI 旅程,并在反馈循环中重复这一过程。

我们经常看到单次 Codex 运行在一个任务上持续工作长达六个小时(通常是在人类睡觉的时候)。

我们将仓库知识作为记录系统

上下文管理是让智能体在大型复杂任务中发挥效用的最大挑战之一。我们最早学到的教训之一很简单:给 Codex 一张地图,而不是一本 1000 页的说明书。

我们尝试过“一个庞大的 AGENTS.md⁠(在新窗口中打开)”方法。它以可预见的方式失败了:

  • 上下文是一种稀缺资源。 一个巨大的指令文件会挤占任务、代码和相关文档的空间——因此智能体要么遗漏了关键约束,要么开始针对错误的约束进行优化。
  • 过多的指导就变成了无指导。 当一切都“重要”时,就没有什么是重要的了。智能体最终会在局部进行模式匹配,而不是有目的地进行导航。
  • 它会瞬间腐烂。 庞大的手册会变成过时规则的坟墓。智能体无法分辨哪些仍然是正确的,人类也停止了维护,这个文件悄然变成了一个“诱人的陷阱(attractive nuisance)”。
  • 它很难验证。 单一的大文件不适合进行机械检查(覆盖率、新鲜度、所有权、交叉链接),因此偏离是不可避免的。

因此,我们不再将 AGENTS.md 视为百科全书,而是将其视为目录

仓库的知识库存放在一个结构化的 docs/ 目录中,并被视为记录系统(system of record)。一个简短的 AGENTS.md(大约 100 行)被注入到上下文中,主要作为一张地图,指向其他地方更深层次的事实来源。

纯文本

1AGENTS.md2ARCHITECTURE.md3docs/4├── design-docs/5│ ├── index.md6│ ├── core-beliefs.md7│ └── ...8├── exec-plans/9│ ├── active/10│ ├── completed/11│ └── tech-debt-tracker.md12├── generated/13│ └── db-schema.md14├── product-specs/15│ ├── index.md16│ ├── new-user-onboarding.md17│ └── ...18├── references/19│ ├── design-system-reference-llms.txt20│ ├── nixpacks-llms.txt21│ ├── uv-llms.txt22│ └── ...23├── DESIGN.md24├── FRONTEND.md25├── PLANS.md26├── PRODUCT_SENSE.md27├── QUALITY_SCORE.md28├── RELIABILITY.md29└── SECURITY.md

仓库内知识存储布局。

设计文档被分类和索引,包括验证状态和一组定义智能体优先操作原则的核心信念。架构文档⁠(在新窗口中打开)提供了领域和包分层的顶层地图。一份质量文档对每个产品领域和架构层进行评分,跟踪随时间推移产生的差距。

计划被视为一等公民。短暂的轻量级计划用于小的更改,而复杂的工作则记录在执行计划⁠(在新窗口中打开)中,其中包含进度和决策日志,并被提交到仓库中。活动计划、已完成计划和已知的技术债务都进行了版本控制并存放在一起,允许智能体在不依赖外部上下文的情况下进行操作。

这实现了渐进式披露:智能体从一个小的、稳定的入口点开始,并被告知接下来该去哪里查找,而不是一开始就被海量信息淹没。

我们通过机械方式强制执行这一点。专用的 linter 和 CI 任务会验证知识库是否是最新的、是否正确交叉链接以及结构是否正确。一个定期运行的“文档园丁(doc-gardening)”智能体会扫描那些不能反映真实代码行为的陈旧或过时文档,并开启修复 Pull Request。

智能体可读性是目标

随着代码库的演进,Codex 的设计决策框架也需要演进。

因为仓库完全是由智能体生成的,所以它首先针对 Codex 的可读性 进行了优化。就像团队旨在提高新入职工程师对代码的导航能力一样,我们人类工程师的目标是让智能体能够直接从仓库本身推理出完整的业务领域。

从智能体的角度来看,任何它在运行时无法在上下文中访问的东西,实际上都不存在。存在于 Google Docs、聊天记录或人们头脑中的知识,系统是无法访问的。仓库本地的、受版本控制的产物(例如代码、Markdown、Schema、可执行计划)是它唯一能看到的东西。

图片 3:图表标题为“智能体知识的局限性:Codex 看不到的东西就不存在”。Codex 的知识被显示为一个有边界的气泡。在它下面是看不见的知识示例——Google Docs、Slack 消息和人类的隐性知识。箭头指示,要使这些信息对 Codex 可见,必须将它们编码到代码库中作为 Markdown 文件。

我们认识到,随着时间的推移,我们需要将越来越多的上下文推送到仓库中。那个让团队在架构模式上达成一致的 Slack 讨论?如果智能体无法发现它,那么它就是不可读的,就像三个月后加入的新员工对此一无所知一样。

给 Codex 提供更多上下文意味着组织并暴露正确的信息,以便智能体可以对其进行推理,而不是用临时的指令淹没它。就像你会向新队友介绍产品原则、工程规范和团队文化(包括表情符号偏好)一样,向智能体提供这些信息会带来更好对齐的输出。

这种框架澄清了许多权衡。我们倾向于使用可以在仓库内完全内化和推理的依赖项和抽象。通常被描述为“无聊(boring)”的技术往往更容易让智能体建模,因为它们具有可组合性、API 稳定性和在训练集中的代表性。在某些情况下,让智能体重新实现部分功能,比绕过公共库中不透明的上游行为成本更低。例如,我们没有引入通用的类似 p-limit 的包,而是实现了我们自己的带并发控制的 map 辅助函数:它与我们的 OpenTelemetry 插桩紧密集成,具有 100% 的测试覆盖率,并且其行为完全符合我们运行时的预期。

将系统的更多部分转化为智能体可以直接检查、验证和修改的形式,不仅增加了 Codex 的杠杆作用,也增加了正在该代码库上工作的其他智能体(例如 Aardvark)的杠杆作用。

强制执行架构与品味

单靠文档并不能保持完全由智能体生成的代码库的连贯性。通过强制执行不变量(invariants),而不是微观管理实现细节,我们让智能体能够快速交付,同时又不会破坏基础。 例如,我们要求 Codex 在边界处解析数据形状⁠(在新窗口中打开),但并不规定它是如何发生的(模型似乎喜欢 Zod,但我们并没有指定那个特定的库)。

智能体在具有严格边界和可预测结构⁠(在新窗口中打开)的环境中最有效,因此我们围绕一个严格的架构模型构建了应用程序。每个业务领域被划分为一组固定的层,具有严格验证的依赖方向和一组有限的允许边缘。这些约束通过自定义 linter(当然是由 Codex 生成的!)和结构测试以机械方式强制执行。

下图展示了这一规则:在每个业务领域(例如应用设置)内,代码只能通过一组固定的层(类型 → 配置 → 仓库 → 服务 → 运行时 → UI)“向前”依赖。横切关注点(身份验证、连接器、遥测、功能标志)通过一个单一的显式接口进入:Providers(提供者)。任何其他方式都是不允许的,并且会被机械地强制执行。

图片 4:图表标题为“具有显式横切边界的分层领域架构”。在业务逻辑领域内部是各个模块:类型 → 配置 → 仓库,以及 提供者 → 服务 → 运行时 → UI,底部是应用组装 + UI。一个 Utils 模块位于边界之外,并输入到提供者中。

这通常是那种你会推迟到拥有数百名工程师时才采用的架构。但对于编码智能体来说,这是一个早期的先决条件:正是这些约束使得在不发生衰退或架构偏离的情况下实现高速度成为可能。

在实践中,我们使用自定义 linter 和结构测试,加上一小部分“品味不变量(taste invariants)”来强制执行这些规则。例如,我们通过自定义 lint 静态地强制执行结构化日志记录、Schema 和类型的命名约定、文件大小限制以及特定于平台的可靠性要求。因为 lint 是自定义的,所以我们编写错误消息,将修复指令注入到智能体的上下文中。

在人类优先的工作流程中,这些规则可能会让人觉得迂腐或受限。但对于智能体来说,它们变成了乘数:一旦被编码,它们就会同时应用于所有地方。

同时,我们明确指出哪些地方的约束很重要,哪些地方不重要。这类似于领导一个大型工程平台组织:在中央强制执行边界,在局部允许自治。你非常关心边界、正确性和可重复性。在这些边界内,你允许团队——或智能体——在如何表达解决方案方面拥有极大的自由度。

生成的代码并不总是符合人类的风格偏好,但这没关系。只要输出是正确的、可维护的,并且对未来的智能体运行具有可读性,它就达到了标准。

人类的品味被持续反馈到系统中。审查评论、重构 Pull Request 和面向用户的错误被捕获为文档更新,或直接编码到工具中。当文档不足以解决问题时,我们会将规则提升为代码。

吞吐量改变了合并理念

随着 Codex 吞吐量的增加,许多传统的工程规范变得适得其反。

仓库以最少的阻塞性合并门控(merge gates)运行。Pull Request 的生命周期很短。测试不稳定(Test flakes)通常通过后续运行来解决,而不是无限期地阻碍进度。在一个智能体吞吐量远远超过人类注意力的系统中,纠错的成本很低,而等待的成本很高。

在低吞吐量环境中,这样做是不负责任的。但在这里,这通常是正确的权衡。

“智能体生成”到底意味着什么

当我们说代码库是由 Codex 智能体生成时,我们指的是代码库中的一切

智能体产出:

  • 产品代码和测试
  • CI 配置和发布工具
  • 内部开发者工具
  • 文档和设计历史
  • 评估测试台(Evaluation harnesses)
  • 审查评论和回复
  • 管理仓库本身的脚本
  • 生产环境仪表板定义文件

人类始终保持在循环中,但工作在我们过去习惯的不同的抽象层面上。我们对工作进行优先级排序,将用户反馈转化为验收标准,并验证结果。当智能体遇到困难时,我们将其视为一个信号:识别缺少了什么——工具、护栏、文档——并将其反馈到仓库中,而且始终是让 Codex 自己编写修复程序。

智能体直接使用我们的标准开发工具。它们拉取审查反馈,进行内联回复,推送更新,并且经常压缩(squash)并合并它们自己的 Pull Request。

不断提高的自治水平

随着越来越多的开发循环被直接编码到系统中——测试、验证、审查、反馈处理和恢复——仓库最近跨越了一个有意义的阈值,Codex 可以端到端地驱动一个新功能。

给定一个提示词,智能体现在可以:

  • 验证代码库的当前状态
  • 复现报告的错误
  • 录制演示故障的视频
  • 实施修复
  • 通过驱动应用程序来验证修复
  • 录制第二个演示问题已解决的视频
  • 开启一个 Pull Request
  • 响应智能体和人类的反馈
  • 检测并修复构建失败
  • 仅在需要判断时才升级给人类处理
  • 合并更改

这种行为在很大程度上依赖于该仓库的特定结构和工具,不应假设在没有类似投入的情况下可以泛化——至少目前还不行。

熵与垃圾回收

完全的智能体自治也引入了新的问题。 Codex 会复制仓库中已经存在的模式——甚至是那些参差不齐或次优的模式。随着时间的推移,这不可避免地会导致偏离。

最初,人类手动解决这个问题。我们的团队过去每个星期五(一周的 20%)都在清理“AI 废料(AI slop)”。不出所料,这种做法无法扩展。

相反,我们开始将我们所谓的“黄金原则”直接编码到仓库中,并构建了一个定期的清理流程。这些原则是带有主观倾向的机械规则,可保持代码库对未来智能体运行的可读性和一致性。例如:(1)我们更喜欢共享的实用程序包,而不是手工编写的辅助函数,以保持不变量的集中化;(2)我们不以“YOLO 风格(随心所欲)”探测数据——我们验证边界或依赖类型化的 SDK,这样智能体就不会意外地基于猜测的数据形状进行构建。按照固定的节奏,我们有一组后台 Codex 任务,它们会扫描偏差、更新质量评分并开启有针对性的重构 Pull Request。其中大部分可以在一分钟内完成审查并自动合并。

这就像垃圾回收一样运作。技术债务就像高息贷款:以小额增量持续偿还,几乎总是比让它产生复利并在痛苦的爆发中解决要好。人类的品味被捕获一次,然后在每一行代码上持续强制执行。这也让我们能够每天捕获并解决不良模式,而不是让它们在代码库中蔓延数天或数周。

我们仍在学习什么

到目前为止,这一策略在 OpenAI 的内部发布和采用过程中运作良好。为真实用户构建真实产品有助于将我们的投资锚定在现实中,并引导我们走向长期的可维护性。

我们还不知道在一个完全由智能体生成的系统中,架构的连贯性在几年内会如何演变。我们仍在学习人类的判断在哪里能增加最大的杠杆作用,以及如何对这种判断进行编码以使其产生复利。我们也不知道随着模型随着时间的推移变得越来越强大,这个系统将如何演变。

已经变得清晰的是:构建软件仍然需要纪律,但这种纪律更多地体现在脚手架上,而不是代码中。保持代码库连贯的工具、抽象和反馈循环变得越来越重要。

我们现在最困难的挑战集中在设计环境、反馈循环和控制系统上,这些系统帮助智能体实现我们的目标:大规模构建和维护复杂、可靠的软件。

随着像 Codex 这样的智能体在软件生命周期中承担越来越大的部分,这些问题将变得更加重要。我们希望分享一些早期的经验教训,能帮助你思考应该将精力投入到哪里,以便你只需专注于构建事物

关联主题