
在过去五个月,我们团队进行了一项极限挑战:从零开始,开发并发布一款完全没有人工编写任何代码的内部产品。
如今,该产品已有内部日活用户及外部Alpha测试人员,能够在真实环境中运行、部署、报错并被修复。其核心特点在于,从应用逻辑到测试脚本,从CI配置到文档与可观测性工具,每一行代码都由 Codex Agent 生成。我们估算,这种模式的开发效率是传统手动编码的10倍。
人类掌舵,Agent执行。
我们设定这个硬性限制,目的就是想验证工程效能能否实现量级上的跃迁。当时,几周内交付百万行代码的紧迫需求,迫使我们重新思考:如果工程师不再亲手“写代码”,而是专注于设计环境、定义意图和构建反馈循环,让Agent可靠地产出结果,那么软件开发模式将如何演变?
本文将分享我们通过Agent团队构建全新产品的实践心得,包括失败的尝试、产生复利效应的策略,以及如何最大化利用人类最宝贵的资源——时间与注意力。
从空仓库起步
2025年8月底,我们向一个空仓库提交了首次提交(Commit)。
初始脚手架由Codex CLI调用GPT-5生成,辅以少量现有模板作为引导,涵盖了仓库结构、CI配置、格式化规则、包管理器设置和应用框架。甚至指导Agent如何在仓库中工作的初始 AGENTS.md 文件,也是由Codex自己完成的。
这里没有任何预存的人工代码作为系统“锚点”。从一开始,整个仓库的形态就是由Agent塑造的。
五个月后,该仓库已拥有约100万行代码,覆盖应用逻辑、基础设施、工具链、文档和内部开发组件。在此期间,一支仅3人的工程团队驱动Codex开启并合并了约1500个PR,相当于人均每天产出3.5个PR。令人惊讶的是,当团队扩大到7人后,人均产出率反而进一步提升。
更重要的是,这并非为了刷量:产品已被数百名内部用户使用,并有重度使用的核心用户。在整个过程中,人类从未直接贡献一行代码。这已成为团队的核心哲学:拒绝人工编写代码。
重新定义工程师的角色
由于不再动手编码,工程师的工作重心转向了系统设计、脚手架搭建和杠杆赋能。
早期进展比预期慢,原因并非Codex能力不足,而是环境的“规范度”不够。Agent缺乏实现高层目标所需的工具、抽象和内部结构。因此,工程团队的首要任务变成了:赋能Agent,使其能够有效工作。
实践中,这采用深度优先的工作方式:将宏大目标拆解为微小的构建块(设计、代码、评审、测试等)。驱动Agent构建这些块。利用已完成的块去解锁更复杂的任务。当任务失败时,修复方案几乎从来不是“再试一次”。由于必须通过Codex推进工作,人类工程师会介入并思考:“缺失了什么能力?我们如何让这种能力对Agent既清晰可见又可强制执行?”
人类与系统的交互几乎完全通过提示词完成:工程师描述任务,运行Agent,并授权其开启一个Pull Request。为了推进PR最终合并,我们会指示Codex在本地审查自己的代码改动,并请求其他特定的Agent(本地或云端)进行交叉评审。Codex会根据人类或Agent的反馈进行响应并迭代,直到所有Agent评审员都满意——这实际上形成了一个“拉尔夫·维格姆循环”(Ralph Wiggum Loop)。Codex直接调用我们的标准开发工具(如GitHub CLI gh、本地脚本和集成在仓库中的技能),自主获取上下文,无需人类手动复制粘贴。
译注:Ralph Wiggum Loop源自《辛普森一家》,在软件工程语境下,通常指代一种“自给自足、闭环且带有幽默色彩的自推导循环”。
虽然人类可以审查PR,但这并非强制要求。随着时间的推移,我们已将几乎所有的评审工作交给了“Agent对Agent”的协作模式。
增加应用的“可读性”
随着代码产出率提升,瓶颈变成了人类的QA能力。由于人类的时间和注意力始终是唯一稀缺资源,我们致力于让应用UI、日志和指标对Codex直接可见且可理解,从而为Agent增添能力。
例如,我们使应用能够针对每个Git工作树独立启动,这样Codex就可以为每次代码变更运行并驱动一个实例。我们还将Chrome DevTools Protocol接入Agent运行时,并创建了处理DOM快照、截图和导航的技能。这使得Codex能够直接复现Bug、验证修复结果并推导UI行为。

我们对可观测性工具也做了同样处理。日志、指标和链路追踪通过一个本地的可观测性栈暴露给Codex,这个栈对于任何给定的工作树来说都是临时的。Codex运行在应用的一个完全隔离的版本上,其日志和指标会在任务完成后被销毁。Agent可以使用LogQL查询日志,使用PromQL查询指标。有了这些上下文,诸如“确保服务启动在800ms内完成”或“这四个关键用户旅程中没有任何Trace Span超过2秒”之类的提示词,就变得可操作了。
我们经常看到单次Codex运行持续处理一个任务超过6小时(通常是在人类睡觉的时候)。
以仓库知识作为“事实来源”
上下文管理是让Agent处理复杂任务的最大挑战之一。我们学到的核心教训是:给Codex一张地图,而不是一本千页手册。
我们曾尝试“单一AGENTS.md大文件”方案,但很快就失败了:
- 上下文稀缺:巨大的指令文件会挤占任务代码和相关文档的空间,导致Agent遗漏关键约束或针对错误目标优化。
- 引导过度等于没有引导:当所有内容都标榜“重要”时,就失去了重点。Agent最终只会进行局部的模式匹配,无法有目的地理解全局。
- 文档极易腐化:单体式手册会变成陈旧规则的坟场。Agent无法判断哪些规则依然有效,人类也懒得维护,结果这份文件反而成了误导Agent的诱饵。
- 难以验证:这种单一的大块内容无法进行机械化检查(如覆盖率、时效性),架构偏离成为必然。
因此,我们将 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
设计文档被编目索引,包含验证状态以及一套定义“Agent优先”运营原则的核心信条。架构文档提供了关于领域划分和包分层的顶级地图。一份质量文档则对每个产品领域和架构层级进行评分,并长期跟踪差距。
计划(Plans)被视为一等公民。临时性的轻量计划用于微小变更,而复杂工作则被记录在执行计划中,连同进度和决策日志一起提交到仓库。活跃计划、已完成计划以及已知技术债都会进行版本化管理并放在一起,使Agent能够无需依赖外部上下文即可开展工作。
这实现了渐进式披露:Agent从一个微小、稳定的入口点开始,并被告知下一步该去哪里寻找信息,而不是预先被海量信息淹没。
我们通过机械化手段强制执行这一点。专门的Linter和CI任务会验证知识库是否处于最新状态、是否正确交叉引用以及结构是否合规。一个循环运行的“文档园丁”Agent会扫描无法反映真实代码行为的陈旧文档,并开启修复类PR。
以“Agent可读性”为目标
随着代码库演进,Codex的设计决策框架也随之进化。
由于整个仓库完全由Agent生成,它首先针对Codex的可读性进行了优化。正如开发团队致力于提高新入职工程师的代码可导航性一样,人类工程师的目标是让Agent能够直接从仓库本身推导并理解完整的业务领域知识。
从Agent视角看,任何在运行时无法通过上下文获取的信息,实际上都不存在。存储在Google Docs、聊天记录或人脑中的知识,系统无法访问。只有仓库本地的、版本化的工件(如代码、Markdown、Schema、可执行计划)才是它可见的全部世界。

我们意识到,随着时间的推移,我们需要将越来越多的上下文推入仓库。比如那次让团队在架构模式上达成一致的Slack讨论,如果它对Agent不可检索,那么它就是“不可读”的——就像对于三个月后入职的新员工来说,这段背景是缺失的一样。
赋予Codex更多上下文,意味着需要组织并暴露正确的信息以便Agent推理,而不是用大量临时指令使其不堪重负。就像向新队友介绍产品原则、工程规范和团队文化一样,向Agent提供这些信息会带来更一致的产出。
这种思路让许多权衡变得清晰。我们更青睐那些可以被完全内化并在仓库内进行推理的依赖项和抽象。那些通常被称为“乏味”的技术,往往因其组合性、API稳定性和在训练集中的高覆盖率,更容易被Agent建模。在某些情况下,让Agent重新实现一部分功能,比绕过公共库中不透明的上层行为成本更低。例如,我们没有引入通用的 p-limit 风格包,而是实现了自己的并发映射助手:它与我们的OpenTelemetry监控紧密集成,拥有100%测试覆盖率,并完全符合运行时期望。
将系统的更多部分转化为Agent可以直接检查、验证和修改的形式,不仅提升了Codex的杠杆效能,也同样造福了其他在同一代码库中工作的Agent。
强制执行架构与审美
仅靠文档不足以保持一个完全由Agent生成的代码库的连贯性。通过强制执行“不变量”而非微观管理实现细节,我们让Agent在快速交付的同时,不破坏系统根基。例如,我们要求Codex在系统边界处必须进行数据格式解析,但并不强制规定实现方式(模型似乎偏好Zod,但我们从未指定过这个特定库)。
Agent在边界严格且结构可预测的环境中效率最高。因此,我们围绕一套僵化的架构模型构建了应用。每个业务领域被划分为一组固定的层级,拥有严格验证的依赖方向和有限的允许连接点。这些约束通过自定义Linter(当然也是Codex生成的!)和结构化测试进行机械化强制执行。
下图展示了这一规则:在每个业务领域内,代码只能沿着一组固定的层级“向前”依赖(类型定义 → 配置 → 仓库层 → 服务层 → 运行时 → UI)。跨领域关注点通过单一且明确的接口进入:提供者(Providers)。除此之外的任何依赖都是被禁止的,并由机械化手段强制执行。

这种架构通常是在拥有数百名工程师后才会考虑推行的。但在使用编程Agent时,它是前置的必要条件:正是这些约束,才使得系统在高速迭代的同时,不会出现腐化或架构偏离。
实践中,我们通过自定义Linter、结构化测试以及一小套“审美不变量”来执行这些规则。例如,我们通过静态检查强制要求:结构化日志记录、架构和类型的命名规范、文件大小限制,以及针对特定平台的可靠性要求。由于Linter是自定义的,我们可以编写专门的错误信息,以便将修复指令直接注入到Agent的上下文中。
在以人类为中心的工作流中,这些规则可能显得过于死板。但在Agent环境下,它们变成了效能倍增器:规则一旦被编码,就会立即应用于所有地方。
与此同时,我们明确区分了哪些地方需要约束,哪些地方不需要。这非常像领导一个大型工程平台组织:中央强制执行边界,地方允许自主。你需要极度关注边界、正确性和可复现性;而在这些边界之内,你允许团队(或Agent)在表达解决方案时拥有极大的自由。
最终生成的代码并不总是符合人类的审美偏好,但这没关系。只要产出是正确的、可维护的,并且对未来的Agent运行而言是可理解的,它就达到了标准。
人类的审美会持续反馈到系统中。评审评论、重构PR以及面向用户的Bug都会被转化为文档更新,或直接编码进工具链。当文档不足以约束行为时,我们就将规则晋升为代码。
吞吐量的提升改变了合并哲学
随着Codex吞吐量增加,许多传统的工程规范反而变得适得其反。
仓库运行时的阻塞性合并门槛极低。Pull Request的生命周期非常短。对于测试偶发失败,通常通过后续运行来解决,而不是无限期地阻塞进度。在一个Agent吞吐量远超人类注意力的系统中,纠错是廉价的,而等待是昂贵的。
在低吞吐量的传统环境中,这样做是不负责任的;但在这里,这通常是正确的权衡。
“Agent生成”的真正含义
当我们说代码库由Codex Agent生成时,我们指的是代码库中的一切。
Agent产出的内容包括:
- 产品代码与测试脚本
- CI配置与发布工具
- 内部开发者工具
- 文档与设计历史
- 评估框架
- 评审评论及回复
- 管理仓库本身的脚本
- 生产环境仪表盘的定义文件
人类依然掌控全局,只是工作的抽象层级变了。我们现在的任务是排列优先级、把用户反馈转化为验收标准,并最终对结果把关。一旦Agent开发受阻,这就是一个明确信号,提醒我们去复盘:系统里到底缺了什么?是工具不够,护栏不稳,还是文档有误?找到症结后,我们会把这些反馈注入仓库,但依然坚持让Codex自己动手来编写修复方案。
Agent直接使用我们的标准开发工具。它们获取评审反馈、进行行内回复、推送更新,并且通常会自主压缩并合并自己的PR。
持续提升的自主化水平
随着越来越多的开发环路被直接编码进系统中,该仓库最近跨越了一个里程碑门槛:Codex已经能够端到端地驱动新特性的开发。
仅需一段提示词,Agent现在就可以自主完成以下流程:
- 验证代码库的当前状态
- 复现报告的Bug
- 录制一段展示故障过程的视频
- 实现修复方案
- 通过操作应用来验证修复结果
- 录制第二段展示修复效果的视频
- 开启Pull Request
- 响应Agent及人类的反馈
- 检测并修复构建失败
- 仅在需要人类判断时才上报
- 合并变更
这种行为极度依赖于本仓库特定的结构和工具链。在没有类似投入的情况下,不应假设这种能力可以被直接泛化。
熵增与垃圾回收
完全的Agent自主权也带来了全新挑战。Codex会复制仓库中已有的模式——即便是那些不均衡或非最优的模式。随着时间的推移,这不可避免地会导致架构偏离。
最初,人类通过手动方式解决这个问题。我们的团队曾固定在每周五清理“AI废料”。不出所料,这种模式根本无法扩展。
针对这些问题,我们选择将所谓的“金科玉律”直接写入代码仓库,并建立了一套周期性的清理机制。这些原则是一些带有明确主张的机械化规则,目的是确保代码库在后续的Agent运行中始终保持清晰、一致。具体实践包括:
- 我们更倾向于使用共享的工具包,而不是手写辅助函数,这样可以集中管理那些不变量。
- 我们拒绝“全凭运气”的数据探测,必须在边界处进行校验,或者依赖强类型SDK,防止Agent采样猜测的数据形状来编写代码。
我们会定期运行一组Codex后台任务,专门扫描偏离规则的代码,更新质量评分并开启针对性的重构PR。由于这些规则非常明确,大部分PR在一分钟内就能完成评审并自动合并。
这种机制运行起来就像“垃圾回收”。技术债就像高利贷:连续进行小额偿还,几乎总是优于让其复滚并最终在痛苦的爆发式清理中解决。人类的审美被捕获一次后,便会持续强制执行到每一行代码中。这还让我们能够在日常工作中及时发现并消除不良模式,而不是任由它们在代码库中蔓延数天甚至数周。
我们仍在探索的领域
到目前为止,这套策略在内部产品的发布和推广中表现良好。通过为真实用户构建真实产品,我们的投入得以为现实需求服务,并引导系统走向长期可维护。
目前我们尚不清楚,在一个完全由Agent生成的系统中,其架构连贯性在长达数年的跨度下会如何演进。我们仍在摸索人类判断力在何处能产生最大的杠杆效应,以及如何将这种判断力转化为可沉淀、可产生复利的规则。同时,随着模型能力持续增强,这套系统将如何进化也仍是未知数。
但有一点已经非常明确:构建软件仍然需要严谨的纪律,只不过这种纪律不再体现在代码编写上,而是体现在“脚手架”的搭建上。那些能保持代码库连贯性的工具链、抽象层和反馈循环,正变得愈发重要。
我们现在面临的最艰巨挑战在于如何设计环境、反馈循环和控制系统。唯有如此,才能帮助Agent达成我们的目标,即大规模地构建并维护复杂且可靠的软件。
随着Codex等Agent承担起软件生命周期中越来越多的份额,这些问题将变得至关重要。希望这些早期教训能帮助你思考该在何处投入精力,从而让你能更纯粹地去创造产品。也欢迎在 云栈社区 与更多开发者交流这类前沿的工程实践。
原文链接:
https://openai.com/index/harness-engineering/