更好的工具反而让 Copilot 代码审查变差了。这是我们实际改进的方法。
给智能体更好的工具,它就应该做得更好。无论如何,这是直觉。当你打开一个 pull request 时,Copilot 代码审查会读取差异并探索周围的代码,在它们发布之前找到真正重要的问题。为此,它使用了自己的代码探索工具。所以当我们换用维护得更好、共享的、为 Copilot CLI、grep、glob 和 view 提供支持的共享工具时,我们期望一次干净的升级。相反,在我们的基准测试中,我们发现审查成本更高,捕获的问题更少。但问题不在于工具,而在于指令。一旦我们根据审查者实际阅读 pull request 的方式重写了指令,倒退变成了胜利:平均审查成本降低约 20%,同时保持相同的审查质量。这就是调整工具工作流程如何让我们找到解决方案的故事。
同样的工具,错误的直觉
如果你是在智能体框架之上构建的,你很可能也继承了它的工具。它们能工作,所以你会一直用它们,直到有一天你的用例偏离它们的设计初衷足够远,以至于它们悄悄地开始与你作对。这正是我们当时的情况。
在尝试使用共享的 CLI 工具之前,Copilot 代码审查使用了自己的代码探索工具。那个工具层的灵感来自于早期的智能体系统,包括 SWE-agent 风格的仓库导航和 GitHub Copilot Autofix 中的想法:列出目录、搜索文件、搜索目录和读取代码。那些工具确实能工作,但它们专属于 Copilot 代码审查,并且是为当时模型的行为方式设计的。早期的智能体编码模型发出的工具调用更少,并且更不擅长自动拉取必要的上下文。这意味着在模型发出的少量工具调用中,包含所有相关信息就更加重要。
与此同时,Copilot CLI 框架拥有一套共享的类 Unix 代码探索工具集:grep、glob 和 view。该框架也被越来越多的 Copilot Agent 产品使用,包括 GitHub Copilot 云 Agent,因此框架的改进可以让多个产品受益。我们希望尽可能清理和共享基础设施,于是尝试在 Copilot 代码审查中使用 Copilot CLI 框架中的这些工具。目标是减少重复的工具实现,创建一个共享位置来改进代码探索工具,并更轻松地在 Copilot 产品之间传递这些改进。
理论上,迁移工作看起来很简单:
| 旧的 Copilot 代码审查 | GitHub Copilot CLI | 用途 |
|---|---|---|
| list_dir | glob | 在打开代码前发现候选文件和目录。 |
| search_file 和 search_dir | grep | 搜索代码中匹配的文本、符号或调用位置。 |
| read_code | view | 在知道路径或范围后读取相关文件内容。 |
现有的审查工具并非轻量包装器。在搜索目录或读取代码范围时,它们可以返回匹配或请求的行,以及额外的周围代码上下文。这会增加 Token 成本,但也符合早期模型通常因自动包含附近上下文而受益的模式。最初,我们希望这是一次简单的迁移:将一套工具替换为另一套。但当我们在离线基准测试中测试共享工具时,审查 Agent 的效率和效果都下降了。平均成本增加,有用评论的数量减少。
追踪结果揭示了一个浏览循环。