工程技术:在智能体优先的世界中利用 Codex

[!meta]
作者: Ryan Lopopolo (特别感谢 Victor Zhu 和 Zach Brock)
发表时间: 2026-02-11
原文出处: OpenAI Engineering

在过去五个月里,我们的团队一直在进行一项实验:构建并交付一款软件产品的内部 Beta 版,==其中没有一行代码是人工编写的==。

该产品有内部日常活跃用户和外部 Alpha 测试者。它经历了交付、部署、故障和修复的整个过程。

与众不同的是,每一行代码——从应用逻辑、测试、CI 配置、文档、可观察性到内部工具——全都是由 Codex 编写的。据估计,我们只用了手工编写代码所需的大约 1/10 的时间就完成了这项工作。

[!important] 核心定律
人类掌舵。智能体执行。

我们有意选择这一限制,以便构建必要的内容,从而将工程速度提升数个数量级。我们用了几周的时间来交付最终达到一百万行代码的项目。

为此,我们需要了解,当软件工程团队的主要工作不再是编写代码,而是设计环境、明确意图和构建反馈回路,从而使 Codex 智能体能够可靠地工作时,会发生哪些变化。

这篇文章记录的是,在我们与智能体团队一起从零开始打造一款全新产品的过程中,所能学到的经验教训——哪些地方出了问题,哪些问题相互叠加,以及如何最大化利用我们唯一真正稀缺的资源:人类的时间和注意力

1. 角色重塑:掌舵者而非码农

由于缺乏人工编码的实践,==工程师工作的重点转向了系统、架构和杠杆作用==。

早期进展比我们所预期的要慢,而这并不是因为 Codex 不具备相应的能力,而是因为环境的规范不够明确。

该智能体缺乏实现高级目标所需的工具、抽象层和内部结构,因而无法取得进展。我们工程团队的主要任务成了协助智能体完成有用的工作。

[!key] 核心工作法
在实践中,这意味着采用深度优先的工作方式:

  1. 将更大的目标拆解为更小的构建模块(设计、代码、评审、测试等);
  2. 提示智能体去构建这些模块,并使用它们去解锁更复杂的任务;
  3. 当事情进行不顺利时,解决方案基本上再也不会是“再努力一点”。因为取得进展的唯一方式是让 Codex 来完成工作。

人类工程师则总是介入这项任务并追问:“究竟还需要什么样的能力,我们又该如何让这个能力对智能体来说既清晰可读又可强制执行?

人类几乎完全通过提示与系统交互:工程师描述任务,运行智能体,并允许其打开一个 Pull Request。

为了推动 PR 的完成,我们会指示 Codex 在本地审核其自身的更改,在本地和云端请求额外的特定智能体审查,对任何人工或智能体给出的反馈做出响应,并循环往复,直到所有智能体审核人员都满意为止(这实际上是一个 Ralph Wiggum 循环)。

Codex 直接使用我们的标准开发工具(gh、本地脚本和嵌入代码仓库的技能)来收集情境,而无需人工将内容复制粘贴到 CLI 中。

人类可以审核 Pull Request,但并非必须这样做。随着时间的推移,我们已将几乎所有的审核工作调整为用智能体对智能体 (Agent-to-Agent) 的方式来处理。

2. 记录系统:用 Repo 地图引导渐进披露

情境管理是使智能体在大型和复杂任务中有效发挥作用的最大挑战之一。我们学到的最早经验教训之一很简单:

[!tip] 核心经验
要给 Codex 的是一张地图,而不是一本 1,000 页的说明书。

我们曾尝试过“一个大型的 AGENTS.md”方法,但不出所料,那是一次失败的尝试:

  • 情境是一种稀缺资源:巨大的指令文件会挤掉任务代码和相关文档,导致智能体容易错过关键约束,或开始针对错误的约束进行优化。
  • 过多的指导反而无效:当一切都是“重要”时,就意味着没有重点。智能体最终只会在本地进行生硬的模式匹配,而不是有意识地在系统中导航。
  • 文档会立即腐烂:一本庞杂的手册会很快变成陈旧规则的坟场。智能体无法判断哪些信息仍然有效,一旦人类停止维护它,此文件就会悄然成为麻烦的源头。
  • 这极难核实:单块大文件(Blob)不适合进行覆盖率、时效性、所有权或交叉链接的机械检查,导致漂移不可避免。

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

代码仓库的知识库位于一个结构化了的 docs/ 目录中,此目录被当作唯一的记录系统 (System of Record) 来使用。

一份简短的 AGENTS.md(大约 100 行)被注入到情境中,主要用作地图,并指向其他地方更深层次的真实信息来源。

2.1. 代码仓库内知识存储布局

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

设计文档已被编目和索引,其中包括验证状态和一套核心理念,定义了智能体优先的操作原则。

架构文档 提供域和包分层的顶层地图。

一份高质量的文档会对每个产品领域和架构层进行评分,并随着时间的推移追踪差距。

计划被视为一流的工件

临时轻量计划用于小幅变更,而复杂工作则记录在 执行计划 中,并附带进度和决策日志,这些日志会被提交到代码仓库。

活跃计划、已完成计划和已知的技术债务都已进行版本控制并集中存放,使智能体能够在不依赖外部情境的情况下运行。

[!success] 渐进式披露 (Progressive Disclosure)
智能体从一个小而稳定的切入点开始,并被指导下一步该去哪里查看,而不是一开始就被海量的信息淹没。

我们严格执行这一点。

专职的 Linter 和 CI 作业会验证知识库的更新状况、是否已交叉链接且结构正确。

一个定期运行的 “doc-gardening” 智能体会扫描那些不再反映真实代码行为的过时或废弃文档,并发起修复用的 Pull Request。

3. 规范架构:用不变式强制约束系统品味

仅靠文档本身,是没法保持完全由智能体生成的代码库的连贯性的。

[!important] 品味管理法则
通过强制执行不变量,而非对实施过程进行微观管理,我们令智能体能够快速交付,而且不会削弱基础。

例如:我们要求 Codex 在边界处解析数据形状,但不规定具体实现方式(模型似乎偏好 Zod,但我们没有指定特定库)。

智能体在具有严格边界和可预测结构的环境中最为高效,因此我们围绕一个严格的架构模型构建了该应用。

每个业务域都划分为一组固定的层,依赖方向经过严格验证,并且仅允许有限的一组边。

这些约束是通过自定义的 Linter(当然是由 Codex 生成的!)和结构测试机械地强制执行的。

下图展示了规则:在每个业务领域内(例如应用设置),代码只能“向前”依赖于一组固定的层:

Types → Config → Repo → Service → Runtime → UI

横切关注点(认证、连接器、遥测、功能标志)通过一个单一的显式接口进入:Providers。其他任何内容都不被允许,并将通过自动化方式强制执行。

分层领域架构:显式横切边界

[!info]- 图表原理解析:分层领域架构边界
在特定业务逻辑域内:Types → Config → Repo 是核心逻辑层;Providers → Service → Runtime → UI 则层层递进,底部统一由 App Wiring + UI 驱动。外侧通用的 Utils 需通过 Providers 接入。

这种架构通常要等到你拥有数百名工程师时才会推迟。对于编码智能体来说,这是一个早期的先决条件:有了约束,速度才不会下降,架构才不会漂移。

在实践中,我们通过自定义 Linter 和结构测试来强制执行这些规则,并辅以一小组“品味不变式”。

例如:我们通过自定义 lint 静态地强制执行结构化日志记录、模式和类型的命名约定、文件大小限制,以及特定平台的可靠性要求。

由于这些 lint 是自定义的,我们编写错误信息时会在智能体情境中注入修复指令。

在以人为本的工作流程中,这些规则可能会让人感到迂腐或束缚。有了智能体,它们就成了倍增器:一旦编码,它们就能立即应用于所有地方。

同时,我们还明确指出了哪些地方需要限制,哪些地方不需要限制。

这类似于领导一个大型工程平台组织:在中央层面强制执行边界,在本地层面允许自主权。

你非常重视界限、正确性和可重复性。在这些边界内,你允许团队或智能体在解决方案的表达方式上拥有很大的自由。

生成的代码不总是符合人类的风格偏好,这也没关系。只要输出是正确的、可维护的,并且对未来的智能体运行而言清晰易读,就可以算作达标。

人类的品味会不断反馈到系统中。

审查评论、重构的 Pull Request 和面向用户的 Bug 会被记录为文档更新,或直接编码到工具中。

当文档不够完善时,我们会将规则转化为代码。

4. 全栈生成:Agent 生成的实际范畴

当我们说代码库是由 Codex 智能体生成的,我们指的是整个代码库。

智能体的产出包括:

  • [x] 产品代码与测试
  • [x] CI 配置和发布工具
  • [x] 内部开发者工具
  • [x] 文档和设计历史
  • [x] 评估框架
  • [x] 审阅评论和回复
  • [x] 管理代码仓库本身的脚本
  • [x] 生产仪表板定义文件

人类始终参与其中,但工作的抽象层次与过去不同。

我们优先处理工作,将用户反馈转化为验收标准,并对结果进行验证。

当智能体遇到困难时,我们将其视为一个信号:识别缺失的内容——工具、指导与约束、文档——并将其反馈到代码仓库中,始终由 Codex 自己编写修复。

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

5. 熵增对抗:代码库的“黄金原则”与垃圾回收

完全自主的智能体也引入了新的问题。

Codex 会复现代码仓库中已存在的模式——甚至包括那些不均衡或不够理想的模式。随着时间的推移,这不可避免地导致漂移。

最初,人类是手动处理这个问题的。我们的团队过去每周五(占一周的 20%)都要花时间清理“AI 残渣”。不出所料,那并不具备可扩展性。

[!success] 黄金原则与垃圾回收流程
相反,我们开始将我们称为“黄金原则”的内容直接编码到代码仓库中,并建立了一个循环清理流程。

这些原则是带有主观意见的机械规则,旨在保持代码库的可读性和一致性,以便将来运行智能体。例如:

  1. 优先复用:我们更倾向于使用共享的实用程序包,而不是手工编写的辅助工具,以便将不变式集中管理;
  2. 边界验证:我们不会使用“YOLO 式”探测数据——我们会验证边界,或依赖类型化的 SDK,这样智能体就不会意外地基于猜测的结构进行构建。

我们会定期运行一组后台 Codex 任务,扫描偏差、更新质量等级,并发起有针对性的重构 Pull Request。其中大多数都可以在一分钟内完成审查并自动合并。

其功能类似于垃圾回收 (Garbage Collection)

技术债务就像一笔高息贷款:不断地以小额贷款的方式偿还债务,总比让债务不断累积,再痛苦地一次解决要好得多。

人类的品味一旦被捕捉,就会持续应用于每一行代码。这也使我们能够每天发现并解决不良模式,而不是让它们在代码库中传播数天或数周。

6. 延伸阅读