先说清楚:AGENTS.md 是写给 Agent 看的,不是写给人看的项目简介
AGENTS.md 是一个约定:在项目根放一份 Markdown,编码 agent 读它来搞清这个项目该怎么改。它和 README 的分工很清楚——README 回答「这是个什么项目、怎么用」,给的是人;AGENTS.md 回答「要动它的时候,命令是什么、规矩是什么、哪里不能碰」,给的是 agent。这份格式由 OpenAI 提出并以 MIT 开放,官方首页写的采用规模是 6 万多个开源项目,Codex、Cursor、Gemini CLI、Aider、Jules 这些工具读的是同一份文件,所以一处写好,多个 agent 通用,不用每家维护一份。
第一步:把「能执行的命令」抄成清单
# 常用命令
- 安装依赖:pnpm install
- 跑测试:pnpm test # 只跑单个文件:pnpm test src/foo.test.ts
- 类型检查:pnpm tsc --noEmit
- 本地起服务:pnpm dev这一节最值钱。agent 最容易卡在「改完怎么验证」上;把安装、测试、构建、起服务的命令原样写清,连「单测怎么只跑一个文件」这种细节都写进去,它就能自己闭环,而不是改完就交差。注意写你现在真正在跑的那条命令,别写理想中的那条——一条跑不通的命令比不写更糟。
第二步:写代码约定,但要写「能判对错」的
# 代码约定
- 目录:一页一个路由,页面放 src/pages,通用组件放 src/components
- 新增接口先加 zod 校验,再写 handler
- 提交信息用 Conventional Commits(feat / fix / chore)
- 不要引入新的状态管理库,现有 store 够用判断标准很简单:删掉这一句,agent 的行为会不会变?不会变的就是废话。「保持代码优雅」「注意性能」这类没法在两个选项之间帮你选对,趁早删。能落地的约定往往长这样:具体到目录名、库名、格式,甚至直接给出一条反例。
第三步:划「禁区」,比写一堆「要求」更重要
# 边界与禁区
- 不要手改 dist/、*.min.js 与 public/rss/*.xml(都是构建或脚本生成)
- 不要动 .env*、生产配置与各类密钥
- 不要升级主版本依赖,除非我明确要求
- 改动尽量小,不做无关重构agent 闯祸多半是「顺手」。把生成物、密钥、生产配置、依赖大版本这几类明确列成「不要动」,比十条正向要求都管用——正向要求它可能理解偏,禁区它照做就行。
第四步:分文件,但别重复
README.md # 给人看:项目是什么、怎么跑起来
AGENTS.md # 给 Agent 看:怎么改、命令、约定、禁区
docs/更新规则.md # 给人看:流程与运维
server/AGENTS.md # 更深的目录放一份,只管 server/ 这块的规矩AGENTS.md 可以放在子目录里,用来覆盖某块代码的规矩:目录越深,作用范围越小、优先级越高,跟 .gitignore 越近越优先是一个道理。但别把 README 的内容抄一遍——两处都写,改起来必然打架,最后 agent 读到的是过期的那份。
第五步:先让 Agent 起草,再逐条确认
帮我读一遍这个仓库,起草一份 AGENTS.md:
- 先只写你能从代码里确认的事实(真实命令、目录结构、技术栈与版本)
- 不确定的标成「待确认」,不要编
- 分成:项目概览 / 常用命令 / 代码约定 / 边界与禁区 / 提交与部署
- 每写完一节,指出这一节里哪些是我的猜测、需要我拍板让 agent 起草比自己从零写快得多,但它会把「看起来合理」的东西当成事实写进去。所以要它标注每条结论是从哪看出来的,把猜测和事实分开;你只拍板存疑的那几条,剩下的它基本能填对。
第六步:边界,以及几个常见的坑
- 它是上下文,不是文档:越长越不划算,把必须遵守的留下、背景说明删掉,超过一屏就该拆到子目录
- 不同工具读的规则文件名不完全一样(有的还认 CLAUDE.md、.cursor/rules 等),但内容可以共用,别在三处各维护一份
- 命令写错比不写更糟:一条跑不通的测试命令会让 agent 反复试错,或者干脆跳过验证
- 改完代码顺手更新它:目录结构、脚本命令、依赖版本一变,文档没跟上,下一次它照旧规矩干活
一句话:写 AGENTS.md 的功夫不在「介绍项目」,而在「让 agent 在两个选项之间选对」——留下能执行的命令和能判对错的约束,其余都是噪音。