返回 文章 apply CMS 文章

Claude Code 团队如何用 AI 审查 AI 生成的代码

当 AI 编写了 90% 的代码,Claude Code 团队用多层自动化审查和风险分级,把人工审查时间压到最低,同时让回滚率下降 40%。

代码审查AI 智能体自动化工程效率
成长分 / 100 76 综合收获、行动、留存与影响

Claude Code 团队如何用 AI 审查 AI 生成的代码
为什么值得读了解在 AI 大规模生成代码的场景下,如何设计可扩展的代码审查流程。

学习如何用自动化审查、风险分级和持续反馈来平衡速度与质量。

关键洞察
  1. 审查从合并前的关卡转变为持续运行的过程,大多数变更在请求人工前已被 Claude 审查和修复。
  2. 通过风险分级(低/中/高)决定所需人工批准数,低风险变更可仅凭自动化检查合并。
  3. 发现项由多个代理验证,只有足够多代理同意才发布,并按严重程度排序,标记为 Important、Nit 或 Pre-existing。
转成行动

深入阅读

正文与原文对照

原文保真覆盖:全文原文字符:15482

当智能体以如此规模产出代码时,你如何进行代码审查?在 Claude Code 团队,一旦我们实现了高覆盖率和深度审查,我们就开始优化,目标是找到不会增加回滚或事故的前提下所需的最少人工审查时间。

我们之前说过,Claude 编写了 Claude Code 自身约 90% 的代码。那么,在我们产出的这种规模下,我们如何审查代码?还有人阅读代码吗?如果出了问题,谁来发现?

这篇文章介绍 Claude Code 团队的代码审查流程及其演变过程。从六月到九月,合并到 Claude Code 代码库的拉取请求数量翻了一倍多,而不得不回滚的比例下降了 40% 以上。

我们并没有取消审查。但我们确实将大部分阅读工作交给了机器,以优化人类的时间和注意力,并大力投入于让撤销错误变得快速而简单。

当智能体编写代码时,变更数量会迅速增长。在 Anthropic 的 monorepo 中,每天落地的变更从五月的约 2,500 个增加到今年九月的 30,000 多个。

Claude Code 拥有独立的代码库,与 monorepo 分开,但它也面临着巨大的压力。当你以如此快的速度交付时,手动逐行进行代码审查极其困难,甚至不可能。

代码审查有两个作用:

本文主要关注发现和修复问题,但我们会在接近结尾时回到第二个作用。

我们认为“是否有人读过代码?”是一个不精确的替代指标,无法回答“这个变更可能出什么问题,以及哪种检查——自动的还是人工的——才是发现它的正确方式?”

提出这个问题也改变了审查发生的时机。以前,审查是道路尽头的关卡:编写代码,打开 PR,等待你的同事。

现在,审查持续运行,更像是你写作时的拼写检查。大多数变更在请求人工查看之前,已经至少被 Claude 审查和修复过一次。这能捕获大多数常规错误,并将团队注意力留给更高层次的问题和审查。

我们希望将人类的时间和注意力保留给只有人类才能解决的问题,并确保自动化检查能捕获其余问题。在我们当前的变更速度下,人类仍有大量工作要做,我们的团队几乎每天都会遇到新的、前所未有的挑战。

人类时间涵盖了审查成本的两个方面:人们花在审查上的时间,以及他们花在修复劣质代码所造成问题上的时间。如果削减前者只是让时间出现在后者上,那就没有帮助。

因此,目标是 Claude Code 代码库(CLI、桌面和 Web 应用以及移动应用)中的大多数拉取请求在合并时,最多只需要一个人在环中,这个人可以是作者,且回滚或事故不增加。为了衡量人类时间,我们追踪每个 PR 的人工批准数(中位数和第 95 百分位数)、人工评论数,以及 PR 等待某人的时长。回滚率和事故率是护栏:如果它们上升,我们就没有节省人类时间,只是把它转移了。

一个典型的变更,从工程师的笔记本电脑(或 Slack 中的 Claude 会话)出发,要经过多层代码审查。

现在大多数审查都发生在 PR 存在之前。我们给 Claude 一些它可以运行的东西——比如测试、构建,或一张用来与设计稿对比的截图——并要求它展示输出,而不是说“做完了”。然后由一个子代理带着全新的上下文来审查 diff。这两个习惯都来自我们的最佳实践指南。

在开 PR 之前,我们中许多人还会运行几个内部技能:一个专门找 bug,一个简化 diff,一个做端到端的行为检查。UI 改动还会对照我们的设计准则进行检查。

创建 Claude Code 的 Boris Cherny 曾说,给 Claude 一种验证其工作的方式可能是最重要的事,这能带来好的结果。他估计这能让最终结果好上两到三倍,并写道:“验证在每个领域看起来都不一样。它可能简单到运行一条 bash 命令,或跑一套测试,或在浏览器或手机模拟器里测试应用。”

当自动审查器反复标记同一件事时,我们从源头修复它:在技能里、用一条 lint 规则,或更新诸如以下的指导性文件:

CLAUDE.md

告诉 Claude 这个项目是什么:技术栈、约定、目标和非目标。每次审查都会加载它,所以在大型代码库中我们让它保持简短,并从那里指向其他文档。审查器还会标记违反其中约定的代码,以及让其中某一行过时的改动。REVIEW.md

由代码所有者撰写,告诉审查器在他们那部分代码中什么才是重要的。我们会单独检查审查器是否真的遵循了它。好的那些都很短。它们说明在那个仓库里失败是什么样子(对文档来说是“它在撒谎”,对配置来说是“它路由错了”),限制琐碎意见的数量,列出要跳过的路径,并要求以文件和行号作为证据,而不是凭名字猜测。它们还要求一份摘要,以计数开头,并在没有需要修复的内容时直说。每个拉取请求在有人查看之前都会先得到一次 Claude 审查。它会对照整个仓库和 PR 声明的意图来阅读 diff,并问:这个改动解决了它的问题吗,契合系统吗,还是破坏了别的东西?

在 bug 修复上,它会寻找根本原因。公开版本 Code Review for Claude Code 现已在 Team 和 Enterprise 计划上全面可用,而 /code-review

在本地运行一个更轻量的版本。

当我们推出研究预览版时,获得实质性审查评论的内部 PR 比例从 16% 上升到 54%。大多数超过 1,000 行的 PR 都会得到发现项,而大多数小的 PR 则干净返回。管理员将每个仓库设置为 Quick、Standard 或 Deep。在漏掉一个 bug 的代价高于额外审查时间的地方,Deep 是值得的。

发现项在人类审查之前会由其他代理验证。多个代理同时寻找 bug。然后一个单独的小组对每个发现项投票,只有当足够多的代理同意它是真实的时,它才会被发布。仅涉及风格、诊断或清理的发现项会被丢弃。我们在保留这些过滤器之前,先在自己的 PR 上做了 A/B 测试。剩下的会以按严重程度排序的行内评论形式出现。每一条都被标记为 Important、Nit 或 Pre-existing,这样 PR 没有引入的 bug 就不会看起来像是作者的错。

每个发现都必须得到回应。 你要么修复它,要么附上理由解决该讨论串。通常智能体会在夜间接手修复,所以作者回来时会看到一个已经经过另一轮处理的 PR。

安全审查也有自己的自动化审查。只要 bug 审查或安全审查中还有任何发现处于未解决状态,PR 就不能合并。你要么修复它,要么用简短的理由关闭讨论串,这就是清除误报的方式。

如果后续提交修复了该问题,该发现会自动清除。你可以通过开源安全审查 GitHub Action 或 /security-review 命令设置同样的机制。设置方法见 Claude Code 中的自动化安全审查。

常规流程:lint、类型检查、各平台测试以及构建。(我们在此文章中写过如何为此规模扩展 CI。)一个典型的 CLI 拉取请求在任何人查看之前可能会运行数十项检查。PR 模板会询问该变更如何测试以及如何撤销。Claude 可以填写这些内容,但提出变更请求的人要签字确认。

文档修复和自动更新器变更的风险不同,因此审查方式也不同。

风险 示例 人工批准
低 文档、文案、仅内部功能、标志位后的增量变更 自动化审查和安全检查通过后无需人工批准
中 普通产品变更,以及对缓存、自动更新器或系统提示等敏感区域的变更 一人
高 最高风险的代码,以及始终需要两人审批的一小部分路径 两人

变更决定层级,而非作者。 分类器读取变更并选择其风险层级。第二个分类器询问该特定变更是否需要另一个人,即使其层级表明不需要。某些路径始终需要人工,包括所有者列为敏感的任何内容以及任何 CI 工作流文件。

只有受信任的作者才能走更轻量的路径。 只有仓库受信任列表上的作者才能走更轻量的路径,主要是拥有该仓库的团队。其他所有人都需要第二个人批准。智能体的批准也永远不能算作人的批准。自动化审查可以清除低风险变更,但无法填补需要人工的位置。

发起变更的人要对其负责。 在智能体编写的 PR 上,指挥智能体的人算作所需审查者之一,就如同他们自己输入了代码一样。

一次批准只覆盖一个特定提交。 如果新的提交落地且系统无法为其担保,例如智能体的推送或有人手动解决的合并,则必须重新给予批准。

合并队列会在应用变更的情况下针对 main 重新运行每一项检查,因此两个分别通过的 PR 不会合并成一个损坏的 main。新行为通常先通过标志位向 Anthropic 员工发布,我们的重度使用往往会在用户之前发现回归。公开发布先进入 latest 频道。stable 频道随后跟进。

有些错误仍会漏过,所以最后一层是为了快速捕获它们。标志位无需部署即可关闭。Claude Code 有每周轮值的 on-call,事故复盘会询问哪一层本应捕获该问题。

发现糟糕的合并仍然依赖于作者和值班人员,以及回滚和事件仪表盘。我们还没有在那些数字变动时收紧审批的熔断机制;这里的工程师希望在更多代码转向零人工合并之前拥有它们。

一位同事说,放慢速度确实会降低错误率,但主要是因为你在所有事情上做得更少。我们更愿意在发现和修复问题上变得更快。

我们的代码审查流程在一个循环中不断改进。

任何事件现在都是一次评估。 团队收集了过去导致事件的 PR,连同它们的修复推进和回滚,并让了解该代码的工程师确认每个 bug 及其所在位置。审查者每天针对该集合运行。

我们通过观察人们对评论的反应来衡量噪音。 如果你不介意标记大量非 bug,就很容易捕获更多 bug,所以我们需要对此进行检查。我们根据 PR 上的人如何回应来对审查者留下的每条评论进行分类:他们修复了它,说它是错的,说该行为是有意为之,或者决定它不重要。我们还在我们知道是干净的 PR 上运行审查者,并计算它报告了多少次会导致某人做出有害更改的内容。我们的优先事项,写下来,是首先捕获真正的 bug,其次减少审查轮次。

当作者是代理时,噪音的代价更高。一个人可以在几秒钟内挥开一个小问题。代理会修复它,这意味着又一次提交和另一轮审查。

审查必须收敛。 代理作者和代理审查者可以无限期地让对方忙碌。一个 CLI PR 在一夜之间经历了超过五十轮的审查和修复,直到其作者停止它。

当我们对审查者一直标记的内容运行 git blame 时,大约 59% 是自审查者第一轮以来就存在的代码。审查者很少发现新 bug,它每轮都在发现一些更旧的 bug。

我们自己让它变得更糟。我们已经习惯于默认运行几轮,因为每一轮都会发现一些新东西。这在有风险的更改上可能是值得的,但不是每个 PR 都如此。团队现在跟踪通过轮次和召回率,并改变了重新审查:

审查代理还在现有代码上每晚运行,帮助我们在旧 bug 出现在其他地方之前捕获它们。

让一位资深工程师从深度工作中抽身来捕获一个常规错误,其代价远高于自动审查。在 Anthropic,我们的工作已经从阅读每个 diff 转变为机器不擅长的决策:

代码审查的第二项工作一直是传播代码库理解。阅读队友的 diff 是你了解什么改变了以及各部分如何组合的方式。如果机器完成了大部分阅读,那么任何人如何学习代码?

我们没有为此的正式流程。团队中没有人对 Claude Code 保持完整的心理模型,我们认为没有人需要这样做。当有人想了解代码库的某一部分时,他们让 Claude 为那个确切的切片写一个解释器。这需要几分钟,并反映今天的代码。

我们中的一些人更进一步,让 Claude 构建一个小工件,可视化代码的那部分,并以那个人喜欢学习的方式教授它。

如果目标是把人的注意力花在刀刃上,这比逐行阅读琐碎的 diff 要好得多。一行文案的改动几乎教不了你什么。而针对你即将修改的模块的说明则能让你学到很多。我们默认在开放的 Slack 频道中工作的文化也有帮助,因为你能在别人构建时看到他们在做什么。

如果你提交了一个小型或中型的改动,而仍然出了问题,团队惯例通常是由你来修复。有几件事可以防止情况恶化:

所有权也是共享的。团队中许多人在开放频道中工作,任何人都能看到别人在构建什么、接手一个讨论串,或让 Claude 去填补一个缺口,反馈也来自不拥有该代码的人。这种开放性是在没有对每一行都设关卡的情况下保持高质量的重要原因。

智能体让启动事情变得廉价,所以有些工作不应该落地。通常频道里会有人问为什么,指出之前的某个决定,或建议一条更简单的路径,然后作者关闭或重塑这个 PR。

既然代码写起来很快,关闭 PR 不会让人觉得是损失。诀窍是在讨论串中尽早提出不同的方向,而不是在已完成的 PR 上作为阻塞性评论提出。

与你的团队一起做到这一点所需的大部分组件今天已经存在。

CLAUDE.md

,再加上运行格式化和 linter 的钩子。/code-review

和 /security-review

在本地运行,或使用全新上下文的子智能体审查。REVIEW.md

,并将重复的审查评论移入其中。REVIEW.md

几周,然后再扩大范围。Code Review 的公告说,批准拉取请求仍然是人的决定;该产品发布的是发现,而不是批准。我们自己的仓库走得更远,让所有者决定哪些低风险改动仅凭自动化检查即可合并,而这条线还在不断移动。

当审查遗漏了某些东西时,我们会问模型面前缺少了什么,并把修复放入 CLAUDE.md

、一个技能或一项新检查中。目标没有改变:每次改动花费更少的人力时间,并且回滚次数不比以前多。

如果你的团队让智能体打开拉取请求,我们想听听你自动化了哪些检查、哪些仍然需要人,以及你认为我们哪里做错了。

感谢 Emma Webb、Michael Segner 和 Amie Rotherham 的审阅。