AI 编程代理在现代开发工作流中扮演着越来越重要的角色,但它们面临一个根本性的矛盾:模型的知识来自预训练数据,而框架和库的 API 却在持续快速迭代。当 Next.js 16 引入 'use cache'、connection()、forbidden() 等新特性时,基于预训练的代理很可能一无所知,要么生成错误代码,要么回退到过时的模式。Vercel 团队近期进行的一项系统性对比实验,为这一困境提供了意想不到的解决方案,其结论可能重塑我们向代理传授框架知识的方式。
两种范式的本质差异
在深入数据之前,有必要理解 Vercel 对比的两种方案在架构上的根本区别。Skills(技能) 是一个开放标准,旨在将领域知识打包成可按需调用的单元。当代理识别到需要特定框架帮助时,它会主动调用相关技能,获取其中的文档、工具和提示。这意味着代理需要做出一个关键决策:当前任务是否需要调用某个技能?这个决策点引入了不确定性 —— 如果代理未能识别调用时机,技能中的内容就形同虚设。
相比之下,AGENTS.md 采用了一种截然不同的思路。它是一个位于项目根目录的 Markdown 文件,其中包含的内容会成为系统提示词的一部分,在每一次交互中持久存在。代理无需决定是否加载它,因为相关信息已经在上下文之中。这种设计将 "是否查找文档" 这个决策从代理的职责中移除,转而依赖开发者在配置阶段的显式声明。Vercel 团队最初对技能方案寄予厚望,认为这种按需调用的模式更符合 "关注点分离" 的设计原则,但实验结果打破了这一预期。
令人意外的基线数据
实验的第一阶段揭示了一个严峻的问题:在没有额外干预的情况下,技能方案几乎没有任何效果。基线配置(不提供任何文档)获得了 53% 的通过率,而添加技能后的默认行为同样停留在 53%,零提升。更令人担忧的是详细指标分析:在 Build、Lint、Test 三个维度的拆解中,技能在部分指标上甚至略低于基线(Test 从 63% 降至 58%),这暗示了环境中存在但未被使用的技能可能引入干扰或认知负担。
深入分析调用日志后,团队发现了一个惊人的事实:在 56% 的评估场景中,技能从未被代理主动调用。代理拥有技能的访问权限,却从未选择使用它。这并非 Vercel 特有的问题 ——OpenAI 自己的评估研究也承认,代理可靠地使用可用工具是当前模型的一个已知局限。模型在预训练阶段积累的模式匹配能力,有时会让它自信地 "凭记忆行事",而忽略显式提供的资源。
指令微调的脆弱性
面对零提升的困境,团队尝试在 AGENTS.md 中添加显式指令,引导代理在编码前先探索项目结构并调用技能。这一干预取得了显著效果:通过率从 53% 跃升至 79%,提升了 26 个百分点。然而,进一步实验揭示了指令措辞的脆弱性。两种看似等效的指令产生了截然不同的行为和结果。
第一条指令采用强制性措辞:"You MUST invoke the skill"。代理在执行任务前会首先阅读文档,但这也导致它过度锚定于文档模式,反而忽视了具体的项目上下文。在 'use cache' 指令测试中,它正确编写了 page.tsx,却完全遗漏了必需的 next.config.ts 修改。第二条指令调整了顺序:"Explore project first, then invoke skill"。代理先建立对项目的整体认知,再将文档作为参考资源,结果在两个文件上都取得了正确实现。同一套技能、同一份文档,仅因指令措辞的细微差异,就产生了完全不同的工程结果。这种脆弱性让团队对基于技能的方案产生了根本性的质疑:如果生产环境中的行为对措辞如此敏感,任何小改动都可能引发难以预测的回归。
硬化评估套件
在得出结论之前,Vercel 团队首先硬化了自己的评估方法论。初始测试套件存在几个严重问题:测试提示模糊、验证的是实现细节而非可观察行为、且过度依赖模型已经熟悉的 API。他们重新设计了评估套件,重点关注 Next.js 16 中那些不在模型训练数据内的新 API,包括 connection() 动态渲染、'use cache' 指令、cacheLife() 和 cacheTag() 缓存控制、forbidden() 和 unauthorized() 访问控制、proxy.ts API 代理,以及异步 cookies() 和 headers() 等。每个配置都在相同条件下运行,并采用多次重试以排除模型方差的影响。这一硬化过程确保了后续数据反映的是真实能力差异,而非测试设计缺陷。
被动上下文的压倒性胜利
实验的第三阶段测试了团队的 "直觉方案":将文档索引直接嵌入 AGENTS.md,移除技能调用这个决策点。实现方式非常直接 —— 不是在上下文中包含完整文档(那样会快速耗尽 token 预算),而是嵌入一个压缩的索引,指引代理在需要时读取 .next-docs/ 目录下的具体文件。关键在于添加了一句指令:"IMPORTANT: Prefer retrieval-led reasoning over pre-training-led reasoning for any Next.js tasks."
结果令整个团队惊讶。AGENTS.md 配置在 Build、Lint、Test 三个维度上全部实现了 100% 的通过率,而基线仅为 53%,带显式指令的技能方案最高也只有 79%。从 53% 到 100% 的 47 个百分点差距,用 "显著" 已经不足以形容 —— 这代表着两种方案在代理能力上的本质差异。更值得注意的是,在详细指标拆解中,AGENTS.md 在 Build(84% → 100%)、Lint(95% → 100%)、Test(63% → 100%)上全面领先。
团队总结出被动上下文优于主动检索的三个核心因素。首先是无决策点:代理无需判断 "是否应该查找文档",信息已经在上下文中。其次是一致性可用性:技能是异步加载的,且仅在调用时生效,而 AGENTS.md 的内容在每次交互中都存在。最后是无排序问题:技能方案需要决定 "先读文档还是先探索项目",而被动上下文避免了这种序列化的决策依赖。
80% 压缩率与上下文管理
将完整文档嵌入上下文的明显风险是 token 消耗。初始注入的文档内容约为 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,...}。代理通过这个索引了解文档的组织结构,在需要时读取具体文件,而非一次性加载全部内容。这种设计既保证了关键信息的持久可用性,又将 token 消耗控制在可接受范围内。
工程实践建议
基于这次实验,Vercel 团队为框架维护者和开发者提炼出几条可操作的建议。第一,不要等待技能方案改进:虽然未来模型可能会更好地处理工具调用,但当前评估结果已经表明 AGENTS.md 是更可靠的选择,延迟采用意味着持续承受的性能损失。第二,积极压缩:完整文档并非必要,指向可检索文件的索引同样有效,且能大幅节省上下文空间。第三,用评估验证:构建针对训练数据外 API 的测试用例,这是文档访问价值的最真实度量。第四,面向检索设计文档结构:确保文档组织清晰,使代理能够快速定位和读取所需文件,而非在庞大的内容中漫无目的地搜索。
值得注意的是,团队并未完全否定技能方案的价值。AGENTS.md 提供的是 "广度、水平" 的改进,适用于代理与框架交互的通用场景;而技能在 "垂直、动作特定" 的工作流中仍然更具优势,例如 "升级我的 Next.js 版本"、"迁移到 App Router" 等需要明确用户触发的任务。两种方案在实践中可以互补,而非互斥。
结论
Vercel 的这项对比实验揭示了一个反直觉但极具价值的结论:在向 AI 代理传授框架知识这件事上,简单的持久上下文方案(AGENTS.md)优于设计更精巧的按需检索方案(Skills)。核心洞察在于移除了代理的决策负担 —— 当文档信息始终可用时,代理无需判断何时应该查阅,专注于任务本身。这一发现对于任何构建或维护框架的人来说都具有直接的实际意义:通过提供可嵌入的 AGENTS.md 片段,可以显著提升依赖该框架的代理生成代码的正确性。
资料来源:Vercel Blog, "AGENTS.md outperforms skills in our agent evals" (2026-01-28)。