更好的工具反而让 Copilot 代码评审变差了?GitHub 工程团队教你如何真正改进

日期:2026-07-12
主题:更好的工具反而让 Copilot 代码评审变差了?GitHub 工程团队教你如何真正改进
原文Better tools made Copilot code review worse. Here's how we actually improved it.
来源:GitHub Engineering Blog
领域:🏗️ 系统工程


背景

给一个 AI Agent 更好的工具,它应该做出更好的工作——这是直觉。但当 GitHub 的工程团队将 Copilot 代码评审的底层工具替换为更强大、维护更好的共享工具时,结果却事与愿违:评审成本上升了,有用的评论反而变少了。

工具本身没有问题。问题出在**指令(instructions)**上。一旦他们按照代码评审的真正工作方式重写了指令,局面就逆转了——平均评审成本降低了约 20%,同时保持了相同的评审质量。

这不是一个"换工具"的故事,而是一个"调整工作流"的故事。GitHub 工程师 Napalys Klicius 在这篇博客中分享了他的团队如何通过让 Agent 的行为可见迭代指令设计,最终把一次失败的迁移变成了成功的优化。对于任何在 Agent 框架之上构建产品的团队来说,这都是一份宝贵的实战记录。

一次看似合理的工具迁移

从自有工具到共享工具

Copilot 代码评审的工作方式是这样的:当你打开一个 Pull Request 时,它会读取 diff,然后探索周围的代码来发现真正的问题。早期版本使用自己的一套代码探索工具——专门为代码评审场景设计的 API。

与此同时,Copilot CLI 维护着一套共享的 Unix 风格代码探索工具:grep(搜索文本)、glob(匹配文件路径)、view(读取文件内容)。这套工具被越来越多的 Copilot Agent 产品使用,包括 GitHub Copilot Cloud Agent。让代码评审也迁移到这套工具上,听起来是一个双赢的方案——工具维护更集中,改进能惠及多个产品。

但事情没有这么简单。

迁移后的异常表现

迁移后,团队在离线 benchmark 中发现了一个令人困惑的结果:Agent 变得更低效了。平均成本上升,有用的评论数量下降。

原有的工具并不是简单的封装。当搜索目录或读取代码范围时,它们会返回匹配行加上额外的周围代码上下文。这增加了 token 消耗,但早期模型往往受益于附近的上下文信息。换成共享工具后,这些"额外上下文"消失了,Agent 的行为也随之改变。

可视化追踪:看见 Agent 在想什么

GitHub 团队之所以能快速定位问题,关键在于他们有一套内部的 Copilot 代码评审 benchmark 系统。这套系统不仅能给出最终评分,还能展示 Agent 的执行路径:调用了哪些工具、返回了多少输出、错误发生在哪里、Agent 是在缩小证据范围还是在扩大搜索面。

当团队首次在离线 benchmark 中使用共享的 Copilot CLI 工具时,Agent 的行为模式很明显:它在浏览仓库,而不是在审查 PR。它会广泛搜索、猜测可能的路径、读大量文件、发现更多可搜索的东西、然后把多余的上下文一路带下去。

这种模式在"理解整个仓库"的任务中是有用的。但它不是代码评审的方式。

你可以在 trace 中看到这种差异。共享工具本身没问题,但指令给 Agent 灌输了错误的直觉。通用编码助手的指令适合交互式场景:开发者可能要求它理解仓库、规划变更、编辑文件,在多个轮次中持续交互。

而 Copilot 代码评审的任务要狭窄得多:从一个 PR diff 出发,收集足够的周围证据来判断变更是否引入了真正的问题,避免加载不需要的上下文。

重新设计指令:从"浏览"到"审查"

认识到问题后,GitHub 团队开始迭代指令设计。目标不是换掉工具,而是改变 Agent 使用工具的方式

审查导向的工作流

新的指令明确了 Copilot 代码评审应该遵循的工作流:

  1. 从 diff 出发:评审的锚点是 PR 中的变更,不是整个仓库
  2. 先用 grep 和 glob 缩小范围:搜索相关符号、文件路径
  3. 用 view 精确读取证据:只读取最相关的代码段
  4. 做出判断:基于收集的证据决定是否存在问题
  5. 搜索失败时优雅恢复:如果 grep 找不到结果,用更简单的转义搜索重试;如果路径错误,用 glob 替代猜测附近路径

Klicius 给出了一个具体的例子:假设 diff 修改了一个授权辅助函数(authorization helper),决定某个操作是否被允许。一个相关的审查问题不是"显示调用这个辅助函数的每个文件的完整内容",而是更狭窄的问题——"是否有任何请求处理调用方依赖已弃用的行为?"

审查 Agent 的工作流应该是:从 diff 中被修改的辅助函数出发 → grep 搜索调用者 → glob 找到可能的路由/控制器文件 → view 读取最相关的调用范围 → 判断变更是否改变了风险。

小改动,大效果

这种变化在文字上是微小的,在效果上是巨大的。它把 Agent 的节奏从"浏览、阅读、再搜索"变成了"提问、缩小、阅读、判断"。

共享的工具集本身没有变,但使用工具的方式变了。工具描述和系统指令对 Agent 来说就像是 API 文档。模糊的 API 文档会让开发者困惑,导致低效或错误的决策。模糊的工具指令对 LLM 也会产生同样的效果——一个措辞上的小改动就可能影响成本、质量和调查路径的形状。

结果:成本降低 20%,质量保持不变

经过迭代后,生产环境中的表现显示平均评审成本相比对照组降低了约 20%。更重要的是,没有出现质量信号上的回退(即没有更多问题的遗漏)。

这个降低不是来自工具本身,而是来自工具周围的工作流。Klicius 特别强调了三个要素的组合:

要素 作用
共享代码探索工具 提供 grep、glob、view 等基础能力,维护成本更低
自定义工具指令 为代码评审场景定制,引导 Agent 聚焦 PR diff 证据
内部 benchmark 系统 让 Agent 行为可见,形成快速迭代的反馈闭环

最有用的信号不是"指令变好了",而是更具体的变化:Agent 调用工具的次数相似,但更多调用花在了相关的证据上,而不是反复扩大搜索范围。这把产品级别的结果和可理解的工程行为联系了起来——不再需要猜测分数为什么变动,而是可以直接检查产生分数的工作流。

重要的反例:同样的指令在 CLI 中并不奏效

团队还尝试在 Copilot CLI 中应用同样的聚焦工具指令。结果是没有产生同样的效果。这是一个重要的反例,也是一个重要的警示:

这个反例验证了一个核心结论:共享工具可以规模化,前提是指令和 benchmark 与具体任务匹配

总结与展望

这个故事的核心洞察值得我们反复品味:对于 Agent 来说,工具表面(tool surface)本身就是产品体验的一部分。它改变了 Agent 能注意到什么、如何搜索、如何组织推理。把工具当作实现细节——换个工具然后比较最终答案——是不够的。

如果用一个比喻来说:工具描述的编写方式,就像是给 API 写文档。模糊的 API 文档让开发者困惑,导致低效甚至错误的决策;模糊的工具指令对 LLM 也是如此。一个措辞上的小改动,就能影响成本、质量和调查路径的形状。

对于正在构建或使用 Agent 系统的团队来说,这篇文章给出了三条可操作的建议:

  1. 让 Agent 的行为可见:投资于 trace 和可视化工具,不要只看最终分数
  2. 为任务设计指令,而不是为工具:同样的工具集在不同任务中需要不同的引导
  3. 建立快速反馈闭环:benchmark 系统的价值不仅在于评估,更在于迭代

GitHub 的这次经历也让我们看到,AI Agent 的开发与传统软件开发有着本质的不同——在传统开发中,替换一个库通常不会改变程序的行为逻辑;但在 Agent 系统中,工具的替换会通过 LLM 的推理路径产生连锁反应。理解这种差异,是构建可靠 Agent 系统的起点。