写一份 AI 真会照做的 AGENTS.md:命令、边界、完成标准

已经有实证研究给出结论:项目说明文件不要自动生成,手写也要写极少。那"极少"到底写什么?
很多人要么让 AI 吐一份几十行的模板,要么照着网上的范例抄一大堆——架构说明、风格偏好、团队介绍全堆进去。结果 AI 读完该错还错,因为那些它本来就能从代码里读出来。
一份管用的文件,核心其实就三块:命令、边界、完成标准。
先给一份最小结构,再逐块说:
"项目一句话"和"交接"是可选的两块;命令、边界、完成标准才是核心,缺一不可。顺序也有讲究:不同工具对靠前的内容权重更高,所以边界要尽量靠前,别埋在最后。
命令块写具体指令,不要写"运行测试"这种空话。顺手把"全量检查"那条拼好,AI 就不会每次自己发明一套顺序:
边界块最重要,用祈使句写"不要做什么",放在文件靠前位置:
研究里有个关键观察:智能体对文件里的指令几乎是"字面照做"的——文件里提到某个包管理器,它就会去用(提到时平均调用 2.5 次,没提到时不到 0.05 次)。顺着这个机制,明确的 don'ts 比抽象的原则管用得多:因为模型会倾向于匹配训练数据里的常见写法,你不拦,它就按最常见的来。
完成标准块告诉 AI 什么算做完,否则它会在认为"差不多了"的时候就交差:
这是最容易踩的坑。对比一下:
差别在于后者有触发条件、有明确动作、有例外处理。前者读完之后,行为不会有任何变化。还有个细节:给具体位置而不是抽象原则。"错误处理参照 src/errors.ts:12" 比 "遵循最佳实践" 有用一百倍。
不同工具读的文件不一样:Claude Code 默认读 CLAUDE.md,Cursor 读 .cursor/rules/,Codex、Copilot、Gemini CLI 等读 AGENTS.md。
推荐做法是单一真相源:
规则只维护一份,工具专属文件只做引用,不复制内容。重复定义会导致优先级混乱,AI 不知道该听谁的。另外可以拆一份 AGENTS.local.md 放个人偏好(加进 .gitignore),公共规范进版本库,两者不混。
误区一:把架构说明写进去
长篇架构说明对 AI 帮助很小——它能读代码。写它读不出来的东西:命令、约定、哪些目录是外生的/生成的/不能碰的。
误区二:写模糊的风格偏好
"代码要优雅""注释要恰当"这类无法判定的要求,不仅无效,还占用上下文。能写进 lint 规则的,就交给 lint,别写进文档。
误区三:写完就不维护
文档是活文档,维护方向是双向的:技术栈变了要更新,过时的条目也要删。陈旧的错误指令比缺失更危险,它会让 AI 稳定地做错事。很好用的经验法则:同一个教训学到第二次,就把它写进文档。
既然说明文件在"被遵守"这件事上有天然的损耗,就有人干脆换了个思路:不再靠 markdown 提醒,改成程序化强制。
社区里已经有人这么做:用 AST 校验规则、pre-commit 钩子、确定性 linter 来卡规范,说明文件只留最少的命令和边界。他们的理由很朴素——"即使写得很明确的指令,也经常被忽略",那就不如让规范在提交前自动报错。
这个方向跟"给 AI 装闸门"是同一件事:能判定就别商量。文档负责传达意图,代码负责兜住红线。
判断一份项目文档好不好,有个很朴素的标准:
如果一个新同事第一天上班,拿着这份文件还不敢动手改,那 AI 也帮不上什么忙。
把命令补全,把边界写死,把完成标准列清楚,然后删掉所有形容词。文件短一点没关系——短到每次运行都能完整读一遍,才是一份真正会被执行的文档。
最后把期待值摆正一次:别指望它让 AI 变聪明,它的作用是让 AI 别猜错。至于生成,可以让 AI 帮你起草,但起草完必须自己删,删到只剩命令、边界和完成标准。
#智能体 #AGENTS.md #AI编程 #工程规范 #技术实践