ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

AGENTS.md 上下文策略层:决定 Agent 能力上限的关键文件

AGENTS.md 上下文策略层:决定 Agent 能力上限的关键文件

1. 为什么一个 Markdown 文件能决定 Agent 的上限

第一次看到AGENTS.md这个命名的时候,我下意识觉得它就是个 README 的变体——无非是把项目说明换个名字,给 AI 读一读,能有多大差别。直到我在一个多工具协作的 Agent 项目里连续踩了三次坑:同一个任务,模型在本地跑得好好的,换到 CI 环境就开始乱调工具;明明写了"不要动生产数据库",它还是把测试数据写进了线上表;上下文一长,它就把最早定下的约束忘得一干二净。排查到最后,问题既不在模型,也不在工具本身,而是没有一个稳定的、可被反复读取的上下文策略层。

AGENTS.md解决的正是这件事。它不是文档,不是注释,更不是可有可无的装饰,而是 Agent 在每一次决策前都会去"对齐"的一份行为契约。你可以把它理解成给 Agent 发的员工手册:告诉它这个项目里什么能做、什么不能做、遇到模糊情况该往哪个方向猜、工具怎么调、输出长什么样。它和普通的 prompt 最大的区别在于——prompt 是临时的、一次性的,而AGENTS.md是持久化、可版本控制、跨会话复用的。

这篇文章适合三类人看:正在从零搭 Agent、被上下文漂移折磨过的开发者;手里有一堆工具但不知道怎么让模型稳定调用的工程同学;以及想把 Agent 从"玩具 demo"推进到"能交付"的产品负责人。我会把AGENTS.md的定位、结构设计、字段取舍、实操写法、常见翻车点全部拆开讲,尽量让你看完就能直接抄一份能用的模板回去。

先说结论:Agent 的能力上限,往往不取决于你用了多强的模型,而取决于你给它划定的上下文边界有多清晰。AGENTS.md就是这条边界最便宜的落地方式。

2. 上下文策略层到底在解决什么问题

2.1 从"提示词工程"到"上下文工程"的转变

早两年大家聊 Agent,张口就是 prompt 怎么写、few-shot 怎么堆。那套思路在单轮任务里确实有效,但一旦进入多轮、多工具、长链路的场景,问题就暴露了。模型不是记不住,而是它记住的东西和你希望它记住的东西不是一回事。你希望它记住"这个仓库用 pnpm 不用 npm",它记住的却是"用户上一条消息里提到了 npm"。

这就是上下文工程要处理的核心矛盾:信息太多会稀释注意力,信息太少会导致决策失据。AGENTS.md的价值在于,它把那些"每次都必须知道"的稳定信息抽出来,固定成一个高优先级的上下文块,让模型不必从零散的对话历史里去猜。

我习惯把 Agent 的上下文分成三层来理解:

层级内容来源生命周期典型例子
策略层AGENTS.md长期稳定,随仓库版本走项目约定、工具白名单、输出规范
任务层当前对话与指令单次会话用户这次要做什么
记忆层历史交互、向量检索跨会话累积上次踩过的坑、用户偏好

AGENTS.md处在最顶层的策略层,它的特点是变化慢、优先级高、必须被无条件遵守。任务层可以灵活,记忆层可以模糊,但策略层一旦定下来,就不该被单次对话轻易覆盖。

2.2 没有策略层会发生什么

我拿自己踩过的坑给你还原一下。当时做的是一个代码审查 Agent,工具包括读文件、跑测试、提交评论。没写AGENTS.md之前,它的行为是这样的:

  • 有时候用cat读文件,有时候用sed,有时候直接调编辑器接口,全看它当时"心情";
  • 遇到测试失败,它会自作主张改测试用例而不是改业务代码;
  • 输出评论时一会儿中文一会儿英文,格式每次都不一样;
  • 上下文超过一定长度后,它开始忽略"只读模式"的约束,尝试写文件。

这些问题单看都不致命,但叠在一起,Agent 就完全不可交付了。后来我把这些约束全部写进AGENTS.md,明确到"读文件统一用 read_file 工具""测试失败时禁止修改测试代码""输出必须为中文 Markdown"这种颗粒度,行为立刻稳定下来。不是模型变聪明了,是它终于不用猜了。

2.3 策略层的三个核心职责

我把AGENTS.md的职责归纳成三条,基本覆盖了实际项目里 90% 的需求:

第一是约束。明确禁止项,比如不能碰的文件、不能调的工具、不能输出的内容。约束要写得像法律条文,不留模糊空间。

第二是引导。当存在多种合理做法时,告诉模型优先选哪个。比如"优先复用已有函数而不是新建""优先小步提交而不是一次性大改"。

第三是对齐。统一术语、格式、风格,让 Agent 的输出和团队既有规范一致。这一条最容易被忽略,但对多 Agent 协作场景至关重要。

提示:策略层不是越厚越好。我见过有人把AGENTS.md写成几千行的百科,结果模型反而抓不住重点。经验值是控制在 200 到 500 行之间,超过就该考虑拆分或分层加载了。

3. AGENTS.md 的结构设计与字段取舍

3.1 一份能用的骨架长什么样

先给你一份我实际在用的骨架,后面再逐块拆解为什么这么设计:

# AGENTS.md ## 项目概览 - 项目类型:Node.js 后端服务 - 包管理器:pnpm(禁止使用 npm/yarn) - 主要语言:TypeScript ## 行为约束 - 禁止修改 `migrations/` 目录下的任何文件 - 禁止直接操作生产环境配置 - 所有文件写入前必须先读取确认 ## 工具使用规范 - 读文件:统一使用 read_file - 执行命令:仅允许 package.json 中已定义的脚本 - 网络请求:默认禁止,需显式声明 ## 输出规范 - 语言:中文 - 格式:Markdown - 代码块必须标注语言类型 ## 决策优先级 1. 安全约束 > 任务目标 2. 已有实现 > 新建实现 3. 小步验证 > 一次性大改

这份骨架看起来朴素,但每一块都对应着前面说的三个职责。项目概览负责对齐基础事实,行为约束负责划红线,工具规范负责统一动作,输出规范负责统一结果,决策优先级负责处理冲突。

3.2 字段取舍背后的逻辑

很多人写AGENTS.md的第一个误区是"什么都想写"。我建议你用一把尺子来筛:这条信息,是不是每次决策都需要?如果只是偶尔用到,那它应该放在任务层或记忆层,而不是策略层。

举个例子。"这个项目用 TypeScript"是每次写代码都要知道的,放策略层。"这个函数上周重构过"是特定任务才需要的,放记忆层。分清楚这个,你的AGENTS.md就不会臃肿。

第二个误区是"写得太抽象"。像"请保持代码整洁"这种话,模型根本没法执行。什么叫整洁?缩进几个空格?函数多长算长?策略层的每一条都应该是可判定的,要么满足要么不满足,不能有中间态。

第三个误区是"只写禁止不写替代"。你告诉模型"不要用 npm",它可能转头去用 yarn。正确的写法是"包管理器统一用 pnpm,禁止 npm 和 yarn"。禁止项最好配一个明确的替代方案,否则模型会在你没想到的地方找出口。

3.3 约束的颗粒度怎么把握

颗粒度这件事,我摸索出来的经验是:约束到"动作"级别,而不是"意图"级别。

"不要破坏数据"是意图级别,太模糊。"禁止执行 DELETE 和 DROP 语句"是动作级别,可判定。前者模型会自己解释,后者模型只能遵守或违反。

再比如工具调用。"合理使用工具"是意图,"读文件只用 read_file,写文件只用 write_file,执行命令只用 run_script"是动作。后者虽然啰嗦,但换来的是行为可预测。

当然,颗粒度太细也有代价。如果你把每个工具的参数都规定死,AGENTS.md会变成一份 API 文档,维护成本极高。我的建议是约束到工具名和调用时机,参数留给工具自己的 schema 去管。

4. 实操:从零写一份可复用的 AGENTS.md

4.1 第一步:盘点项目的稳定事实

动手写之前,先做一次信息盘点。拿张纸,把下面几类信息列出来:

  • 技术栈事实:语言、框架、包管理器、运行时版本;
  • 目录约定:哪些目录是源码、哪些是生成物、哪些禁止改动;
  • 工具清单:Agent 能用哪些工具,每个工具的适用场景;
  • 输出要求:语言、格式、风格、长度限制;
  • 红线清单:绝对不能做的事。

这一步不需要写得多漂亮,先把信息倒出来。我通常会花 20 分钟做这个盘点,比直接开写效率高得多。

4.2 第二步:把事实翻译成可执行条款

盘点完,逐条翻译。翻译的原则是动词开头、条件明确、结果可验。

比如"这个项目用 pnpm"翻译成"包管理器统一使用 pnpm,禁止执行 npm install 和 yarn add"。"不要动数据库迁移文件"翻译成"禁止读取、修改、删除 migrations/ 目录下的任何文件,如需变更迁移,必须由人工处理"。

这一步最容易犯的错是保留口语化表达。像"尽量别""最好不"这种词,在策略层里等于没写。要么禁止,要么允许,没有中间地带。

4.3 第三步:设置决策优先级

当约束之间发生冲突时,模型需要一个裁决顺序。这就是决策优先级的作用。

我常用的顺序是:安全 > 正确 > 效率 > 风格。安全指不破坏数据、不越权;正确指逻辑符合需求;效率指少走弯路;风格指格式统一。这个顺序不是绝对的,你可以根据项目调整,但一定要有,而且要写清楚。

举个实际冲突的例子:任务要求"尽快完成重构",但重构过程中需要修改一个受保护的文件。这时候优先级就起作用了——安全高于效率,所以模型应该停下来报告冲突,而不是硬着头皮改。

4.4 第四步:验证与迭代

写完不是结束,是开始。我一般会设计几个"探针任务"来验证AGENTS.md是否生效:

  • 故意让它做一个被禁止的操作,看它是否拒绝;
  • 给它一个模糊指令,看它是否按优先级做合理推断;
  • 连续跑多轮,看约束是否随上下文增长而衰减。

如果探针任务失败,说明对应条款写得不够明确,回去改。这个迭代过程通常要跑两三轮,AGENTS.md才会真正稳定。

注意:不要指望一次写完美。AGENTS.md是活的文档,随着项目演进和踩坑积累不断补充。我现在的模板里有一半条款都是被坑出来的。

5. 多工具与多 Agent 场景下的策略层设计

5.1 工具白名单与调用时机

当 Agent 手里工具变多,最大的风险不是它不会用,而是它用错工具。读文件用写文件的工具,查数据用改数据的工具,这类错误在工具超过五个之后会明显增多。

AGENTS.md里我建议单独开一节"工具使用规范",明确每个工具的适用场景和禁用场景。格式可以这样:

工具适用场景禁用场景
read_file读取源码、配置读取密钥文件
write_file写入非保护目录写入 migrations/
run_script执行已定义脚本执行任意 shell 命令
search查找符号、文本替代精确读取

这张表的价值在于,它把"什么时候用什么"从模型的自由判断变成了查表动作。查表比判断稳定得多。

5.2 多 Agent 协作时的共享策略

多 Agent 场景下,AGENTS.md的角色会升级成"共享契约"。每个 Agent 可能有自己的角色定位,但它们必须遵守同一份底层约束。

我的做法是拆成两层:一份AGENTS.md放全局约束,所有 Agent 共享;每个 Agent 再带一份角色说明,只写它特有的职责和工具。这样既保证了一致性,又保留了灵活性。

比如一个代码审查场景,全局AGENTS.md规定"禁止修改任何源码",审查 Agent 的角色说明写"只输出评论,不执行修复",修复 Agent 的角色说明写"只修改被标记的文件,修改前必须读取原文件"。三者叠加,行为边界就非常清晰了。

5.3 上下文长度与策略层的加载策略

长会话里,策略层内容会被逐渐"淹没"。这是物理规律,不是模型缺陷。应对办法有两个:

一是在关键节点重新注入。比如每执行 N 步,或者每次切换工具前,把AGENTS.md的核心约束重新拼进上下文。这个动作可以由框架自动完成,不需要模型自己记得。

二是分层加载。把AGENTS.md拆成"核心约束"和"扩展规范"两部分,核心部分每次都加载,扩展部分按需加载。核心部分控制在 50 行以内,保证注意力不被稀释。

我实测下来,重新注入这个动作对约束遵守率的提升非常明显,尤其是在超过 20 轮的会话里。别指望模型自己记住,要主动帮它记住。

6. 常见翻车场景与排查清单

6.1 约束被忽略的三种典型原因

第一种是约束位置太靠后。模型对上下文开头和结尾的内容注意力最高,中间部分容易被忽略。所以核心约束要放在AGENTS.md的最前面,别藏在文档末尾。

第二种是约束之间有冲突。比如一处写"禁止写文件",另一处写"完成后保存结果",模型就会困惑。写完后一定要通读一遍,检查有没有自相矛盾的条款。

第三种是约束太抽象无法判定。前面说过,"保持整洁"这种话等于没写。凡是模型无法明确判断"我是否违反了"的条款,都要重写。

6.2 排查速查表

我把实际排查中最高频的问题整理成一张表,你可以直接对照使用:

现象可能原因排查动作
约束时灵时不灵位置靠后或上下文过长前移约束,增加重新注入
模型钻空子只写禁止没写替代补充明确的替代方案
多轮后行为漂移策略层被稀释缩短核心约束,定期重注入
工具调用混乱缺少工具规范表补充工具适用场景表
输出格式不统一输出规范不具体给出格式示例而非描述
冲突时乱决策缺少优先级补充决策优先级章节

6.3 几个我踩过的坑

第一个坑是把AGENTS.md当成一次性文档。写完就不管了,结果项目演进后约束过时,模型按旧规则办事。现在我养成的习惯是每次项目结构变动,同步更新AGENTS.md。

第二个坑是约束写得太死导致 Agent 无法工作。有一次我把网络请求全禁了,结果 Agent 连依赖都装不了。后来改成"默认禁止,需在任务中显式声明允许",才恢复正常。约束的目的是让 Agent 可控,不是让它瘫痪。

第三个坑是忽略输出规范。早期我只管行为不管输出,结果 Agent 每次返回的格式都不一样,下游解析经常失败。补上输出规范后,这个问题彻底消失。输出规范不是锦上添花,是工程化的必需品。

7. 把策略层当成产品来维护

写到这里,我想聊一个更宏观的视角。AGENTS.md看起来是个技术文件,但它本质上是一个产品化的上下文接口。它定义了 Agent 和项目之间的契约,决定了 Agent 能做什么、不能做什么、怎么做。

既然是产品,就要有维护机制。我的做法是把它纳入代码审查流程,任何改动都要走 PR,都要有人 review。这样能保证约束的一致性和可追溯性。同时我会定期做一次"约束审计",把过时的、冗余的、冲突的条款清理掉。

另一个体会是,策略层的质量直接决定了 Agent 的可迁移性。一份写得好的AGENTS.md,换个模型、换个框架,行为基本能保持一致。反过来,如果约束全靠 prompt 临时拼,换个环境就全乱套。这也是为什么我越来越重视这个文件——它是我把 Agent 从 demo 推向生产的关键抓手。

最后分享一个小技巧:我会在AGENTS.md末尾留一个"变更日志"区块,记录每次修改的原因和日期。看起来多余,但当三个月后你回头看某条约束为什么存在时,这个日志能救你一命。踩过几次"不知道这条为什么这么写"的坑之后,我就再也没删过这个区块。

返回列表