翻译自 Vercel 博客文章:AGENTS.md outperforms skills in our agent evals
我们原本期望技能是教授编码智能体框架特定知识的解决方案。在构建专注于 Next.js 16 API 的评估后,我们发现了意想不到的结果。
直接嵌入在 AGENTS.md 中的压缩版 8KB 文档索引实现了 100% 的通过率,而技能即使在明确指示智能体使用它们的情况下,最高也只能达到 79%。如果没有这些指示,技能的表现与完全没有文档时没有区别。
以下是我们尝试的方法、我们学到的经验,以及如何在自己的 Next.js 项目中设置这一功能。
我们试图解决的问题
AI 编码智能体依赖于会过时的训练数据。Next.js 16 引入了 'use cache'、connection() 和 forbidden() 等 API,这些 API 并不在当前模型的训练数据中。当智能体不了解这些 API 时,它们会生成不正确的代码或回退到旧的模式。
反之也可能发生——你运行的是较旧版本的 Next.js,而模型建议了你的项目中尚不存在的新 API。我们希望通过向智能体提供版本匹配的文档来解决这个问题。
教授智能体框架知识的两种方法
在深入探讨结果之前,先简要介绍一下我们测试的两种方法:
- 技能是一种开放标准,用于封装编码智能体可以使用的领域知识。一个技能将智能体可以按需调用的提示、工具和文档捆绑在一起。其理念是智能体在意识到需要特定框架的帮助时调用该技能,并获取相关文档。
- AGENTS.md 是项目根目录中的一个 Markdown 文件,为编码智能体提供持久上下文。无论你在 AGENTS.md 中放入什么内容,智能体在每个回合都可以使用,而无需智能体决定加载它。Claude Code 使用 CLAUDE.md 来达到相同的目的。
我们构建了一个 Next.js 文档技能和一个 AGENTS.md 文档索引,然后将它们通过我们的评估套件,看看哪种表现更好。
我们最初押注于技能
技能似乎是正确的抽象。你将框架文档打包成一个技能,智能体在处理 Next.js 任务时调用它,然后你就能得到正确的代码。职责分离清晰,上下文开销最小,智能体只加载它需要的内容。甚至在 skills.sh 上还有一个不断增长的现成技能目录。
我们期望智能体遇到 Next.js 任务,调用技能,阅读版本匹配的文档,然后生成正确的代码。
然后我们运行了评估。
技能没有被可靠地触发
在 56% 的评估案例中,技能从未被调用。智能体可以访问文档但没有使用它。添加技能相比基线没有产生任何改进:
| 配置 | 通过率 | 相比基线 |
|---|---|---|
| 基线(无文档) | 53% | — |
| 技能(默认行为) | 53% | +0pp |
零改进。技能存在,智能体可以使用它,但智能体选择不使用。在详细的构建/Lint/测试细分中,技能在某些指标上实际上表现比基线更差(测试方面为 58% vs 63%),这表明环境中未使用的技能可能会引入噪声或干扰。
这并非我们设置所独有。智能体不能可靠地使用可用工具是当前模型的一个已知局限性。
明确指令有帮助,但措辞很脆弱
我们尝试在 AGENTS.md 中添加明确指示,告诉智能体使用该技能。
Before writing code, first explore the project structure,
then invoke the nextjs-doc skill for documentation.
这提高了触发率到 95% 以上,并将通过率提升到 79%。
| 配置 | 通过率 | 相比基线 |
|---|---|---|
| 基线(无文档) | 53% | — |
| 技能(默认行为) | 53% | +0pp |
| 带明确指令的技能 | 79% | +26pp |
一个实质性的改进。但我们发现指令措辞影响智能体行为的方式有些出乎意料。
不同的措辞产生了截然不同的结果:
| 指令 | 行为 | 结果 |
|---|---|---|
| "你必须调用技能" | 先阅读文档,以文档模式为锚点 | 错过项目上下文 |
| "先探索项目,再调用技能" | 先构建心理模型,使用文档作为参考 | 更好的结果 |
相同的技能。相同的文档。基于微小的措辞变化产生不同的结果。
在一个评估('use cache' 指令测试)中,"先调用"的方法编写了正确的 page.tsx,但完全错过了所需的 next.config.ts 更改。"先探索"的方法两者都得到了。
这种脆弱性让我们担心。如果微小的措辞调整会导致巨大的行为变化,这种方法在生产环境中感觉会很脆弱。
构建我们可以信任的评估
在得出结论之前,我们需要能够信任的评估。我们的初始测试套件存在模棱两可的提示、验证实现细节而非可观察行为的测试,以及关注模型训练数据中已有的 API。我们没有测量我们真正关心的东西。
我们通过移除测试泄露、解决矛盾以及转向基于行为的断言来强化评估套件。最重要的是,我们添加了针对不在模型训练数据中的 Next.js 16 API 的测试。
我们重点评估套件中的 API:
- connection() 用于动态渲染
- 'use cache' 指令
- cacheLife() 和 cacheTag()
- forbidden() 和 unauthorized()
- proxy.ts 用于 API 代理
- 异步 cookies() 和 headers()
- after()、updateTag()、refresh()
以下所有结果都来自这个强化的评估套件。每种配置都根据相同的测试进行判断,并通过重试排除模型差异。
产生回报的直觉
如果我们完全移除决策会怎样?与其希望智能体调用技能,我们可以直接在 AGENTS.md 中嵌入文档索引。不是完整的文档,只是一个告诉智能体在哪里找到与你的项目 Next.js 版本匹配的特定文档文件的索引。然后智能体可以根据需要读取这些文件,无论你是使用最新版本还是维护旧项目,都能获得版本准确的信息。
我们在注入的内容中添加了一个关键指令。
IMPORTANT: Prefer retrieval-led reasoning over pre-training-led reasoning
for any Next.js tasks.
这告诉智能体查阅文档,而不是依赖可能过时的训练数据。
结果让我们惊讶
我们在所有四种配置上运行了强化评估套件:
最终通过率:
| 配置 | 通过率 | 相比基线 |
|---|---|---|
| 基线(无文档) | 53% | — |
| 技能(默认行为) | 53% | +0pp |
| 带明确指令的技能 | 79% | +26pp |
| AGENTS.md 文档索引 | 100% | +47pp |
在详细细分中,AGENTS.md 在构建、Lint 和测试方面都获得了满分。
| 配置 | 构建 | Lint | 测试 |
|---|---|---|---|
| 基线 | 84% | 95% | 63% |
| 技能(默认行为) | 84% | 89% | 58% |
| 带明确指令的技能 | 95% | 100% | 84% |
| AGENTS.md | 100% | 100% | 100% |
这并非我们所预期的。"简单"的方法(静态 Markdown 文件)表现优于更复杂的基于技能的检索,即使我们微调了技能触发器。
为什么被动上下文能胜过主动检索?
我们的工作理论归结为三个因素。
- 没有决策点。 使用 AGENTS.md,智能体不需要决定"我应该查找这个吗?"的时刻。信息已经存在。
- 一致的可用性。 技能异步加载且仅在调用时加载。AGENTS.md 内容在每个回合的系统提示中都可用。
- 没有顺序问题。 技能创建排序决策(先读文档 vs 先探索项目)。被动上下文完全避免了这个问题。
解决上下文膨胀的担忧
在 AGENTS.md 中嵌入文档有膨胀上下文窗口的风险。我们通过压缩来解决这个问题。
最初的文档注入大约 40KB。我们将其压缩到 8KB(减少了 80%),同时保持了 100% 的通过率。压缩格式使用管道分隔的结构,将文档索引打包到最小空间中:
[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,...}
完整索引涵盖 Next.js 文档的每个部分。
智能体知道在哪里可以找到文档,而无需在上下文中包含完整内容。当它需要特定信息时,它会从 .next-docs/ 目录读取相关文件。
亲自尝试
一条命令即可为你的 Next.js 项目设置:
npx @next/codemod@canary agents-md
此功能是官方 @next/codemod 包的一部分。
此命令执行三件事:
- 检测你的 Next.js 版本
- 将匹配的文档下载到 .next-docs/
- 将压缩索引注入到你的 AGENTS.md 中
如果你使用支持 AGENTS.md 的智能体(如 Cursor 或其他工具),同样的方法也适用。
这对框架作者意味着什么
技能并非无用。AGENTS.md 方法在所有任务中提供智能体与 Next.js 协作的广泛、横向改进。技能更适合用户明确触发的垂直、特定于操作的工作流,如"升级我的 Next.js 版本"、"迁移到 App Router"或应用框架最佳实践。这两种方法相辅相成。
也就是说,对于一般框架知识,被动上下文目前优于按需检索。如果你维护一个框架并希望编码智能体生成正确的代码,请考虑提供一个 AGENTS.md 片段供用户添加到他们的项目中。
实用建议:
- 不要等待技能改进。 随着模型在工具使用方面变得更好,差距可能会缩小,但结果现在就很重要。
- 积极压缩。 你不需要上下文中的完整文档。指向可检索文件的索引同样有效。
- 使用评估进行测试。 构建针对训练数据中不存在的 API 的评估。这是文档访问最重要的地方。
- 为检索而设计。 构建你的文档结构,以便智能体可以找到并读取特定文件,而不需要预先获取所有内容。
目标是将智能体从预训练主导的推理转变为检索主导的推理。AGENTS.md 结果证明是实现这一目标的最可靠方法。
研究和评估由 Jude Gao 完成。CLI 可通过 npx @next/codemod@canary agents-md 使用
原文链接:https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals