过去五个月,我们团队一直在进行一项实验:构建和发布一款软件产品的内部测试版,全部代码由 Codex 自动生成,没有任何人工编写的代码。
该产品已有内部日常用户和外部 alpha 测试者。它可以发布、部署、运行、出现问题并得到修复。不同之处在于,每一行代码——应用逻辑、测试、CI 配置、文档、可观测性和内部工具——都是由 Codex 编写的。我们估计,使用 Codex 编写代码的速度大约是人工编写的 1/10。
人类引导,智能代理执行。
我们故意设置了这个限制,以便在工程效率方面取得数量级的提升。在短短几周内,我们构建了一个最终包含百万行代码的产品。为了实现这一目标,我们需要了解当软件工程团队的主要任务不再是编写代码,而是设计环境、指定意图并建立反馈循环,以使 Codex 智能代理能够可靠地工作。
本文将介绍我们在使用智能代理团队构建全新产品时学到的经验——什么问题出现了,什么情况变得复杂,以及如何最大化利用我们真正稀缺的资源:人类的时间和注意力。
空仓库的第一个提交记录于 2025 年 8 月末。
初始框架——仓库结构、CI 配置、格式化规则、包管理器设置和应用框架——由 Codex CLI 使用 GPT-5 生成,并以少量现有模板为指导。甚至指导智能代理在仓库中工作的初始 AGENTS.md 文件也是由 Codex 编写的。
没有预先存在的人工编写的代码来锚定系统。从一开始,仓库就由智能代理塑造。
五个月后,仓库中包含约一百万行代码,涵盖应用逻辑、基础设施、工具、文档和内部开发者工具。在此期间,约有 1,500 个拉取请求被打开和合并,仅需三名工程师驱动 Codex。这相当于每位工程师每天平均 3.5 个拉取请求,令人惊讶的是,随着团队扩大到七名工程师,吞吐量反而增加了。重要的是,这并非为了产出而产出:该产品已被内部数百名用户使用,包括每日内部重度用户。
在整个开发过程中,人类从未直接贡献任何代码。这成为团队的核心哲学:没有人工编写的代码。
缺乏人工编码 引入了一种不同类型的工程工作,专注于系统、基础架构和杠杆效应。
早期进展比预期缓慢,不是因为 Codex 能力不足,而是因为环境规范不明确。智能代理缺乏所需的工具、抽象和内部结构,无法朝着高级目标取得进展。我们工程团队的主要任务变成了使智能代理能够开展有用的工作。
实际上,这意味着深度优先工作:将更大的目标分解为较小的构建块(设计、编码、审查、测试等),提示智能代理构建这些块,并使用它们来解锁更复杂的任务。当出现问题时,解决方法几乎从不是“尝试更努力”。由于取得进展的唯一方法是让 Codex 完成工作,人类工程师总是介入任务并询问:“缺少什么能力,我们如何使其对智能代理来说既易读又可强制执行?”
人类几乎完全通过提示与系统交互:工程师描述任务,运行智能代理,并允许它打开拉取请求。为了驱动拉取请求完成,我们指示 Codex 在本地审查自己的更改,请求其他特定的智能代理审查(本地和云端),响应人类或智能代理的反馈,并迭代直到所有智能代理审查者满意(实际上,这是一个 Ralph Wiggum Loop)。Codex 直接使用我们的标准开发工具(gh、本地脚本和存储库嵌入式技能)来收集上下文,而无需人类复制和粘贴到 CLI。
人类可以审查拉取请求,但不是必需的。随着时间的推移,我们已将几乎所有的审查工作转移到智能代理之间进行。
随着代码吞吐量的增加,我们的瓶颈变成了人类 QA 能力。由于人类时间和注意力的限制,我们通过使应用 UI、日志和应用指标本身直接对 Codex 可读,来为智能代理添加更多功能。
例如,我们使应用可启动到 git 工作树中,因此 Codex 可以为每个更改启动和驱动一个实例。我们还将 Chrome DevTools 协议连接到智能代理运行时,并创建了处理 DOM 快照、截图和导航的技能。这使 Codex 能够重现错误、验证修复和直接推理 UI 行为。

我们对可观测性工具也做了同样的处理。日志、指标和跟踪通过本地可观测性堆栈暴露给 Codex,该堆栈对于任何给定的工作树都是短暂的。Codex 在应用的完全隔离版本上工作,包括其日志和指标,这些日志和指标会在任务完成后被销毁。智能代理可以使用 LogQL 查询日志,使用 PromQL 查询指标。借助可用的上下文,像“确保服务启动时间少于 800ms”或“这四个关键用户旅程中没有一个 span 超过两秒”这样的提示变得可以处理。
我们经常看到单个 Codex 运行在单个任务上工作长达六个小时(通常是在人类睡觉时)。
上下文管理是使智能代理在大型和复杂任务中有效的主要挑战之一。我们学到的最早的教训之一非常简单:给 Codex 一张地图,而不是一千页的说明书。
我们尝试了“一本通用的 AGENTS.md”的方法。它以可预测的方式失败了:
因此,我们没有把 AGENTS.md 当作百科全书,而是把它当作 目录。
存储库的知识库存储在结构化的 docs/ 目录中,被视为记录系统。一个简短的 AGENTS.md(大约 100 行)被注入上下文中,主要用作地图,指向其他地方更深层次的真实来源。
1 AGENTS.md
2 ARCHITECTURE.md
3 docs/
4 ├── design-docs/
5 │ ├── index.md
6 │ ├── core-beliefs.md
7 │ └── ...
8 ├── exec-plans/
9 │ ├── active/
10 │ ├── completed/
11 │ └── tech-debt-tracker.md
12 ├── generated/
13 │ └── db-schema.md
14 ├── product-specs/
15 │ ├── index.md
16 │ ├── new-user-onboarding.md
17 │ └── ...
18 ├── references/
19 │ ├── design-system-reference-llms.txt
20 │ ├── nixpacks-llms.txt
21 │ ├── uv-llms.txt
22 │ └── ...
23 ├── DESIGN.md
24 ├── FRONTEND.md
25 ├── PLANS.md
26 ├── PRODUCT_SENSE.md
27 ├── QUALITY_SCORE.md
28 ├── RELIABILITY.md
29 └── SECURITY.md
存储库内知识存储布局。
设计文档被编目和索引,包括验证状态和一组定义智能代理优先操作原则的核心信念。架构文档 提供了域和包分层的顶级地图。质量文档对每个产品域和架构层进行评分,跟踪随时间推移的空白。
计划被视为一等公民。小型更改使用短期的轻量级计划,而复杂的工作则被捕获在 执行计划 中,包含进度和决策日志,这些日志被提交到存储库中。活动计划、已完成的计划和已知的技术债务都被版本化和集中存储,允许智能代理在不依赖外部上下文的情况下运行。
这使得 渐进式披露 成为可能:智能代理首先从一个小而稳定的入口开始,然后被告知下一步该去哪里,而不是一开始就被大量信息淹没。
这使得 渐进式披露 成为可能:代理从一个小而稳定的入口开始,并被告知下一步该去哪里,而不是一开始就被信息淹没。
我们机械地强制执行这一点。专用的 linter 和 CI 作业验证知识库是否最新、相互关联并且结构正确。一个循环的“文档维护”代理会扫描过时或废弃的文档,这些文档不能反映实际的代码行为,并会打开修复的拉取请求。
随着代码库的演变,Codex 的设计决策框架也需要演变。
由于代码库完全由代理生成,因此它首先针对 Codex 的可读性 进行了优化。就像团队旨在改善新工程师加入时代码的可导航性一样,我们的人类工程师的目标是让代理可以直接从代码库本身理解整个业务领域。
从代理的角度来看,它在运行时无法在上下文中访问的内容是不存在的。存储在 Google Docs、聊天线程或人们脑海中的知识对系统来说是不可访问的。代码库本地的、版本化的工件(例如代码、markdown、模式、 可执行计划)都是它可以看到的。

我们了解到,随着时间的推移,我们需要将越来越多的上下文推送到代码库中。那个使团队在架构模式上达成一致的 Slack 讨论?如果它对代理不可发现,那么它就像三个月后加入的新员工一样不可读。
给予 Codex 更多上下文意味着组织和暴露正确的信息,以便代理可以推理它,而不是用临时指令淹没它。就像您会为新同事提供产品原则、工程规范和团队文化(包括表情符号偏好)进行入职培训一样,给代理这些信息会导致输出更好地对齐。
这种框架阐明了许多权衡取舍。我们倾向于选择可以在代码库中完全内部化并推理的依赖和抽象。那些通常被描述为“枯燥”的技术由于可组合性、API 稳定性和训练集中的表示而更容易被代理建模。在某些情况下,与其围绕公共库的不透明上游行为进行变通,不如让代理重新实现部分功能。例如,我们没有引入一个通用的 p-limit 样式包,而是实现了自己的带有并发性的映射助手:它与我们的 OpenTelemetry 仪表盘紧密集成,具有 100% 的测试覆盖率,并且行为完全符合我们的运行时预期。
将更多系统拉入代理可以直接检查、验证和修改的形式中,不仅增加了 Codex 的杠杆率,也增加了其他代理(例如 Aardvark)的杠杆率,它们也在处理代码库。
仅凭文档不足以保持完全由代理生成的代码库的连贯性。通过强制不变式而不是微观管理实现,我们让代理快速交付而不至于破坏基础。 例如,我们要求 Codex 在边界处 解析数据形状,但并不规定具体如何实现(模型似乎更喜欢 Zod,但我们并没有指定那个特定的库)。
代理在具有 严格边界和可预测结构 的环境中最为有效,因此我们围绕一个刚性的架构模型构建了应用程序。每个业务领域都被划分为一组固定的层,具有严格验证的依赖方向和有限的允许边集。这些约束通过自定义的 linter(当然是 Codex 生成的!)和结构测试机械地强制执行。
下图显示了规则:在每个业务领域(例如,应用设置)内,代码只能通过一组固定的层依赖“向前”(类型 → 配置 → 代码库 → 服务 → 运行时 → UI)。 跨领域关注点(身份验证、连接器、遥测、功能标志)通过单一的显式接口进入:提供者。其他任何方式都是不允许的,并且机械地强制执行。

这种架构通常会在您拥有数百名工程师时推迟。对于编码代理来说,它是一个早期先决条件:约束允许速度而不会衰退或架构漂移。
在实践中,我们通过自定义的 linter 和结构测试以及一组小的“风格不变式”来强制执行这些规则。例如,我们静态地强制执行结构化日志记录、模式和类型的命名约定、文件大小限制以及具有自定义 lint 的平台特定可靠性要求。因为 lint 是自定义的,所以我们编写错误消息以将修复指令注入代理上下文。
在人类优先的工作流程中,这些规则可能感觉很刻板或约束人。但对于代理来说,它们变成了倍增器:一旦编码,它们就立即在所有地方应用。
同时,我们明确指出约束在哪些地方重要,在哪些地方不重要。这类似于领导一个大型工程平台组织:在中心强制边界,允许本地自治。你会深入关心边界、正确性和可重复性。在这些边界内,你允许团队或代理在解决方案表达方面有显著的自由。
生成的代码并不总是符合人类的风格偏好,但这没关系。只要输出正确、可维护并且对未来的代理运行可读,就达到了标准。
人类的品味通过审查评论、重构拉取请求和面向用户的错误反馈到系统中。当文档不足时,我们会将规则提升到代码中。
随着 Codex 的吞吐量增加,许多传统的工程规范变得适得其反。
代码库在很少的阻塞合并关口下运行。拉取请求是短暂的。测试 flake 通常通过后续运行解决,而不是无限期阻塞进度。在一个代理吞吐量远超人类注意力的系统中,修正是廉价的,而等待是昂贵的。
在低吞吐量环境中,这将是鲁莽的。在这里,它往往是正确的权衡。
当我们说代码库由 Codex 代理生成时,我们指的是代码库中的所有内容。
代理生成:
人类始终保持在环中,但工作在不同的抽象层面上。我们优先处理工作,将用户反馈转化为验收标准,并验证结果。当代理遇到困难时,我们将其视为信号:识别缺少的内容 - 工具、护栏、文档 - 并将其反馈到代码库中,始终由 Codex 本身编写修复程序。
代理直接使用我们的标准开发工具。他们拉取审查反馈,在线响应,推送更新,并经常压缩和合并自己的拉取请求。
随着开发循环的更多部分直接编码到系统中 - 测试、验证、审查、反馈处理和恢复 - 代码库最近跨越了一个有意义的门槛,Codex 可以端到端地驱动新功能。
给定一个提示,代理现在可以:
这种行为在很大程度上取决于该代码库和工具的具体结构和工具,不应假设在没有类似投资的情况下会普遍适用 - 至少目前还不是这样。
完全的代理自主权也引入了新的问题。 Codex 复制了代码库中已经存在的模式 - 即使是不均匀或次优的模式。随着时间的推移,这不可避免地导致漂移。
最初,人类手动解决了这个问题。我们的团队曾经每周五(每周的 20%)清理“AI 垃圾”。不出所料,这并不具备可扩展性。
相反,我们开始将我们称之为“黄金原则”的内容直接编码到代码库中,并建立了一个循环的清理过程。这些原则是带有机械规则的有偏见的规则,它们保持代码库的可读性和一致性,以供未来的代理运行。例如:(1)我们更喜欢共享实用程序包而不是手工制作的帮助程序,以将不变式集中起来;(2)我们不以“YOLO 风格”探测数据 - 我们验证边界或依赖于类型化的 SDK,以便代理不会意外地建立在猜测的形状上。在定期的节奏中,我们有一组后台 Codex 任务,扫描偏差,更新质量等级,并打开有针对性的重构拉取请求。其中大多数可以在不到一分钟内审查并自动合并。
相反,我们开始在代码仓库中直接编码我们所称的“黄金原则”,并建立了一个定期的清理流程。这些原则是有倾向性的、机械的规则,它们能使代码库在未来的代理运行中保持易读和一致。例如:(1)我们更倾向于使用共享的工具包,而不是自己编写的辅助函数,以保持不变性的集中管理;(2)我们不会以“YOLO 方式”探测数据——我们会验证边界或依赖类型化的 SDK,这样代理就不会意外地基于猜测的形状构建内容。在定期的时间间隔内,我们有一组后台 Codex 任务,会扫描偏差、更新质量评级并开启有针对性的重构拉取请求。其中大部分可以在一分钟内审查完毕并自动合并。
这就像垃圾收集一样。技术债务就像高利贷款:通常最好以小步幅连续偿还,而不是让它复合并在痛苦的突发中解决。人类的偏好被捕获一次,然后在每行代码中连续强制执行。这也让我们能够每天捕获和解决不良模式,而不是让它们在代码库中传播数天或数周。
到目前为止,这一策略在 OpenAI 的内部发布和采用过程中表现良好。 为真正的用户构建真正的产品有助于我们的投资落到实处,并引导我们实现长期的可维护性。
我们尚不知道的是,在完全由代理生成的系统中,架构一致性如何随着时间的推移而演变。我们仍在学习人类的判断力在哪里能发挥最大作用,以及如何编码这种判断力使其不断增强。我们也不知道,随着模型随着时间的推移变得越来越强大,这个系统将如何演变。
很明显的是:构建软件仍然需要纪律,但这种纪律更多地体现在脚手架上,而不是代码本身。保持代码库一致性的工具、抽象和反馈循环变得越来越重要。
我们目前最困难的挑战集中在设计环境、反馈环和控制系统,以帮助代理实现我们的目标:大规模构建和维护复杂、可靠的软件。
随着 Codex 等代理在软件生命周期中承担更大的角色,这些问题将变得更加重要。我们希望分享一些早期经验能帮助您思考在哪里投入精力,以便 您可以直接构建事物。