Harness Engineering(二):给 Agent 一张代码库地图
把所有规则塞进一份巨型 AGENTS.md,并不能解决上下文问题。Agent 真正需要的是清晰入口、分层知识,以及一套始终与代码同步的知识体系。
Jonathan
创始人
Agent 第一次进入陌生的代码库,很像一名刚加入团队的工程师。它能阅读代码、搜索文件,却不知道核心业务位于哪些目录,哪些限制源于过去的事故,哪些文档早已过时,也不知道某个看似奇怪的实现其实是团队有意做出的取舍。
很多团队的第一反应,是写一份更长的 AGENTS.md:把项目介绍、目录结构、编码规范、常用命令、产品原则和各种注意事项全部放进去,希望 Agent 开始工作前一次读完。
OpenAI 的 Harness Engineering 实验表明,这种做法很快就会失效。他们最终把一份约 100 行的 AGENTS.md 当作目录,而不是百科全书。详细知识则分别写入版本化的 docs/ 目录、架构文档、产品规格和执行计划。
这个变化背后是一条更普遍的原则:
Agent 需要一张可以继续探索的地图,而不是一本每次都必须背下来的手册。
巨型 AGENTS.md 同时浪费上下文和注意力
把所有指导集中在一个文件里,看起来最方便,却会产生四个问题。
第一,上下文空间有限。一份巨大的说明文件会与当前任务、相关代码和工具结果争夺 token。Agent 读到的文字更多了,真正相关的信息反而更容易被淹没。
第二,规则失去了轻重之分。架构边界、命名偏好、部署警告和单个组件的局部约定混在一起时,Agent 很难判断哪些是必须遵守的全局规则,哪些只是特定场景下的建议。当每句话都标成“必须”,也就等于没有优先级。
第三,内容会迅速过时。新规则不断加入,旧规则却很少删除。几个月后,Agent 面对的便是一组真假难辨的约束。过时文档甚至比没有文档更危险,因为它仍然显得权威可信。
第四,内容很难自动核验。面对一整块长文档,团队很难持续检查:每个业务领域是否有人负责?架构页面是否仍被引用?某项产品规格是否已经实现?文中的链接是否仍然有效?
因此,真正的问题不是“AGENTS.md 应该写多长”,而是仓库知识是否具有清晰边界、稳定入口和持续维护机制。
代码库应该成为工程事实的唯一可信来源
Agent 在执行任务时无法访问的信息,对它来说实际上就不存在。
团队可能在 Slack 讨论后决定不采用某个依赖,也可能因为一次线上事故增加重试限制;产品负责人或许只在会议上解释过某个看似反常的交互。如果这些信息只留在聊天记录、会议纪要或个人记忆里,Agent 下次修改相关代码时便无从得知。
这并不意味着所有公司知识都要搬进 Git。真正应该进入代码库的,是会影响软件设计和验证的工程事实:
- 当前架构和允许的依赖方向。
- 各业务领域的边界与关键产品行为。
- 已经做出的决定及其理由。
- 正在执行的计划、已完成的工作和已知技术债务。
- 可靠性、安全和质量要求。
- 可以执行的开发、测试与发布方式。
把这些内容纳入版本控制有三个好处:知识可以和代码同步变化;代码审查可以发现实现与文档不一致;Agent 也能在同一个环境中搜索、引用和更新这些信息。
这样一来,代码库不再只是存放源代码的地方,也成为 Agent 查找工程事实的可信来源。
分层导航让 Agent 只加载当前所需的信息
一个适合 Agent 的知识结构,可以从三层开始:
AGENTS.md
├── 项目入口、核心命令、全局不变量
├── 指向架构、产品、计划和质量文档的地图
└── 说明什么时候应该读取哪一类文档
ARCHITECTURE.md
├── 顶层业务域和包结构
├── 依赖方向与关键边界
└── 指向各领域设计文档
docs/
├── design-docs/ 设计决定与核心理念
├── product-specs/ 产品行为与验收标准
├── exec-plans/ 活跃计划、完成计划、决策日志
├── generated/ 数据库结构等自动生成事实
└── references/ 外部库和平台的项目相关说明
这里最重要的不是目录如何命名,而是 Agent 如何读取它们。
Agent 首先读取简短、稳定的入口,确认任务属于哪个业务领域;再沿着链接查阅相关架构和产品规则;只有在处理复杂任务时,才继续加载执行计划和更深入的文档。与当前任务无关的细节无需进入上下文。
这就是渐进式提供信息:先给出导航,再按需展开。这样既能提高上下文的相关性,也让每份文档拥有更明确的职责,更容易持续维护。
Agent 是否看得懂,也会影响技术选型
当代码库成为工程事实的可信来源后,团队选择依赖和抽象时,考虑的就不再只有开发便利性。还要问:Agent 能否在代码库中检查它、理解它,并验证它的行为?
OpenAI 团队发现,一些看似“朴素”的技术反而更适合 Agent。它们的 API 更稳定,组件之间更容易组合,公开资料也更充分。相反,如果第三方库把关键行为藏在代码库之外,Agent 可能需要花费大量精力猜测和绕过它。有时,实现一个范围明确、完全可检查的本地抽象,反而比适配不透明的外部依赖更简单。
例如,团队没有直接引入通用的 p-limit 类库,而是实现了一个支持并发控制的 map helper。这个本地实现能直接接入 OpenTelemetry,拥有完整的测试覆盖,而且行为与项目运行时的要求完全一致。
这并不是主张重复实现所有依赖。判断标准应该是:哪种选择更容易让 Agent 理解、验证和修改系统,同时又不会给团队带来不必要的维护成本。让更多关键行为在代码库内可见,受益的也不只是 Codex,还包括未来接手系统的工程师和其他 Agent。
计划和决策也应该进入版本控制
复杂的 Agent 任务往往持续数小时,甚至跨越多个上下文窗口。如果计划只存在于最初的 prompt 或对话记录中,一次上下文压缩、任务重启或工作交接,就可能让关键决定丢失。
因此,计划不能只是 Agent 临时生成的一段文字。对较大的变更,它至少应该记录:
- 目标与非目标。
- 当前进度和剩余步骤。
- 已确认的约束。
- 做过的关键决定及理由。
- 发现但暂不处理的技术债务。
- 验证方式与当前结果。
小任务可以使用简短计划;复杂任务则需要一份能够中断后继续执行的计划。任务完成后也不要立即删除,而应归档到已完成区域,让后来的 Agent 理解相关代码为何演变成今天的样子。
这与普通的项目管理记录不同。它不是为了向管理者汇报,而是为了保持工程工作的连续性。下一个 Agent 无需从聊天记录中重新推断进度,可以直接根据结构化计划继续工作。
文档必须进入反馈循环,才能保持可信
“把知识写进仓库”本身还不够。没有维护机制的知识库,只会制造更大规模的过期信息。
这套维护机制可以分为三层:
- 结构检查:验证必需文件、链接、索引、负责人和元数据是否存在。
- 变更检查:当代码跨越架构边界或改变公开行为时,要求同时更新对应文档。
- 内容巡检:定期让 Agent 对照代码检查文档,发现过时内容后发起范围明确的修复。
第三层尤其适合 Agent。它不必一次重写整个知识库,只需持续寻找能够明确验证的偏差,例如已经删除的路径、失效的命令、与实际数据结构不一致的示例,以及尚未加入索引的新设计文档。
这样,文档维护就能像测试一样进入 CI 和日常工作,而不必等到半年后再进行一次大规模清理。
一份仓库地图应该回答五个问题
如果要为现有项目建立面向 Agent 的知识入口,可以先检查 AGENTS.md 能否让 Agent 快速回答以下问题:
- 这个项目解决什么问题,哪些目标不在范围内?
- 代码库由哪些核心领域组成,依赖方向是什么?
- 完成开发、测试和验证应该使用哪些命令?
- 哪些规则是全局不变量,违反后会被什么检查发现?
- 遇到产品、架构、可靠性或安全问题时,下一步应该阅读哪里?
如果一个答案需要数百行解释,就把详细内容移动到专门文档,并从入口链接过去。如果某条规则足够稳定且重要,就考虑把它升级成自动检查,而不是永远留在文字里。
代码库地图的价值,不是让 Agent 一次掌握所有信息,而是让它意识到自己还缺少什么,并知道去哪里寻找可信答案。
下一篇会继续解决另一个环境缺口:即使 Agent 理解了代码库,它仍然需要直接观察正在运行的软件,才能独立验证自己的工作。
本文整理自 OpenAI 的文章 Harness engineering: leveraging Codex in an agent-first world,核心观点来自原文。
Harness Engineering 系列
- (一)当工程师开始设计 Agent 的工作环境
- (二)给 Agent 一张代码库地图(本文)
- (三)让软件运行状态对 Agent 可读
- (四)把工程规则变成可执行约束
- (五)当 Agent 的产出超过人的注意力
- (六)Agent 也会复制技术债务
相关阅读
- Agent 长任务的瓶颈,是上下文工程 —— 从运行时角度理解上下文、压缩、记忆和状态。
- 智能体需要 Harness,不只是更强的模型 —— Harness 为什么是模型转化为可靠行动的工程外壳。