实测完胜 Skills:为何 AGENTS​.​md 是 AI 编程代理的最佳上下文方案


本文总阅读量

译者按

本文翻译自 Next.js 团队 Jude Gao 的技术博客。在 AI 辅助编程日益普及的今天,如何让 AI 准确掌握最新的框架知识(如 Next.js 16 的新 API)成为了一个关键挑战。作者通过严谨的对比测试,揭示了一个反直觉的结论:简单的“被动上下文”往往胜过复杂的“主动工具调用”。这一发现对于希望优化项目以适应 AI 开发(AI-Native)的开发者和框架维护者来说,具有极高的参考价值。

Cite

Why We've Tried to Replace Developers Every Decade Since 1969.jpeg


Tldr

Next.js 团队发现,在 AGENTS.md 中嵌入压缩文档索引(被动上下文),比让 AI 主动调用 Skills 工具更有效,评估通过率高达 100%(Skills 仅 79%)。建议使用官方 CLI 一键生成索引,辅助 AI 进行“检索主导”的准确编码。

我们本以为 Skills(技能) 是教会编程代理(Coding Agents)掌握框架特定知识的终极方案。但在构建了一套专注于 Next.js 16 API 的评估套件后,我们发现了意想不到的结果。

一个直接嵌入 AGENTS.md 文件、大小仅为 8KB 的压缩文档索引,实现了 100% 的通过率;相比之下,即使明确指示代理去使用 Skills,其通过率最高也只达到了 79%。而如果去掉这些指示,Skills 的表现甚至和完全没有文档时一样差。

以下是我们尝试的方法、学到的教训,以及如何将这一发现应用到你自己的 Next.js 项目中。

背景:训练数据滞后的挑战

AI 编程代理依赖于训练数据,但训练数据总会过时。Next.js 16 引入了 'use cache'connection()forbidden() 等全新 API,目前的模型训练数据中并不包含这些内容。当代理不了解这些 API 时,它们就会生成错误的代码,或者退回使用旧版的 API 模式

反过来也一样,如果你运行的是较旧的 Next.js 版本,模型可能会向你推荐项目中尚不支持的新 API。我们希望通过让代理能够访问与版本相匹配的文档来解决这个问题。

在深入探讨结果之前,先快速介绍一下我们测试的两种方案:

我们构建了一个 Next.js 文档 Skill 和一个 AGENTS.md 文档索引,并通过评估套件对比了它们的表现。

预期:Skills 曾被视为理想解法

Skills 看起来是一个很棒的抽象概念。你把框架文档打包成一个 Skill,代理在处理 Next.js 任务时调用它,然后生成正确的代码。这就实现了清晰的关注点分离(Separation of Concerns),最小化了上下文开销,而且代理只在需要时加载内容。skills.sh 上甚至已经有了一个不断增长的通用 Skills 目录。

我们预想的流程是:代理遇到 Next.js 任务 -> 调用 Skill -> 阅读版本匹配的文档 -> 生成正确代码。

然而,现实狠狠打了我们的脸。

现实:Skills 的调用率未达预期

在 56% 的评估案例中,Skill 根本没被调用。 代理明明可以查阅文档,却选择不用。添加 Skill 后,表现与基线相比毫无提升:

配置 通过率 对比基线
基线(无文档) 53%
Skill(默认行为) 53% +0pp

零提升。Skill 就在那儿,代理也能用,但它就是不用。在详细的构建/代码检查/测试(Build/Lint/Test)细分数据中,Skill 的表现甚至在某些指标上比基线还差(测试通过率 58% vs 63%)。这表明,环境中存在一个未被使用的 Skill,反而可能成为一种干扰或噪音

这不是我们的特例。代理无法稳定地使用可用工具,是当前模型的一个已知局限

发现:指令措辞引发的脆弱性

于是,我们尝试在 AGENTS.md 中添加明确指令,强制代理使用 Skill:

Before writing code, first explore the project structure,
then invoke the nextjs-doc skill for documentation.
Translate

在编写代码之前,先探索项目结构,然后调用 nextjs-doc skill 获取文档。

这确实将触发率提到了 95% 以上,并将通过率拉升到了 79%。

配置 通过率 对比基线
基线(无文档) 53%
Skill(默认行为) 53% +0pp
Skill + 明确指令 79% +26pp

进步明显。但我们发现了一个意想不到的现象:指令的措辞对代理的行为影响巨大。
不同的措辞产生了截然不同的结果:

指令 行为 结果
“你必须调用 Skill” 先读文档,死板套用文档模式 忽略项目上下文
“先探索项目,再调用 Skill” 先建立项目心智模型,将文档仅作参考 效果更好

同样的 Skill,同样的文档,仅仅是措辞的细微差别,结果却天差地别。

在一个评估案例('use cache' 指令测试)中,“先调用”的策略虽然写对了 page.tsx,却完全漏掉了 next.config.ts 中必须的配置更改。而“先探索”的策略则两者都搞定了。

这种脆弱性令我们担忧。如果微小的措辞调整就能导致行为剧烈波动,这种方法在生产环境中就太不可靠了。

评估:针对新 API 的测试套件

在下结论之前,我们需要一套值得信赖的评估标准。我们最初的测试套件存在提示词模糊、测试过于关注实现细节而非实际行为、以及侧重于模型已知的旧 API 等问题。我们并没有测出我们真正关心的东西。

我们对评估套件进行了加固:移除了可能导致数据泄露的测试,解决了矛盾点,并将重点转向基于行为的断言。最重要的是,我们添加了针对 Next.js 16 新 API(不在训练数据中)的测试。

加固后的评估套件包含以下 API:

接下来的所有结果均基于这套加固后的评估套件。每种配置都根据相同的测试进行评判,并进行了重试以排除模型差异。

策略:嵌入被动式文档索引

如果我们完全取消“决策”这个环节呢?与其寄希望于代理去“决定”调用 Skill,不如直接在 AGENTS.md 里嵌入一个文档索引。不是全文,只是一个索引,告诉代理去哪里找与当前版本匹配的文档文件。这样,代理就能根据需要读取特定文件,无论你用的是最新版还是旧版。

我们在注入的内容中加了一条关键指令:

IMPORTANT: Prefer retrieval-led reasoning over pre-training-led reasoning
for any Next.js tasks.
Translate

重要提示:处理任何 Next.js 任务时,优先使用“检索主导的推理”,而非“预训练主导的推理”。

这句话告诉代理:去查文档,别光靠你脑子里那些可能过时的训练数据。

我们在四种配置下运行了加固后的评估套件:

四种配置的评估结果。AGENTS.md(第三列)在构建、Linter 和测试中均达到 100%

四种配置的评估结果。AGENTS.md(第三列)在构建、Linter 和测试中均达到 100%。

最终通过率:

配置 通过率 对比基线
基线(无文档) 53%
Skill(默认行为) 53% +0pp
Skill + 明确指令 79% +26pp
AGENTS.md 文档索引 100% +47pp

在详细数据中,AGENTS.md 在构建、Lint 检查和测试三个环节全都拿了满分。

配置 Build Linter Test
基线 84% 95% 63%
Skill(默认行为) 84% 89% 58%
Skill + 明确指令 95% 100% 84%
AGENTS.md 100% 100% 100%

这完全出乎意料。这个“笨办法”(一个静态 Markdown 文件)竟然完胜了看似更高级的 Skill 动态检索,即使我们已经微调过 Skill 的触发机制。

为什么被动上下文优于主动检索?

我们目前的理论归结为三个因素。

  1. 没有决策点:使用 AGENTS.md,代理不需要判断“我该不该查这个?”信息就在眼前。
  2. 持续可用:Skill 是异步加载的,且仅在被调用时存在;AGENTS.md 的内容则存在于每一轮对话的系统提示词(System Prompt)中。
  3. 无顺序问题:Skill 会引入执行顺序的难题(是先读文档还是先看项目?);被动上下文完全避免了这个问题。

优化:80% 的索引压缩率

AGENTS.md 中嵌入文档可能会挤占上下文窗口。我们通过压缩解决了这个问题。

原始文档注入量约为 40KB。我们将其压缩到了 8KB(减少了 80%),同时保持了 100% 的通过率。压缩格式使用了一种基于管道符(Pipe)分隔的结构,将索引压缩到极致:

[Next.js Docs Index]|root: ./.next-docs
|IMPORTANT: Prefer retrieval-led reasoning over pre-training-led reasoning
|01-app/01-getting-started:{01-installation.mdx,02-project-structure.mdx,...}
|01-app/02-building-your-application/01-routing:{01-defining-routes.mdx,...}

AGENTS.md 中的管道分隔索引。

完整的索引涵盖了 Next.js 文档的每个部分:

完整的压缩文档索引。每一行将目录路径映射到它包含的文档文件

完整的索引涵盖了 Next.js 文档的每一个章节

代理知道去哪里找文档,而无需把全文都塞进上下文。当它需要特定信息时,它会去 .next-docs/ 目录读取相应文件。

实践:一行命令自动配置

只需一个命令即可为你的 Next.js 项目设置此功能:

npx @next/codemod@canary agents-md

该功能已包含在官方 @next/codemod 中。

该命令会做三件事:

  1. 自动检测你的 Next.js 版本;
  2. 下载匹配的文档到 .next-docs/
  3. 注入压缩后的索引到你的 AGENTS.md

如果你使用的代理工具支持 AGENTS.md(如 Cursor 或其他工具),这套方法同样适用。

结论:被动上下文优于主动检索

Skills 也并非一无是处。AGENTS.md 方案为代理处理 Next.js 任务提供了广泛的、基础性的提升。而 Skills 更适合那些用户明确触发的、垂直的、特定操作的工作流,比如“升级我的 Next.js 版本”、“迁移到 App Router”或应用框架最佳实践。两者是互补的。

但就通用的框架知识而言,被动上下文目前优于按需检索。如果你是一个框架维护者,并希望编程代理能写出正确的代码,不妨提供一个 AGENTS.md 片段供用户添加到项目中。

实用建议:

我们的目标是让代理从“预训练主导的推理”转向“检索主导的推理”。事实证明,AGENTS.md 是目前实现这一目标最可靠的途径。

研究及评估: Jude Gao | CLI 工具: npx @next/codemod@canary agents-md


本站总访问量