给已有项目补一份 AI 预读取文档:AGENTS.md 与上下文治理实践
已有项目接入 AI 编程工具后,光给 PRD 和截图往往对不准代码。问题通常不在模型,而在项目缺少一份常驻的约定文档。本文说明该补什么样的文件、写哪些内容、如何用渐进式披露拆分大文档,以及规则维护和提需求方式的改进清单。
问题:为什么把 PRD 和截图喂给 AI,代码还是写偏
一个典型的场景是:后端出身的人接手前端项目,把需求文档、原型图、截图一起丢给 AI 编程工具,让它生成或修改页面。结果经常是——接口字段名对不上、组件参数用错、样式引入了项目里根本没有的库、明明有现成的公共组件却重新手写了一遍。反复纠正几次,效率反而不如自己写。
PRD 只回答「要做什么」,不回答「这个项目里该怎么做」。技术栈、组件库版本、目录约定、字段命名、金额与时间的存储方式、哪些文件不许碰,这些信息在需求文档里从来不会出现,但它们恰恰决定了生成结果能不能直接落到代码里。所以需要补的不是更详细的需求,而是一份每次对话都会被读取的项目约定文档。
先分清两种上下文:任务上下文与常驻上下文
- 任务上下文:本次要改什么、涉及哪个页面、验收标准。它是临时的,一次任务结束就没用了。
- 常驻上下文:项目是什么、用了什么技术栈、遵循哪些约定、有哪些历史坑。它需要长期存在、反复被读、持续演进。
绝大多数准确率问题,是常驻上下文缺失造成的。补的方式不是写一份巨长的说明丢给 AI,而是建立一个分层的、可维护的规则体系。
载体选择:不同工具读不同的文件
| 载体 | 典型使用者 | 适用场景 |
|---|---|---|
AGENTS.md |
支持该约定的多种工具 | 跨工具共用的项目说明,放在仓库根目录 |
CLAUDE.md |
Claude Code 一类工具 | 项目规则与 Agent 行为约束 |
.cursorrules 或项目规则目录 |
Cursor 一类编辑器 | 编辑器内的补全与对话 |
| 子目录规则文件 | 支持目录级规则的工具有 | 大型仓库按模块隔离约定 |
具体文件名和加载优先级各工具并不相同,且仍在变化,配置前请以对应工具的官方文档最新说明为准。稳妥做法是:先写一份内容中立的 AGENTS.md 作为唯一事实来源,再用各工具的入口文件引用或复制关键条目,避免同一份规则维护两套。
初版该写什么:五段结构
不要一上来就写几十页。第一版控制在能覆盖 80% 常见错误的长度,重点写「不写就会错」的东西:
# 项目概览
B 端后台,前端 Vue 3 + Vite + TypeScript,后端 FastAPI,数据库 PostgreSQL。
# 技术栈与版本
- 组件库:使用仓库内已有的 UI 库,禁止自行升级大版本或引入同类新库
- 状态管理:Pinia,禁止引入 Vuex
- 请求层:统一走 src/api/request.ts,禁止在组件内直接 fetch
# 目录与命名约定
- 页面:src/views/<模块>/ ;复用组件:src/components/
- 接口类型统一放 src/types/,返回值必须有类型
# 边界与特殊逻辑
- 金额以整数分存储,仅展示层除以 100
- 时间统一按 UTC 存储,仅展示层做时区转换
- 分页参数以 1 为起始页,与后端保持一致
# 禁止事项(踩过的坑逐条追加)
- 禁止用 any 绕过类型检查
- 禁止修改 .env、部署脚本、依赖锁文件
- 禁止在 components 下发起业务请求
其中「禁止事项」是最有价值的一段。它不需要一开始就完整,而是随着每次 AI 犯错不断追加——相当于把踩过的坑沉淀成约束,写得越久越值钱。
大项目别塞进一个文件:渐进式披露
仓库一大,把所有文档都堆进根目录文件,会带来两个后果:每次都消耗大量上下文,真正关键的几条反而被淹没。更合理的做法是分层披露,让 AI 先读精简的入口,需要时再去读细节:
repo/
├── AGENTS.md # 常驻:项目是什么、技术栈、硬性禁止项
├── docs/
│ ├── architecture.md # 按需:模块划分、调用链
│ ├── components.md # 按需:组件用法、常见参数与版本差异
│ └── pitfalls.md # 按需:历史边界问题与踩坑记录
└── .agents/
└── skills/
└── new-endpoint/
└── SKILL.md # 可复用流程:新增接口的标准步骤
入口文件里写清「什么情况下该去读哪个文件」,比把内容全部前置更有效。进一步可以按用途再分三层:项目规则(人工维护、变更需评审)、长期偏好与经验(半自动积累)、临时工作笔记(任务结束即清理)。很多团队做的所谓「记忆文件演化」,本质就是让这三层各自有生命周期,别混在一起。
提需求的方式同样影响准确率
有了规则文件之后,任务描述也要配合。把需求定位到具体模块和接口,比写一大段自然语言描述有效得多:
根据 AGENTS.md 与 docs/components.md,在 src/views/order/ 下新增订单导出按钮。
约束:只改该目录;复用 ExportButton 组件;不要改动 api 层以外的文件。
先列出将要修改的文件清单,确认后再动手。
三个要点:指明参照哪份文档、圈定可改范围、要求先给计划再改代码。这样即使 AI 理解有偏差,也能在改代码之前被发现。
常见误区与注意事项
- 规则膨胀:文件越长,模型越容易顾此失彼。定期删掉已经内化或过期的条目,保留仍然会出错的那些。
- 规则冲突:两条互相矛盾的约定会让输出摇摆不定。合并同类项,同一件事只留一条。
- 写进敏感信息:令牌、内网地址、数据库连接串不要写进规则文件,它会随仓库一起被提交和读取。
- 过度依赖记忆工具:动态记忆类方案适合长期对话场景,但对「让代码写得对」这件事,一份准确的项目约定往往比一套记忆框架更直接。先把手写规则跑顺,再考虑引入工具。
- 以为写完就一劳永逸:技术栈升级、组件库换版本后,文档必须同步更新,否则它比没有更糟。
另外,如果团队需要让 Agent 长时间在线跑批量重构或定时巡检,本地机器休眠断连会打断任务,可以考虑把运行环境放到一台常驻的机器上(例如按月租用的远程 Mac)。但这只解决运行连续性问题,不能替代上下文治理——文档写不好,跑多久都还是偏。
小结:一份可执行的检查清单
- 在仓库根目录建立
AGENTS.md,按「概览 / 技术栈 / 目录约定 / 边界 / 禁止事项」五段起草,控制长度。 - 把组件库版本差异、金额与时间处理、分页与字段命名这类最容易出错的约定单列出来。
- 文档超过一屏时,拆成
docs/下的专题文件,入口只留导航和硬性规则。 - 每次 AI 犯错,追加一条禁令,并注明原因,避免后人误删。
- 提需求时指明参照文档、限定改动范围、要求先出文件清单。
- 每隔一段时间清理过期规则,检查是否存在互相矛盾的条目。
- 规则文件纳入代码评审,和代码一起演进。
补文档这件事的投入产出比通常很高:前期花一两个小时梳理,后续每次对话都能省下反复纠正的时间。先从最容易错的三五条写起,比追求一份完美的大而全文档要现实得多。