写给谁
你已经在用 Claude Code、Codex CLI、Cursor 或其他 AI coding agent 写代码。你发现 agent 有时候表现很好,有时候莫名其妙——同一个模型,在项目 A 里很靠谱,在项目 B 里乱来。你怀疑问题不在模型,而在你给它的"环境"。
你怀疑得对。
2026 年 2 月,OpenAI 发布了一篇名为 Harness Engineering: Leveraging Codex in an Agent-First World 的文章,描述了他们用 Codex agent 从零构建百万行代码产品的经验。核心发现是:瓶颈从来不是模型的编码能力,而是缺少结构、工具和反馈机制。 LangChain 在 Terminal Bench 2.0 上的实验也验证了同一结论——同一个模型,仅改变 harness(即环境和约束),得分从 52.8% 跳到 66.5%,从排行榜中游直接进入 Top 5。
本文聚焦其中最核心的一环:项目文档——agent 的"眼睛"和"地图"。
第一原则:Agent 看不到的,就不存在
在讨论任何具体实践之前,先建立一个根本认知。
OpenAI 在 Harness Engineering 文章中明确说:从 agent 的视角看,任何它无法在 context 中访问的知识都不存在。 存放在 Slack 对话、Google Docs、人脑里的知识,对 agent 来说是透明的——除非你主动把它物化到 agent 可触及的地方。
最可靠的做法是把知识物化到代码仓库中——版本化的、可审查的、可测试的。仓库就是唯一的事实来源(single source of truth)。
这意味着:如果你希望 agent 遵守某条规则,写在 Confluence 里没用,写在仓库里的文档里才有用。
入口文件:给 Agent 一张地图,而非一本百科全书
教训:一个大文件为什么失败
OpenAI 最早尝试的方案是"一个大 AGENTS.md"——把所有指令塞进一个文件。结果可以预见地失败了,原因有三:
- Context 是稀缺资源。 巨大的指令文件挤占了任务描述、代码和相关文档的空间,导致 agent 遗漏关键约束或优化了错误的方向。
- 当所有东西都"重要"时,什么都不重要。 Agent 从全局模式匹配退化为局部模式匹配。
- 单体手册会立即腐烂。 过时的规则和当前规则混在一起,agent 无法分辨。
HumanLayer 团队的研究也发现了一个关键细节:Claude Code 在注入 CLAUDE.md 时会附加一条系统提示——“这些上下文可能与你的任务相关也可能不相关,除非高度相关,否则不要回应。“这意味着 CLAUDE.md 里与当前任务无关的内容越多,agent 越可能整体忽略你的指令。
最佳实践:短入口 + 渐进式披露
OpenAI 最终的方案是:一个约 100 行的 AGENTS.md 作为入口,它本质上是一张地图,指向更深层的文档。
Anthropic 官方文档的建议也完全一致:运行 /init 生成一个起始 CLAUDE.md,然后持续精简。内容应包括 bash 命令、代码风格和工作流规则——那些 agent 无法从代码本身推断出的持久上下文。
业界共识是 CLAUDE.md / AGENTS.md 控制在 300 行以内,越短越好。HumanLayer 自己的根 CLAUDE.md 不到 60 行。
入口文件应该包含:
- 项目一句话描述 + 技术栈(具体到版本:“React 18 + TypeScript + Vite + Tailwind CSS”,而非"React 项目”)
- 可复制粘贴的构建/测试/lint 命令(
npm run test、npm run build等) - 项目结构概览(“src/ 放应用代码,tests/ 放测试,docs/ 放文档”)
- 绝对边界(agent 绝不能触碰的东西——密钥、vendor 目录、生产配置)
- 指向深层文档的导航链接(“架构详见 docs/architecture.md”)
一个好的入口文件读起来应该像新员工第一天收到的 onboarding checklist,而不是公司全部制度汇编。
文档分层:OpenAI 的知识库结构
OpenAI 在 Harness Engineering 实践中,将仓库内文档组织成了一个分层目录结构:
AGENTS.md ← 目录索引(约 100 行)
ARCHITECTURE.md ← 顶层领域地图
docs/
├── design-docs/ ← 经索引和验证的架构决策
├── exec-plans/
│ ├── active/ ← 进行中的执行计划
│ ├── completed/ ← 已完成的执行计划
│ └── tech-debt-tracker.md
├── generated/
│ └── db-schema.md ← 自动生成的参考文档
├── product-specs/ ← 产品规格
├── references/ ← 外部参考资料
└── ...
这个结构体现了几个关键设计原则:
① 渐进式披露(Progressive Disclosure)。 Agent 从一个小而稳定的入口开始,被告知"下一步去哪找”,而不是一次性被信息淹没。OpenAI 的原话是:active plans、completed plans 和已知技术债都版本化并共存于仓库中,使 agent 无需依赖外部上下文就能工作。
② 执行计划也是文档。 传统软件工程把规划状态放在 Jira、Confluence、Slack 里。在 agent-first 开发中,这是根本性的架构缺陷——agent 接触不到 context 外的信息。OpenAI 团队把执行计划当作版本化的仓库 artifact。后续任务的 agent 可以推理出先前任务的决策、理由和当前状态。
③ 文档的维护也是自动化的。 专用的 linter 和 CI 任务验证知识库是否最新、交叉引用是否正确、结构是否合规。一个定期运行的"文档清理 agent"扫描陈旧或过时的文档,并发起修复 PR。这就是用 agent 维护给 agent 看的文档。
值得注意的是,OpenAI 主仓库目前有 88 个 AGENTS.md 文件——每个主要子系统一个。这不是偶然,而是刻意的设计:保持指令的局部性和最小化。
Anthropic 的方案:为跨会话 Agent 设计文档
Anthropic 从另一个角度切入了同样的问题。他们在 Effective Harnesses for Long-Running Agents 中描述了一个核心挑战:agent 在离散会话中工作,每个新会话都不记得之前发生了什么——就像轮班的工程师,每个人到岗时对之前的班次毫无记忆。
他们的解决方案是一个双 agent 架构:
Initializer Agent(首次运行) 建立环境基础设施:
feature_list.json——200+ 个细粒度特性(全部标记为 “failing”),使用 JSON 而非 Markdown,因为 agent 更不容易不当修改 JSON 格式的结构化数据init.sh——一键启动脚本claude-progress.txt——进度日志- 初始 git commit
Coding Agent(后续每次运行) 的固定起手式:
- 读 git log 和 progress file,理解当前状态
- 运行 dev server 和端到端测试
- 选择一个 feature 实现
- 提交有描述性的 commit message
- 更新 progress file
关键洞察:外部 artifact 成为 agent 的记忆。 Progress file、git history 和结构化的 feature list 跨会话持久化。每个 agent 会话在开始工作前先从这些 artifact 重建上下文。
这给文档设计带来了一个重要启示:文档不仅是"规则手册",还应该包含状态追踪文件——让 agent 知道"当前进展到哪了",而不只是"应该怎么做"。
每类文档的职责与写法
综合 OpenAI、Anthropic 和社区的实践,项目文档可以分为以下几类,每类有不同的职责和写法原则:
1. 入口文件(AGENTS.md / CLAUDE.md)
职责: 地图和导航。告诉 agent 项目是什么、关键命令有哪些、去哪里找详细信息。
写法原则:
- 控制在 100-300 行
- 命令优先——可复制粘贴的 bash 命令比描述性文字有用得多
- 用实际代码示例展示风格,而非用文字描述风格。一个真实的代码片段胜过三段文字描述
- 明确写出绝对边界——“绝不提交密钥"是被证明最有效的单条约束
2. 架构文档(ARCHITECTURE.md / docs/architecture.md)
职责: 定义系统的分层规则、依赖方向和模块边界。
写法原则:
- 明确定义层级和依赖方向(如:Types → Config → Repo → Service → Runtime → UI)
- 这些约束必须同时被 linter 机械化执行——文档是给 agent 读的"软约束”,linter 是"硬约束"
- 当 linter 报错时,error message 本身应该包含修复指引——error message 就是 agent 的"教学时刻"
OpenAI 的做法是用自定义 linter(由 Codex 自己生成)和结构测试来执行这些规则。他们强调:在人类优先的工作流中,这些规则可能显得过于死板;但在 agent 优先的环境中,它们成为效率倍增器——一旦编码,就在所有地方同时生效。
3. 编码规范(docs/conventions.md)
职责: 命名约定、代码风格、Git 工作流。
写法原则:
- 用"展示"而非"讲述"——提供真实的代码片段作为范例
- Git 工作流要具体:分支命名格式、commit message 格式、PR 要求
- 指明 agent 应该优先使用的共享工具包,而非让它自己写 helper——集中管理不变量
4. 状态追踪文件(进度日志、feature list)
职责: 让新会话的 agent 快速理解"当前进展到哪了"。
写法原则:
- 使用 JSON 格式而非 Markdown(Anthropic 发现 agent 更不容易不当修改 JSON)
- 每次会话结束时由 agent 更新
- 配合 git commit history 使用——描述性的 commit message 本身就是最好的进度文档
5. 设计决策记录(ADR / Design Docs)
职责: 记录"为什么"——为什么选了 pgvector 而不是 Pinecone,为什么认证流程这样设计。
写法原则:
- 编号索引,便于 agent 按需查阅
- 包含决策的上下文、考虑过的替代方案和最终理由
- 版本化,让后续 agent 可以推理出先前的决策链
6. 子模块文档(各子目录的 AGENTS.md)
职责: 局部上下文。Agent 工作在 backend/ 目录时,只需要看到后端相关的约束。
写法原则:
- Agent 会自动读取目录树中最近的文件,最近的优先
- 子模块文档可以覆盖根文档的规则
- 保持局部性——只放该子模块特有的信息
反模式:文档怎么写会让 Agent 变差
综合多个团队的踩坑经验,以下做法会显著降低 agent 表现:
① 信息过载。 研究已证实"指令诅咒"现象:指令堆积越多,模型遵循每条指令的性能下降越严重。多个团队独立发现,当 context 利用率超过约 40% 时,性能就开始退化。过量的工具、冗长的文档和累积的历史记录会让 agent 变差而非变好。
② 规则互相矛盾。 一份说"用 Tailwind",另一份说"用 CSS Modules"。Agent 遇到矛盾信息时,行为变得不可预测。
③ 过时信息没有清理。 创建文档容易,维护文档才是真正的挑战。一个看起来完整的 CLAUDE.md 可能在生成几周后就开始说谎——项目结构变了,技术栈升级了,约定改了,但文档没跟上。Anthropic 内部团队的经验是:CLAUDE.md 越准确,Claude Code 表现越好。
④ 用描述代替示例。 “请使用函数式组件"不如直接贴一个符合要求的组件代码。Agent 从模式匹配中学习,真实代码是最强的模式信号。
⑤ 把技术文档放在仓库外部。 外部 API、库或框架的文档应该存放在代码旁边。Agent 搜索外部资源时经常因版本问题失败。把关键参考文档内嵌到仓库中。
文档维护:最难的部分
几乎所有实践者都强调同一个观点:引导上下文的初始创建不是挑战,维护才是。
运行 /init 几秒钟就能生成一个 CLAUDE.md。这创造了一种完整性幻觉——文件存在、有内容、看起来很专业。但它可能在几周内就开始腐烂。
推荐的维护策略:
① 文档即代码。 把文档纳入 CI 验证。OpenAI 用 linter 和 CI 任务验证文档是否最新、交叉引用是否正确。
② 用 Agent 维护给 Agent 看的文档。 OpenAI 运行定期的"文档清理 agent”,扫描不反映真实代码行为的过时文档并发起修复 PR。这就是用自动化对抗文档的熵增。
③ 把 spec 当"活文档"。 当你和 agent 做出决定或发现新信息时更新它。如果数据模型变了或功能被砍了,在文档中反映出来。
④ PR review 时检查文档一致性。 每次代码变更的 PR 都应该问:“这个变更是否需要更新相关文档?“最好用 CI 自动检查。
一个可落地的起步方案
如果你现在想开始实践,不需要一步到位搭建 OpenAI 那样的 88 文件体系。从最小可行方案开始:
第一周: 创建或精简你的根 CLAUDE.md / AGENTS.md。确保它包含项目描述、技术栈、关键命令和绝对边界。控制在 100 行以内。
第二周: 把架构规则抽到 docs/architecture.md。在入口文件中链接过去。如果你有明确的分层规则,配一个最基本的 linter 来执行。
第三周: 如果项目跨多个模块,在主要子目录放置局部 AGENTS.md。只包含该模块特有的上下文。
持续: 每当 agent 犯了一个你不希望它再犯的错误,问自己:缺少什么文档或约束?然后把修复编码进仓库。这就是 harness engineering 的核心循环。
Mitchell Hashimoto(Terraform 创始人)对此的总结最为精确:“每当你发现 agent 犯了一个错误,你就花时间设计一个方案,使 agent 永远不会再犯那个错误。这就是 Harness Engineering。”
总结
| 原则 | 来源 | 要点 |
|---|---|---|
| Agent 看不到的就不存在 | OpenAI Harness Engineering | 仓库是唯一事实来源 |
| 地图而非百科全书 | OpenAI, Anthropic, HumanLayer | 入口文件 ≤ 300 行,指向深层文档 |
| 渐进式披露 | OpenAI, AGENTS.md 标准 | 按需加载,不一次性灌满 |
| 展示而非讲述 | Addy Osmani, 社区共识 | 代码示例 > 文字描述 |
| 机械化执行 | OpenAI Harness Engineering | 文档是软约束,linter 是硬约束 |
| 状态也是文档 | Anthropic Long-Running Agents | JSON 进度文件 + git history |
| 用 Agent 维护 Agent 的文档 | OpenAI “doc-gardening” agent | 自动化对抗文档熵增 |
| 维护比创建重要 | Packmind, 社区共识 | 过时的文档比没有文档更危险 |
最后一句话: 更好的模型让 harness engineering 变得更重要而非不重要。更强的模型解锁更大的自主性,更大的自主性需要更好的护栏。你为 agent 构建的文档体系,就是这些护栏中最基础的一层。
参考来源:
- OpenAI, “Harness Engineering: Leveraging Codex in an Agent-First World”, 2026.02
- Anthropic, “Effective Harnesses for Long-Running Agents”, 2025.11
- Anthropic, “Best Practices for Claude Code”, 2026
- AGENTS.md 标准 (agents.md), Linux Foundation
- Addy Osmani, “How to Write a Good Spec for AI Agents”, 2026.02
- Martin Fowler / Birgitta Böckeler, “Harness Engineering”, 2026.02
- HumanLayer, “Writing a Good CLAUDE.md”, 2025.11
- Marmelab, “Agent Experience: Best Practices for Coding Agent Productivity”, 2026.01