如何写好 AGENTS.md
引子:AGENTS.md 是什么
在仓库根目录放一个 Markdown 文件,告诉 AI Coding Agent 这个项目是什么、怎么构建、有哪些规矩。这个做法现在有了一个事实标准的名字——AGENTS.md。
它的角色是:README.md 给人类读者看,AGENTS.md 给 AI 读者看。前者聚焦快速开始与贡献指南,后者聚焦构建命令、编码约束、验证闭环、踩坑清单,覆盖任何会影响 Agent 产出正确性的上下文。
这个概念最初由 Anthropic 的 Claude Code 以 CLAUDE.md 形式普及。随后各家工具一度各走各路:Cursor 用 .cursor/rules/*.mdc,Copilot 用 .github/copilot-instructions.md,Gemini CLI 用 GEMINI.md,Cline 用 .clinerules,Sourcegraph Amp、OpenAI Codex、Cursor、Factory、Jules(Google)等团队联合推出 AGENTS.md 作为通用入口。这场标准之争最终在 OpenAI 主导的格式上收敛——agents.md 域名指向当前规范,Linux Foundation 下属的 Agentic AI Foundation(AAIF,执行董事 Mazin Gilbert,与 MCP、Goose 同级)作为标准 steward。截至 2026 年 5 月,agents.md 主页统计 GitHub 上已有超过 6 万个开源项目使用这一格式,OpenAI Codex 自己的仓库就有 88 份按子项目就近放置的 AGENTS.md。Cursor、Aider、goose、opencode、Zed、Warp、Windsurf、Devin、JetBrains Junie、UiPath Autopilot、GitHub Copilot Coding Agent、Augment Code 等主流工具均已原生识别。Claude Code 仍以 CLAUDE.md 为主,但自 v2.107(2025 年 5 月 9 日)支持 @path/to/file.md 引用语法之后,CLAUDE.md 里只需一行 @AGENTS.md 就能完成桥接,迁移成本几乎为零。
历史脉络和段落顺序不是 AGENTS.md 真正值得讨论的地方。真正值得讨论的问题只有一个:为什么一份几百行的 Markdown,能显著改变 AI Coding 的产出质量? 答案藏在一条设计原则里:地图,而非手册。
核心设计原则:地图,而非手册
OpenAI 在 Harness Engineering 实践中把 AGENTS.md 的第一原则命名为「Map, not Manual」。Anthropic 的官方博客在 Skill 设计中也重复了同一条原则:渐进式披露(progressive disclosure)。两家把不相容的工具做到相容点上,背后的机制是同一个:大模型的注意力是有限资源,上下文窗口越大,注意力被稀释得越严重。
注意力为什么是有限资源
「Lost in the Middle: How Language Models Use Long Contexts」(Liu et al., TACL 2024,arXiv 2307.03172)给出过一个反直觉的数据点:在 20 篇文档的多文档问答任务里,把答案文档放在中间位置,准确率比放在首尾掉超过 30%。这条 U 形曲线在所有主流长上下文模型上都能复现,包括那些标榜支持几十万 token 的版本。
最近的工程实测把这条规律推得更远。一篇 2026 年的 monitor 性能评测显示,Claude Opus 4.6(开 thinking)在 100K token 转录中插入对抗指令,靠近开头的 recall 是 99.7%,移到深处之后掉到 69%。Gemini 3 标称 2M、Claude 4 标称 1M、GPT-5 标称 400K,但在 needle-in-a-haystack 测试里,几乎所有前沿模型在大约 32K 之后都会快速劣化。
这意味着「上下文窗口大」不等于「真的能用上这么大」。一份 5000 行、事无巨细的 AGENTS.md,把关键约束和普通说明同等推进窗口里,关键约束反而被淹没。一份 200 行的 AGENTS.md,只标注「要做 X 就去看 Y 文档,要写 Controller 就去看 Z 目录」,模型按需跳转,注意力花在真正当前任务相关的那一小块。
Anthropic Skills 把这一点工程化得更彻底:每个 Skill 是一个目录,分三层加载——session 启动只载入 frontmatter 元数据让模型知道有什么;正文 SKILL.md 只在被判断相关时再装进上下文;references/、assets/、scripts/ 推迟到执行需要时才取。AGENTS.md 是 flat-file,做不到三层精细切分,但思路是同一个:把上下文当成稀缺资源来分配,而不是当成无限堆放的仓库。
一刀切的判断标准
这条原则推导出了一个判断标准:
这条标准把「该写什么」和「不该写什么」一刀切干净。分层架构的依赖方向、异常处理的强制约定、响应体由框架统一包装,违反就直接跑不通或留下隐患,必须进 AGENTS.md。某个 Service 内部的调用顺序、某个组件 prop 的推荐写法,错了可以改,属于详细文档的领域。
反过来看,有几类东西不应该进 AGENTS.md,即便它们看起来重要:
- 能机械检查出来的。让 lint 脚本说话,AGENTS.md 只放命令入口(如
make lint-arch)。把规则同时写在 AGENTS.md 和 lint 里,迟早会两边对不上,对不上时 Agent 该信谁? - 极少触发的边界。一年用一次的特殊路径,留在 design doc 里,AGENTS.md 提一句「特殊场景见 docs/edge-cases.md」即可。
- 个人偏好和临时调试笔记。这些应该流向工具的 user-level 配置(如
~/.claude/CLAUDE.md)或者 PR 评论,混进项目级 AGENTS.md 反而误导新成员。 - secrets、PII、内部链接的明文。AGENTS.md 进 Git,进 Git 就会被各种工具 index、缓存、训练。任何敏感值用
${ENV_VAR}引用,AGENTS.md 只声明依赖关系。
一组先行的场景
在展开具体实践之前,先看一组没有 AGENTS.md 时 AI Coding 的典型失败模式。它们解释了为什么 AGENTS.md 不是可有可无的装饰,而是工程化使用 AI Coding 工具的基础设施。
上下文割裂。前后端分属两个 Git 仓库时,AI 工具一次只能看到一半。改一个前后端联动的功能,比如后端新增接口、前端调用这个接口,需要在两个窗口之间来回切换。每次切换,模型就丢掉上一轮的上下文。
私域组件不可见。训练数据里没有的闭源组件(内部组件库、私有 SDK、商业框架),AI 既不认识也查不到文档。写出来的代码要么编译不过,要么 prop 传错,要么漏掉必要配置。
规矩活在人脑里。每个项目都有自己的潜规则:异常必须通过 BusinessException 抛出、响应体禁止手动构造、Controller 不得直接注入 Repository。这些规矩写在团队成员的默契里,不写下来 AI 就反复违反,每次纠正完下次还犯。
验证闭环断裂。AI 改完代码不知道怎么构建、怎么启动、怎么自测。本地环境配置、启动命令、验证方式散落在聊天记录和个人脚本里。AI 只能把代码改完就停下,剩下的人来接手。这意味着 Agent 无法夜间自主执行:连项目都启动不起来,谈不上自主闭环。
跨会话失忆。Agent 每开一个新会话就回到出厂状态。上一轮花了二十分钟摸清楚的目录布局、踩过的兼容性坑、定下来的命名约定,下次进来全部归零。模型本身没有「这个项目我熟」的能力,只有看到 AGENTS.md 那一刻才能瞬间穿越回相同的认知水位。
工具规则矩阵不同步。团队里同时存在用 Cursor 的、用 Claude Code 的、用 Copilot 的、用 Codex 的成员。每个人维护各自的 .cursor/rules/、CLAUDE.md、.github/copilot-instructions.md、AGENTS.md,规则慢慢漂移成不一致的几份。新人入职打开仓库被四五份说明文件淹没,反而不知道该信哪个。
这六种失败模式背后是同一个根因:项目的知识与约束存在于人脑或散落的角落,不存在于 AI 能读到的统一位置。AGENTS.md 就是把这些隐性知识外化、并收敛到唯一入口的那个载体。
五类实践:让 AGENTS.md 真正起作用
AGENTS.md 自己一份是不够的,它需要周边基础设施配合。下面五类实践来自在多个真实项目(Spring Boot + React 的全栈管控系统、C++ 内核引擎、产品基线、文档系统)里收敛出的共同经验。
实践一:仓库聚合,消除上下文割裂
前后端分仓的项目,最直接的改造是把前端仓库放进后端的子目录下,或者进一步重构为 monorepo。两种方案的代价不同,收益方向一致:让 AI 在一个窗口里同时看到 Controller 定义和对应的前端调用。
脚本聚合是成本较低的折中:一个 setup-repos.sh 把前端仓库 clone 到 frontend/ 下,.gitignore 里把 frontend/ 屏蔽掉,不影响后端 CI/CD,不用 AI 工具的同事完全无感。monorepo 是更干净的选择:前后端代码、用户手册、参考项目、构建脚本、文档在同一棵目录树下。
1 | |
把用户手册也放进来有个副作用:AI 改完功能代码后可以顺手把对应的用户文档也更新掉。文档和代码在同一次 commit 里共进退,文档滞后问题自然消失。
聚合方案的两个常见顾虑值得一起回答。仓库变大,clone 时间是不是会爆炸? 用 git submodule 的 ignore = all 与按需 git submodule update --init <path>,参考项目可以延迟到真正要看时再拉。前端独立 CI/CD 怎么办? 子目录方案下前端仓库依然是独立的 git 仓库,独立 push/PR/部署,只是被本地 mount 进了后端工作区——这是一个本地视图问题,不是版本管理问题。pnpm workspaces / yarn workspaces 之类的 monorepo 工具同样可以服务这个布局。
实践二:环境配置归一,让 AI 能启动项目
AI 无法验证产出的根本障碍往往不在于 AI 不会验证,而在于验证所需的环境配置散落在每个人的 .bashrc、IDE JVM 参数、临时 export 里。AGENTS.md 只要无法指向一个明确的配置文件,Agent 就没法自主启动项目。
可行的约定是:所有本地环境变量统一写在 ~/.<project>_env,纯 KEY=VALUE 格式,启动脚本自动 source。放在 ~ 下而不是项目目录的理由是避免误提交到 Git。AGENTS.md 明确写清楚优先级:
1 | |
配套一键启动脚本:
1 | |
JDK 检测、优雅关闭旧进程、健康检查轮询这些细节被封装在脚本里,AGENTS.md 只暴露命令。Agent 的认知负担被压到最低:不需要理解 nvm、fnm、JAVA_HOME 的关系,只需要知道「要启动后端就跑这个脚本」。
这条实践和 12-Factor App 的 Config 原则方向一致,但有重要差别:12-Factor 服务于云上部署,强调环境变量从外部注入;AGENTS.md 服务于本地开发与 Agent 自动化,强调启动入口的单一与默认值的可发现。两者并不冲突——~/.<project>_env 在本地补全了云上由 Secret Manager 注入的那部分,但仍然 export 成环境变量,进程拿到的接口是同一个。direnv / .envrc 是另一种风格,缺点是依赖额外工具,Agent 在不知道这个工具存在时会找不到入口;统一脚本风格的好处是它对 Agent 的可见性是闭合的——AGENTS.md → 脚本 → 进程,链路里没有黑盒。
实践三:验证闭环,改完代码不算完
验证闭环是 AGENTS.md 实践里最容易被低估的一环。它直接决定了 Agent 的产出是「看起来做完」还是「真的跑通了」。
后端的验证主力是 curl。一个可靠的 curl 验证规范有几条硬约束:每个 curl 独立执行,不串联;响应写到 /tmp/ 下的临时文件,后续用 python3 独立解析;token 获取模板化,登录写文件、提取、后续请求携带。这套啰嗦是有原因的。Agent 在 shell 里执行命令时容易踩到兼容性坑,例如 zsh 下管道加方括号 glob 会炸,curl | python3 -c "print(data['key'])" 直接报错。临时文件中转多一步,稳定性高一个量级。
1 | |
前端的验证则要靠 Agent Browser。curl 看不到页面渲染、交互、布局问题,调试前端疑难杂症时需要让 Agent 自己打开浏览器、操作页面、截屏对比(Qoder 的 agent-browser、Claude Code 接入的 computer use 都提供这个能力)。这比让 Agent 凭空猜 CSS 问题要可靠得多。
验证闭环的完整形态是:lint 和格式检查在每次代码变更后自动触发,启动脚本把应用真正拉起来,curl 或 Agent Browser 跑接口/页面验证,Spec 的 Design 文档里明确写入验证方案。最后这一点尤其关键,它告诉 Agent「写完代码不算完,自测过功能才算完」。这套端到端验证是夜间自主执行能跑通的前提。睡前设计好 Spec 提交给 Agent,第二天早上验收结果,是只有在闭环完整时才成立的工作模式。
更进一步的方向是把验证本身也基础设施化。一种做法是写出一份 harness/config/environment.json,由 AGENTS.md 指向它:里面声明启动命令、依赖服务、必需环境变量、关键功能场景;每次任务结束由「verifier 子 Agent」基于环境契约和本次改动动态生成 verify.json,跑一遍冒烟。这种 environment.json 与 verify.json 分离的模式来自 OpenAI Harness Engineering 的实践,好处是验证策略不需要每次手写——你定义一次环境,验证逻辑在每次任务时按上下文重新生成。
另一个值得提的方向是 eval 化:把每次出现过的 bad case 留下来作为 eval task。验证闭环不只是「这次跑通了」,而是「这次跑通的能力下次还在」。
实践四:自动化检查,给规则装上执行力
AGENTS.md 里写的规则,如果没有自动化检查,AI 和人都会违反。规则的优先级天然是:能自动化检查的 > 写在 AGENTS.md 中的 > 口头约定的。
典型例子是分层依赖检查。项目里定义严格的层级约束:
1 | |
光把这段贴进 AGENTS.md 是不够的。需要一个 shell 脚本扫描所有 Java 文件的 import 语句,按包路径判断层级,检测是否违反依赖方向。违规时输出的错误信息必须按 WHAT / WHY / HOW 三段式组织:
1 | |
这三段不只是给人看的,更是给 AI 看的。Agent 读到这条错误信息后可以直接按 HOW 的指引去修,不需要额外上下文。集成到 make lint-arch,一条命令完成检查。改完代码 Agent 自己跑一遍检查,形成「改 → 检 → 修」的闭环。
错误信息的 agent-actionable 工艺值得单独说一句。同样是层级违规,下面两种写法对 Agent 的价值差一个数量级:
1 | |
第一种 Agent 看完只知道「错了」,会进入瞎试;第二种 Agent 直接挑选选项 1/2/3 之一执行。差别不在 lint 写得有多复杂,而在你愿不愿意把「为什么」和「怎么修」也写进去。
通过 Makefile 把质量检查命令收敛成统一入口:
1 | |
Agent 不需要记住每个检查命令的具体写法,AGENTS.md 只暴露 make lint-arch 和 make lint-format。
这一条还有一个被忽视的延伸:把架构图也机械化生成。Mermaid 包依赖图、组件关系图、序列图都可以由 go list -json ./... 之类的导入分析自动产出,AGENTS.md 里写图本身没有意义——写「这张图由 make arch-diagram 生成」才有意义,因为这意味着图永远不会和代码失同步。
实践五:引入参考项目源码,替代永远滞后的文档
这一条是反直觉但效果最显著的一条。AI 不认识的东西——闭源私域组件、内部网关内核、公有云项目、竞品架构——靠写使用文档补上,成本高、覆盖不全、还总是滞后于实现。换一个思路:不写文档,直接把源码引进来。
1 | |
每个参考项目通过 git submodule 引入,配合 ignore = all 避免影响 CI/CD。本地按需拉取:
1 | |
源码永远不会过时,它本身就是最准确的文档。 AI 不会写私域组件时,直接读源码里的 TypeScript 定义和实现;要对接网关内核时,直接查看路由和插件的实际代码。代价是仓库体积变大和 submodule 的管理负担,换来的是 Agent 写代码的准确性。对于训练数据中不存在的内部项目,这个交易划算。
仅有源码还不够。每个参考项目配一份架构说明文档(docs/design-docs/ref-*.md),作为参考项目的地图:
| 文档 | 说明 |
|---|---|
ref-higress.md |
网关内核:路由模型、插件机制、CRD 结构 |
ref-nacos.md |
Nacos:配置中心对接、服务发现集成 |
ref-teamix-pro.md |
Teamix Pro:ProTable/ProForm 使用模式、TS 类型速查 |
ref-apigo.md |
公有云后端:目录结构、分层架构、核心模块 |
ref-apigw.md |
公有云前端:页面结构、组件体系、路由设计 |
ref-himarket.md |
HiMarket:多模块结构、领域模型 |
ref 文档告诉 Agent「这个参考项目的整体结构和关键模块在哪」,reference-projects 提供细节。这些 ref 文档本身也可以由 AI 基于参考项目源码生成,又一个「代码生成文档」的闭环。生成 prompt 大致是「读 reference-projects/<name>/ 下的目录结构与几个核心文件,产出一份不超过 200 行的 AGENTS.md 风格地图,标注每个核心模块的入口位置和关键接口」,跑一遍即可。
引入这么多参考仓库会不会让 Agent 无所适从?实测下来不会。AGENTS.md 的项目结构树标注了每个目录的用途,ref 文档提供架构概览,参考优先级规则明确「什么时候该看哪个项目」。现在的大模型知道什么时候该去参考项目里翻实现,什么时候该在本项目里改动,不会因为仓库里多了几个参考项目就迷失方向。
AGENTS.md 的骨架
把上面五类实践沉淀成一份 AGENTS.md,大致的章节结构是这样的:
1 | |
控制在 200 行以内。超过这个范围说明有细节该拆到 docs/ 下的专题文档里。
为什么是 200 行而不是 500、不是 1000?回到前面 Lost-in-the-Middle 的曲线——一份 200 行的 AGENTS.md 配合现代模型,几乎全部落在「首尾区间」,每条规则都能被注意到;500 行就开始有相当一部分内容滑入中段衰减区;1000 行以上,关键规则的命中率和写在某处源码注释里没有本质差别。这是一个工程取舍,不是审美偏好。
每个一级标题加序号(## 1. 项目概述 而不是 ## 项目概述),是为了让 detail 文档在跨文档引用时有稳定 anchor:docs/architecture.md 里写 “依赖方向参见 AGENTS.md §5” 就不会因为顺序调整而失效。
子项目嵌套是另一个关键技巧。OpenAI Codex 自己的仓库里有 88 份 AGENTS.md,每份对应一个子项目目录,最近原则生效——Agent 在 packages/foo/ 下工作时优先读 packages/foo/AGENTS.md,再叠加根目录的全局 AGENTS.md。这套就近原则把项目根的全局规则和子项目的具体细节解耦:根 AGENTS.md 不必为每个子项目维护章节,子项目的 AGENTS.md 也不必重复全局约定。前提是工具本身支持就近读取——Codex 和 opencode 原生支持,Claude Code 通过 CLAUDE.md 的目录树机制天然就有,Cursor 用 .mdc 的 glob 实现类似效果。
AGENTS.md 与同类文件的兼容关系
虽然 AGENTS.md 在收敛成事实标准,但每个工具仍有自己的偏好与扩展。理解这些差异,决定了一份 AGENTS.md 能不能在多种工具下都生效。
| 工具 | 默认文件 | 加载方式 | 嵌套语义 |
|---|---|---|---|
| OpenAI Codex / opencode | AGENTS.md |
自动;最近原则 | 多级嵌套,子目录覆盖父目录 |
| Claude Code | CLAUDE.md(默认) |
自动;从 cwd 向上层走目录树拼接 | 支持 @path/to/file.md 引用(v2.107+) |
| Gemini CLI | GEMINI.md |
自动;项目级 | 单一项目根 |
| GitHub Copilot | .github/copilot-instructions.md |
自动 | 单文件 |
| Cursor | .cursor/rules/*.mdc(也读 AGENTS.md) |
部分自动、部分按 glob 匹配 | 规则按 glob 作用域 |
| Aider | AGENTS.md |
自动 | 项目根 |
| Hermes-agent | AGENTS.md 全部子目录组合 + SOUL.md 总是加载 |
自动 | 全部组合 |
几个值得注意的细节:
- Codex / opencode 把 AGENTS.md 当作 system prompt 直接拼进上下文,最近的覆盖最远的;这意味着「每个子目录写自己的小 AGENTS.md」是被原生支持的工作模式。
- Claude Code 默认读 CLAUDE.md,不读 AGENTS.md。最干净的兼容方案是 CLAUDE.md 里只写一行
@AGENTS.md,让 Claude Code 通过@import把 AGENTS.md 当成内容引入。这条 import 是 v2.107(2025-05-09)才加上的,更早的 Claude Code 需要用软链ln -s AGENTS.md CLAUDE.md来桥接。 - Cursor 的
.mdc规则系统更复杂——可以按文件 glob 设置作用域、也可以标 always-apply。Cursor 也会读 AGENTS.md,但语义上和.mdc不完全等价;如果 Cursor 是团队主力,把核心约定放.mdc里、把通用项目地图放 AGENTS.md,是比较稳的写法。 - Copilot 的
.github/copilot-instructions.md是单文件、单作用域、自动加载。把它配置成「include AGENTS.md 内容」是一种实践,但 Copilot 本身不支持@import,只能复制粘贴或用脚本 sync。
实操层面,团队最少需要做三件事:
- AGENTS.md 是源。把项目级所有约束、命令、文档导航写在这里。
- 其他工具的入口文件作为薄壳。CLAUDE.md =
@AGENTS.md;GEMINI.md 同;.cursor/rules/main.mdc写一段引用。 - 承认 Copilot / Cursor 的扩展能力。如果团队真的依赖 Cursor 的
.mdcglob 作用域或者 Copilot 的特定语法,那它们是 AGENTS.md 之外的补充而不是替代——补充在工具特定文件里,绝不复制规则文本,复制就埋下漂移。
记忆层级是另一个值得对照的概念。Claude Code 提供四层记忆:Enterprise managed policy → User Global(~/.claude/CLAUDE.md)→ Project(./CLAUDE.md)→ Local 嵌套,加上 @import 递归。AGENTS.md 模型故意放弃了这种层级——它不区分 user global 和 project,所有内容都进项目仓库。这是一个有意识的取舍:单文件、可移植、可被任何工具读到,代价是没法表达「我个人偏好用 vim 风格快捷键」这种用户级配置。后者本来也不该写进项目共享文件,留给工具的 user-level 配置即可。
AGENTS.md 与 Skill / Slash command 的取舍
Anthropic 在 2025 年 10 月推出 Skills,把 AI 助手的「能力」做成可独立分发的目录,引出了一个新问题:什么应该写进 AGENTS.md,什么应该做成 Skill?
两者的根本差别是加载时机:
- AGENTS.md 永远在场。每次会话启动,工具把 AGENTS.md 内容拼进 system prompt 或上下文头部。它是「项目是什么样子」的常驻说明。
- Skill 按需加载。Anthropic Skills 用三层渐进式披露——session 启动只载入 frontmatter 元数据(一行 description),SKILL.md 正文要等模型判断「这个 skill 跟当前任务相关」时才加载,
references/与scripts/推迟到执行需要时才取。一个仓库可以挂几十个 Skill,绝大多数永远不会被加载,token 成本接近零。
这条加载差异决定了归属判断:
| 内容 | 应该在哪 | 原因 |
|---|---|---|
| 项目结构、技术栈、构建命令 | AGENTS.md | 每个任务都要用 |
| 分层架构约束、命名规范 | AGENTS.md | 永远开 |
| 常用 lint / build / test 入口 | AGENTS.md | 高频 |
| 验证 PR 是否准备好合并 | Skill | 只有在「我做完了」这种节点用 |
| 把 Markdown 报告渲染成 PPTX | Skill | 偶发任务 |
| 跑一份安全审计 | Skill | 按场景触发 |
| 把日志切片再喂给一个分析子 agent | Skill | 工作流式、需要 scripts |
| 团队特定的 git commit message 风格 | 可两可——日常用就 AGENTS.md,特殊场景才用就 Skill | 看频率 |
一条简单的判断启发:如果省略它会立刻写出错代码,进 AGENTS.md;如果只是某些任务需要的 workflow / 工具组合,进 Skill。
Skills 的另一个好处是可独立版本与可分发。harness-creator、pdf-extractor、security-reviewer 这种通用能力做成 Skill 之后,可以跨项目复用;AGENTS.md 是项目自己的描述,没有跨项目复用的语义。社区已经出现 SKILL.md 包目录、Skill marketplace 等基础设施,把 AGENTS.md 也朝这个方向推不太合适——AGENTS.md 越通用化越没用,它的价值恰恰在于"对这个项目而言"。
Slash command 是 Skill 的一种轻量形态:固定流程、用户主动触发,不依赖模型判断相关性。当一个流程足够刚性、又总是由人类发起时,Slash command 比 Skill 干净。
怎么开始写
从零写一份 AGENTS.md 的门槛比想象中低。
第一种起步方式:大多数 AI Coding 工具提供 /init 或等价命令(Claude Code 的 /init、Qoder 的 qoder init),扫描项目结构生成初始版本。自动生成的版本覆盖项目概述和基本构建命令,作为骨架够用。
第二种起步方式:用更完整的 Skill 起步。社区里有几个开源的 harness-creator 风格 Skill,能一次性生成 AGENTS.md、分层架构 lint 脚本、Makefile、验证脚本、参考文档骨架,相当于把本文五类实践打包成一键产出。本文末尾给出一份脱敏过、可直接拷进 ~/.claude/skills/ 或本地 Skill 目录的版本。
起步之后的迭代是 bad case 驱动 的:
- 某次 AI 用了错误的命名风格 → 思考「如果 AGENTS.md 里多一条 XX 规则,是不是就不会犯」→ 补一条
- 某次 AI 在错误的层级引入了依赖 → 是全局规则,加到 AGENTS.md;或者补一个 lint 脚本自动拦
- 某次 AI 在某个模块用错了某个 prop → 是模块细节,补到对应的
docs/文档里 - 某次 AI 改完没自测,PR 里漏了关键路径 → 是验证闭环漏洞,补
harness/config/environment.json里的 functional scenario
判断改哪里的标准始终是一条:全局规则进 AGENTS.md,模块细节进 docs,能 lint 的让 lint 说话。如果所有细节规则都往 AGENTS.md 里怼,上下文会膨胀到重要规则被淹没。
更结构化的迭代节奏是把 bad case 沉淀成两种产物:第一种是 AGENTS.md 的新规则(如果是项目级、高频、机械可识别的违规);第二种是 eval task(如果是某个具体场景,留下来作为回归测试)。两条流水线并行——AGENTS.md 防止下次同类 bad case 再出现,eval 检查这次的修复是否真的生效并守得住后续修改。
让 AGENTS.md 不腐烂
写一份 AGENTS.md 不难,难的是它一年后还有用。文档腐烂在 AI Coding 场景比传统场景更危险——一条过期规则给人类只是误导,给 Agent 就是 30 个 tool call 之后才发现走错方向。社区里几种已知的腐烂姿态:
链接腐烂。AGENTS.md 引用 docs/foo.md,文档被重命名或删除后链接失效。Agent 顺着断链走会得到 404,更糟的情况是中间还过了一层别名重定向,最后落到一个看似相关其实不对的页面。检测办法:一份 50 行的 Python 脚本扫描所有 markdown 链接,对内部相对路径用 os.path.exists 校验,外部链接用 HEAD 请求探活,CI 跑一遍。
Interface drift。AGENTS.md 写「核心接口 UserService 在 internal/core/user.go:18」,半年后 UserService 重命名为 UserManager、文件也挪到 internal/users/service.go,但 AGENTS.md 没更新。Agent 读到这条线索去找 UserService 找不到,可能就编造一个出来。检测办法:对 AGENTS.md 里出现的所有类型名 grep 代码,找不到的标记为 P0 警告。
陈旧规则压过新规则。Reddit 上一种常见抱怨:AGENTS.md 写「不能直接 import L2 包」,但项目两个月前已经决定打通 L2,AGENTS.md 没改,结果 Agent 严格遵守一条已经废弃的规则。这一种比缺信息更糟糕——比起「不知道」,「知道一条错的」更难纠偏。
100 本书塞进一个文件。AGENTS.md 涨到 2000 行,包含每个团队成员的偏好、每次 retro 的结论、所有踩过的坑。结果是没人读,Agent 也读不进去。
当成安全边界。把 “不要读 production env” 写进 AGENTS.md 是一回事,把它当作真正的访问控制是另一回事。AGENTS.md 是建议,不是 sandbox。关键约束的兜底必须在 lint、execpolicy、shell sandbox 里——harness-creator 提到的 environment.json 把所有 secret 标记为 ${VAR} 引用、绝不内联值,是一个相同思路的具体化。
对应的工程化对策:
- 链接 / interface drift 检测脚本作为 CI 的一部分。每个 PR 跑一遍,发现新增断链或类型不匹配就 fail。
- AGENTS.md 的最小行数 / 最大行数硬性预算。低于 60 行通常说明骨架未完成,高于 250 行通常说明该往 docs/ 拆。CI 里加
wc -l AGENTS.md的硬阈值。 - 维护节奏挂在 release 节奏上。每次 release 前的 review checklist 加一项:AGENTS.md 是否需要更新。比 “某天定期 review” 这种口号有用得多。
- 关键规则双写。重要约束在 AGENTS.md 写明的同时,必须在
scripts/lint-*里有机械检查兜底。前者是给 Agent 看的「为什么」,后者是给系统看的「不许做」,两者只缺一个就会出事。 - 每条进入 AGENTS.md 的规则必须能溯源。理想做法是写明「来自 PR #1234 的 retro」「来自 incident 2026-04-12」。当规则失去 context 时,半年后没人敢删。
谁来读这些文件
推广 AGENTS.md 时,明确标注每个文件的读者有助于降低团队的理解成本:
| 文件 | 读者 | 说明 |
|---|---|---|
README.md |
人 | 项目介绍、快速开始,人类入口 |
AGENTS.md |
AI 为主,人可浏览 | AI 工具自动读取的项目指令 |
docs/*.md |
AI 为主,人可参考 | 各模块的开发手册 |
scripts/*.sh |
人和 AI 共用 | 构建、启动、部署脚本 |
setup-repos.sh |
人执行 | 一键环境搭建 |
harness/config/environment.json |
AI / Verifier 子 Agent | 运行时契约:依赖、启动、env vars |
~/.claude/CLAUDE.md 或类似 user-global |
个人 | 个人偏好、不进项目仓库 |
README 和 AGENTS.md 是互补的。README 聚焦快速开始和贡献指南,AGENTS.md 聚焦构建命令、编码规范、验证流程。内容可能有少量重叠(比如项目概述),侧重点不同,不需要合并。脚本是人和 AI 共用的部分,因此脚本本身的可读性和健壮性格外重要,其中的每一行注释都可能成为 Agent 决策的依据。
为什么是 AGENTS.md
工具不统一的现状下,AGENTS.md 作为核心入口的价值来自几个方面:
- 足够通用:被大多数主流工具识别,一份文件覆盖多数场景
- 零配置成本:工具打开项目自动读取,不需要安装插件或配置 hook
- 维护负担低:不用为每种工具维护一份规则文件
- 兼容性好:不识别 AGENTS.md 的 Claude Code 可以通过
CLAUDE.md内的@AGENTS.md引用接入,迁移成本接近零 - 有标准 steward:AAIF 在 Linux Foundation 旗下托管,有 backing 而不是某家厂商的私货
和特定工具绑定的 rules、hook、Skill 作为补充,核心规则全部收敛到 AGENTS.md 一个入口。换工具时迁移成本趋近于零。
作为知识沉淀的副作用
AGENTS.md 的初衷是给 AI 看,它的维护过程本身是一次团队知识梳理。过去散落在 Wiki、聊天记录、口头约定里的编码规约,现在被结构化地写进了一份 Markdown。新人入职读完 AGENTS.md,就能拿到过去需要摸索很久的「潜规则」。给 AI 写 AGENTS.md 的过程,客观上也是给人写了一份项目使用手册。
这和 Code as Documentation 的思路一脉相承:隐性知识外化成可执行、可校验的文本,才能跨越时间和人员传承。AGENTS.md 加上 lint 脚本、启动脚本、验证规范,本质是在构建一个反馈回路:Agent 读 AGENTS.md 理解项目,写代码,自动检查,启动验证,根据结果修正。人类的角色从回路中的每一步执行者,变成回路本身的设计者。
更进一步看,AGENTS.md 标记了一种工程文化的转折:从「文档是给人看的副产品」变成「文档是给 Agent 用的主输入」。一旦文档有了机械读者,它就被迫保持准确——因为 Agent 不会自动忽略矛盾、不会主动修补遗漏,每一处不准都会在某次 tool call 里付出代价。某种意义上,AI Coding 让我们第一次有了一支严格执行 RFC 的工程团队,前提是我们愿意把 RFC 写得让它能用。
一份可参考的起步 skill
把上面所有实践打包成一键产出的工具叫 harness-creator——一个 Anthropic Skill 风格的目录,扫描你的仓库后产出 AGENTS.md、docs/ 架构骨架、scripts/lint-deps、harness/config/environment.json、Makefile、CI 模板。作者把它脱敏后放在了 claude-configurations/skills/harness-creator/ 下,可以直接 cp -R 到 ~/.claude/skills/ 用。
它的工作流大致是:Phase 1 探测项目状态(空仓库 / 已有代码 / 部分 harness / 完整 harness),Phase 2 并行跑三个分析子 Agent(架构 / 现状 / 环境),Phase 3 计算 delta,Phase 4 并行跑创作子 Agent 产出文档、lint、配置,Phase 5 跑验证。所有 prompt 模板和 reference 文档都在仓库里可读。
如果你打算自己起步而非用现成 Skill,这份目录里的 references/documentation-templates.md、references/linter-templates.md、references/environment-config-guide.md 也可以单独当作素材库参考——本文五类实践的所有具体格式(AGENTS.md 章节、Mermaid 包依赖图模板、layer linter 错误信息样式、environment.json schema)都在里面有可复制的版本。
参考资料
- AGENTS.md 官方主页
- Agentic AI Foundation 公告
- Anthropic Claude Code: Memory Management
- Anthropic Skills 介绍(2025-10)
- OpenAI Harness Engineering 实践(agents-md-best-practices)
- Liu et al., “Lost in the Middle: How Language Models Use Long Contexts”(arXiv 2307.03172, TACL 2024)
- Agent Harness Engineering: A Survey(OpenReview)
- Claude Code release notes(含 v2.107
@import) - Sourcegraph Amp AGENT.md Proposal


