AGENTS.md 实战指南:用渐进式披露优化 AI Agent 上下文工程
1. 为什么我们需要一个叫 AGENTS.md 的东西如果你最近半年在折腾 AI Agent 开发大概率会遇到一个很尴尬的场景项目里塞了十几个 markdown 文件有 README、有 CONTRIBUTING、有各种 prompt 模板、有工具说明、有记忆文件结果 Agent 每次启动都要把这些东西全量读一遍。上下文窗口是有限的token 是要花钱的更麻烦的是——信息一多模型反而抓不住重点开始胡说八道。AGENTS.md这个文件本质上就是给 Agent 用的“上下文策略层”。它不是给人类看的项目说明而是给 AI 看的“操作手册 路由表 记忆索引”。你可以把它理解成 Agent 的“入职培训文档”新来的员工Agent不需要把公司所有资料都背下来只需要知道“遇到什么事该翻哪本手册、该找谁、该用什么工具”。这个思路在社区里有个专门的说法叫Context Engineering上下文工程而AGENTS.md是其中一种非常务实的落地形式。它解决的核心问题是如何让 Agent 在有限的上下文预算内拿到最相关的信息并且知道什么时候该主动去拿更多信息。适合谁来参考三类人一是正在从零搭 Agent 项目的开发者二是被“上下文爆炸”折磨过的团队三是想理解 Agent 架构里“策略层”到底该放什么的人。哪怕你用的是不同的 Agent 框架这套思路都是通用的。我先把结论摆出来AGENTS.md不是又一个配置文件它是 Agent 的**渐进式信息披露Progressive Disclosure**入口。它的设计质量直接决定了你的 Agent 是“聪明助手”还是“话痨废物”。2. AGENTS.md 到底该放什么不该放什么2.1 先搞清楚它和 README 的本质区别很多人第一反应是“这不就是个 README 吗”。不是。README 是写给人类协作者的讲究叙事完整、背景铺垫、安装步骤。AGENTS.md是写给 Agent 的讲究检索效率、指令明确、边界清晰。我踩过的第一个坑就是把 README 直接改名成AGENTS.md丢给 Agent结果 Agent 每次都要读一大段“项目愿景”“设计哲学”真正干活需要的“命令怎么跑”“文件在哪”反而被淹没了。两者的差异可以这样对照维度READMEAGENTS.md读者人类开发者AI Agent目标理解项目执行任务结构叙事式索引式长度可长可短必须精简更新频率低高关键内容背景、安装、用法路由、约束、工具、记忆指针一句话README 回答“这是什么”AGENTS.md回答“现在该干什么、去哪找、别碰什么”。2.2 核心内容清单五块必须有的东西根据我实际搭过几个 Agent 项目的经验AGENTS.md里最该出现的是这五类内容缺一块都会让 Agent 变笨第一块项目身份与当前状态。用两三句话告诉 Agent 这个项目是干嘛的、当前处于什么阶段开发中/稳定/实验性。不要写愿景写事实。比如“这是一个基于 Python 的文档处理 Agent当前支持 PDF 和 Markdown 输入OCR 模块尚未接入”。第二块目录与文件路由表。这是最核心的部分。告诉 Agent 每个目录放什么、什么任务该看哪个文件。比如“/prompts存放所有提示词模板修改 Agent 行为时优先看这里”“/tools是工具定义新增工具需要同步更新tools/index.md”。第三块常用命令与操作。跑测试、构建、部署、格式化全部列出来。Agent 不需要猜直接抄。第四块约束与禁忌。哪些文件不能改、哪些操作需要确认、哪些依赖不能引入。这块是防止 Agent “好心办坏事”的关键。第五块记忆与上下文指针。告诉 Agent 长期记忆存在哪、历史决策记录在哪、遇到不确定的事情该去哪个文件查。这就是 Progressive Disclosure 的落点。2.3 不该放什么三个反模式我见过太多AGENTS.md写成“大杂烩”这里明确说三个反模式不要把完整文档粘进去。需要详细说明的内容放到独立文件AGENTS.md里只留一行指针。上下文是稀缺资源不是仓库。不要写模糊的形容词。“代码要优雅”“注意性能”这种话对 Agent 毫无意义。要写就写“函数不超过 50 行”“数据库查询必须走索引”。不要放会频繁变动的数据。版本号、日期、临时状态这些放到单独的状态文件里AGENTS.md保持相对稳定。提示判断一条信息该不该进AGENTS.md问自己一句——“Agent 每次启动都需要知道这个吗”如果答案是“只在特定任务时需要”那就把它放到指针指向的文件里。3. 渐进式信息披露让 Agent 按需加载上下文3.1 什么是 Progressive Disclosure为什么它重要Progressive Disclosure 直译是“渐进式披露”在产品设计里指的是“先给用户看最重要的细节按需展开”。放到 Agent 上下文里逻辑是一样的Agent 启动时只加载最小必要上下文随着任务推进按需拉取更多信息。为什么这个策略重要两个硬约束第一上下文窗口是有限的。哪怕现在模型支持 200K token塞满之后模型注意力会稀释关键信息被淹没回答质量断崖式下跌。这是实测结论不是理论担忧。第二token 是要花钱的。每次调用都把全量上下文塞进去成本会随项目规模线性增长。一个成熟项目如果每次对话都读 5 万 token一天跑几百次账单会很难看。Progressive Disclosure 的核心思想是把上下文当成一个分层结构而不是一个平铺的大文本。3.2 三层上下文结构的设计我一般把 Agent 的上下文分成三层第一层常驻层Always Loaded。就是AGENTS.md本身控制在 500-1500 token 以内。包含项目身份、路由表、核心约束。这层每次必加载。第二层任务层Task Loaded。根据当前任务类型动态加载。比如任务是“修改提示词”就加载/prompts/README.md任务是“新增工具”就加载/tools/README.md。这层由AGENTS.md里的路由表决定。第三层深度层Deep Loaded。具体文件内容、历史决策、详细规范。只有在 Agent 明确需要时才读取通常通过工具调用比如读文件触发。这个结构的好处是Agent 启动成本恒定任务复杂度增加时上下文才增长而且增长是可控的、有方向的。3.3 路由表怎么写才有效路由表是 Progressive Disclosure 的“调度中心”。写得好Agent 自己就能找到该看的东西写得烂Agent 要么乱翻文件要么干脆不翻。我推荐用“任务类型 → 文件路径”的映射格式而不是“文件路径 → 说明”。因为 Agent 是带着任务来的它需要的是“我要做 X该看哪”而不是“这个文件是干嘛的”。一个实际可用的路由表示例## 任务路由 - 修改 Agent 行为/提示词 → 先读 prompts/README.md再定位具体模板 - 新增或修改工具 → 先读 tools/README.md同步更新 tools/index.md - 调整记忆策略 → 读 memory/strategy.md - 排查运行错误 → 读 docs/troubleshooting.md - 了解历史决策 → 读 docs/decisions/ 下按日期命名的记录 - 涉及数据库变更 → 必须先读 docs/db-migration.md 并确认注意最后一条带“必须”和“确认”的约束这是防止 Agent 自作主张的关键。3.4 上下文预算的粗略估算很多人不知道自己的AGENTS.md该写多长。给个经验值常驻层控制在 1500 token 以内。按中文大约 1 字 ≈ 1.5 token 估算也就是 1000 字左右。怎么分配这 1000 字我的建议是项目身份与状态100 字路由表300-400 字核心命令200 字约束与禁忌200 字记忆指针100 字超过这个量就要考虑把内容下沉到第二层。记住AGENTS.md是索引不是百科。4. 实操从零搭一个 AGENTS.md 驱动的 Agent 项目4.1 目录结构设计先给一个我实际在用的目录结构你可以直接抄project/ ├── AGENTS.md # 常驻层Agent 入口 ├── prompts/ │ ├── README.md # 提示词说明与索引 │ └── *.md # 具体模板 ├── tools/ │ ├── README.md # 工具说明 │ ├── index.md # 工具注册表 │ └── *.py # 工具实现 ├── memory/ │ ├── strategy.md # 记忆策略说明 │ └── working/ # 工作记忆存储 ├── docs/ │ ├── troubleshooting.md # 排错手册 │ ├── db-migration.md # 数据库变更规范 │ └── decisions/ # 历史决策记录 └── src/ # 实际代码这个结构的关键是每个 Agent 可能需要的“知识域”都有独立的 README 作为入口AGENTS.md只负责指路。4.2 AGENTS.md 完整模板下面是我打磨过好几版的模板可以直接拿去改# AGENTS.md ## 项目身份 文档处理 Agent支持 PDF/Markdown 输入输出结构化摘要。 当前阶段开发中OCR 模块未接入。 ## 任务路由 - 改提示词 → prompts/README.md - 加工具 → tools/README.md 更新 tools/index.md - 调记忆 → memory/strategy.md - 排错 → docs/troubleshooting.md - 查历史决策 → docs/decisions/ - 数据库变更 → 必读 docs/db-migration.md 并确认 ## 常用命令 - 跑测试pytest tests/ -v - 格式化ruff format . - 本地运行python -m src.main ## 约束 - 不改 src/core/ 下的核心逻辑除非明确要求 - 新增依赖需在 docs/decisions/ 记录理由 - 涉及删除操作必须先确认 ## 记忆指针 - 工作记忆memory/working/ - 长期决策docs/decisions/ - 不确定时先读 docs/troubleshooting.md这个文件大概 400 字token 消耗很低但信息密度足够。4.3 让 Agent 真正用起来加载策略光有文件不够还得让 Agent 知道怎么用。这里分两种情况情况一你用的是支持自定义系统提示的框架。直接把AGENTS.md内容注入系统提示并在末尾加一句“当任务涉及路由表中的条目时主动读取对应文件”。情况二你用的是工具调用型 Agent。把AGENTS.md作为初始上下文同时给 Agent 一个read_file工具。在系统提示里明确“遇到不确定的任务先查AGENTS.md的路由表再决定读哪个文件。”我实测下来第二种方式效果更好因为 Agent 有了“主动查资料”的能力而不是被动接受一堆上下文。4.4 一个真实的加载流程示例假设用户说“帮我改一下摘要生成的提示词。”Agent 的执行流程应该是读AGENTS.md发现路由表里“改提示词 →prompts/README.md”读prompts/README.md找到摘要生成对应的模板文件路径读具体模板文件执行修改如果涉及约束比如模板有版本管理要求回到AGENTS.md确认整个过程 Agent 只加载了必要的文件上下文占用可控。这就是 Progressive Disclosure 的价值。5. 常见问题与排查技巧实录5.1 Agent 不读 AGENTS.md 怎么办这是最高频的问题。原因通常有三个原因一文件没被注入初始上下文。检查你的框架配置确认AGENTS.md确实在系统提示或初始消息里。原因二系统提示没强调。光注入不够要在提示里明确说“这是你的操作手册遇到任务先查路由表”。模型需要被明确告知这个文件的重要性。原因三文件太长被截断。如果AGENTS.md超过上下文预算可能被静默截断。用 token 计数工具确认一下实际长度。排查顺序先确认注入再确认提示最后确认长度。5.2 路由表失效Agent 找不到该读的文件路由表失效通常是路径写错了或者描述太模糊。比如写“改配置 →config/”Agent 不知道具体读哪个文件。解决办法路由表指向的必须是具体文件不是目录。如果确实需要指向目录就在目录里放一个README.md作为入口路由表指向这个 README。另外路径要用相对路径并且和实际目录结构严格一致。我踩过一次坑路由表写的是prompt/实际目录是prompts/Agent 找半天找不到最后开始瞎猜。5.3 上下文还是爆炸预算失控的排查如果按 Progressive Disclosure 设计了上下文还是爆炸检查这几点常驻层是不是写太长了超过 1500 token 就要精简。第二层文件是不是也被全量加载了确认加载逻辑是按需的不是启动时全读。有没有“递归加载”比如 A 文件指向 BB 又指向 AAgent 来回读。工具返回的内容是不是太长了工具输出也要控制必要时做摘要。我遇到过一次工具返回了完整的数据库 schema几万 token 直接塞爆上下文。后来改成只返回相关表的结构问题解决。5.4 常见问题速查表问题现象可能原因排查方向Agent 不读 AGENTS.md未注入/未强调/被截断检查注入配置和长度路由失效路径错误/描述模糊核对路径指向具体文件上下文爆炸常驻层过长/递归加载/工具输出过大精简限制输出Agent 乱改文件约束不明确在 AGENTS.md 加“必须确认”条款记忆丢失记忆指针缺失补充 memory 路由5.5 几个我踩过的坑坑一把 AGENTS.md 当成文档写。一开始我写了两千多字结果 Agent 每次启动就消耗大量 token还抓不住重点。后来砍到 400 字效果反而更好。坑二路由表太细。我一度把每个文件都列进路由表结果 Agent 选择困难。后来改成按“任务类型”分组清晰多了。坑三忘了更新。目录结构变了路由表没同步Agent 开始读不存在的文件。现在我把“更新 AGENTS.md”写进了代码审查清单。坑四约束写得太软。“建议不要修改核心文件”这种话 Agent 会忽略。改成“禁止修改src/core/如需修改必须先确认”效果立竿见影。6. 进阶把 AGENTS.md 做成 Agent 的“策略中枢”6.1 多 Agent 场景下的 AGENTS.md 分层如果你在做多 Agent 系统AGENTS.md可以分层设计根级 AGENTS.md全局路由和约束所有 Agent 共享子级 AGENTS.md每个 Agent 自己的专属说明放在各自目录下根级负责“去哪找”子级负责“我是谁、我负责什么”。这样多 Agent 协作时每个 Agent 的上下文都是精准的不会互相污染。6.2 结合记忆系统让 AGENTS.md 成为记忆入口AGENTS.md里的“记忆指针”部分可以对接你的记忆系统。比如工作记忆存在memory/working/Agent 需要时读取长期决策存在docs/decisions/按日期索引用户偏好存在memory/user-prefs.md这样 Agent 就有了“知道自己知道什么、也知道自己不知道什么”的能力。遇到不确定的先查记忆而不是瞎编。6.3 版本化与演进AGENTS.md 也要迭代AGENTS.md不是一次写完就完事的。项目演进它也要跟着变。我的做法是每次目录结构调整同步更新路由表每次新增约束追加到约束区每季度审查一次砍掉过时内容把它当成代码一样维护而不是当成文档一样放着。6.4 一个可扩展的模板骨架最后给一个可扩展的骨架你可以按需增删# AGENTS.md ## 身份与状态 [一句话项目定位 当前阶段] ## 任务路由 [任务类型 → 文件路径] ## 常用命令 [命令列表] ## 约束与禁忌 [禁止事项 需确认事项] ## 记忆指针 [记忆存储位置] ## 扩展区 [按项目需要添加如多 Agent 分工、外部系统对接等]这个骨架的好处是核心五块固定扩展区灵活。项目简单时扩展区为空项目复杂时往里加内容但常驻层始终精简。我个人在实际操作中的体会是AGENTS.md的价值不在于它写了什么而在于它强迫你思考“Agent 到底需要知道什么”。很多 Agent 项目做不好不是因为模型不行而是因为上下文策略没设计好——该给的信息没给不该给的塞了一堆。把AGENTS.md当成策略层来设计而不是当成说明文档来写你的 Agent 会立刻聪明一个档次。最后分享一个小技巧如果你不确定某条信息该不该进AGENTS.md先别放观察 Agent 会不会因为缺这条信息而犯错。如果会再放进去。这样迭代几轮你的AGENTS.md会自然收敛到最优状态。