73% PR 由AI生成!Claude Code之父对话Spotify:2900名工程师每天部署4500次,坐地铁都能提交代码
<p data-type="paragraph">去年 9 月,Anthropic Claude Code 创始人 Boris Cherny 曾与 Spotify 工程副总裁 Niklas Gustavsson 谈到 AI 编程工具的未来。当时,Nicholas 作出一个激进判断:到了年底,开发者可能已经不再需要传统 IDE。</p><p data-type="paragraph"></p><p data-type="paragraph">Boris 的第一反应是,这几乎不可能发生。在他看来,AI 编程工具完全取代传统 IDE,或许需要两年,但不可能只用两个月。然而仅仅两个月后,Boris 发现,自己真的不再使用传统 IDE,整个工作方式也随之彻底改变。</p><p data-type="paragraph"></p><p data-type="paragraph">“这种变化,是我从事这类工作近 30 年来从未见过的。”Boris 在两人最近的一次谈话中说道。</p><p data-type="paragraph"></p><p data-type="paragraph">如今,Spotify 已经成为全球范围内将 AI 编程大规模嵌入软件研发体系的代表公司之一。在这家拥有约 2900 名工程师的流媒体巨头内部,约 73%的 PR 已经可以直接由 AI 生成,AI 工具推动 PR 提交频率提高了 75%以上。</p><p data-type="paragraph"></p><p data-type="paragraph">Spotify 经历了一场几乎“肉眼可见”的研发方式重构:从 IDE 逐步退出日常开发现场,到智能体在后台同时运行;从工程师亲自编写和修改代码,到模型完成大部分实现并通过自动化验证进入生产环境;再到原本需要数周甚至数月的功能验证,被压缩到数小时。</p><p data-type="paragraph"></p><p data-type="paragraph">但 Spotify 的实践并不是简单地给工程师购买一套 Claude Code 订阅。其背后,是持续多年的代码自动化基础设施、代码库标准化、自动化测试、持续集成、权限系统和验证闭环建设。</p><p data-type="paragraph"></p><p data-type="paragraph">Spotify 的经验表明,模型能力只是起点,真正决定 AI Coding 能否在大型企业落地的,是企业是否已经把代码、测试、工具和研发流程改造成一个可以被智能体理解、调用和验证的系统。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>太长不看版</strong></p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Q:你们总是比其他人更早看到未来,这与文化有关还是和参与团队有关?</strong></p><p data-type="paragraph"></p><p data-type="paragraph">A:大约五六年前,我们发现公司代码库的增长速度远远超过工程师人数的增长速度,大约快了 7 倍。这意味着,随着时间推移,需要维护的代码越来越多。而 Spotify 是一家不缺产品创意的公司,我们一直有大量想要交付给用户的功能。如果团队长期被维护工作拖住,那显然不是一个理想状态。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Q:很多公司常犯的一个错误,是对验证闭环的投入不足。</strong></p><p data-type="paragraph"></p><p data-type="paragraph">A:这确实非常普遍。当我们开始自动生成并提交针对源代码的 PR 时,就必须改变对各团队的要求。团队可能不再参与每一次变更。我们会自动合并其中大多数变更,相关团队甚至可能根本不会看到这些 PR。这意味着,我们必须构建更完善的自动化测试体系,确保所有软件都能够承受这种自动化变更。这项投入对我们帮助非常大。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Q:你们会如何考虑 ROI?</strong></p><p data-type="paragraph"></p><p data-type="paragraph">A:最初关于 ROI 的讨论相对简单,因为我们看到的提升实在太大了。但随着技术逐渐成熟、成本结构不断改善,大家对 ROI 测算精度的要求也越来越高。其中一部分是衡量生产力提升了多少;另一部分,则是为了获得这些提升,究竟付出了多少成本,包括消耗了多少 Token、投入了多少小时,以及最终产生了多少有效产出。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Q:对其他公司的 CTO、VP 以及工程管理者,有什么建议?</strong></p><p data-type="paragraph"></p><p data-type="paragraph">A:除了自动化测试和验证,标准化同样重要。我们一直在推动代码库变得更加一致,也在推动团队统一使用的工具和框架。这些投资最初是为了降低人类工程师的工作复杂度,提高人的生产力。但我们发现,这些做法同样可以非常顺利地迁移到智能体上。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Q:过去大量花在实现上的时间被释放出来了。</strong></p><p data-type="paragraph"></p><p data-type="paragraph">A:我们现在正在大力投资原型开发。而且,这项投入不仅面向工程师,也面向非工程人员。目前,我们的一位联合 CEO 也在这个内部应用商店里提交了原型。</p><p data-type="paragraph"></p><p data-type="paragraph">下面是两人详细对话,我们进行了翻译并在不改变原意基础上进行了删减,以飨读者。</p><p data-type="paragraph"></p><h2 data-type="heading" data-id="heading0">还没有 Claude 时就想要代码自动化</h2><p data-type="paragraph"></p><p data-type="paragraph"><strong>Boris:我还记得,去年大概 9 月的时候和你聊过一次,你当时说了一句类似的话:“我觉得到了年底,可能已经没人再用 IDE 了。”我当时听完就在想,“这也太疯狂了,绝对不可能发生”。我能想象这种变化可能会在两年左右发生,但两个月实在太夸张了。可两个月后,我发现自己真的不再用了,整个工作方式也彻底改变了。这种变化,是我从事这类工作近 30 年来从未见过的。</strong></p><p data-type="paragraph"></p><p data-type="paragraph">Nicholas:有意思的是,我们公司内部的感受和外界几乎完全一样。只不过我们可能领先了几个星期。也就只有几个星期,但感受确实完全一样。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Boris:现在智能体和大模型正在带来巨大变化。在我看来,无论是你个人的使用方式,还是 Spotify 的使用方式,都处在行业最前沿。你第一次真正感到“AGI 来了”是什么时候?</strong></p><p data-type="paragraph"></p><p data-type="paragraph">Nicholas:我觉得自己经历过好几次这样的时刻,具体取决于我们当时试图解决什么问题。</p><p data-type="paragraph"></p><p data-type="paragraph">大模型刚出现时,我们就比较早地尝试用它们自动完成代码变更。最开始,这件事非常难。但过了一段时间,随着我们逐渐摸索出如何使用大模型、评判模型以及其他方法,我们开始得到一些非常令人振奋的结果。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Boris:那已经是几年前了?</strong></p><p data-type="paragraph"></p><p data-type="paragraph">Nicholas:对。那时候还没有 Claude,应该算是 GPT 非常早期的阶段。我们当时得到的结果,并不是已经可以解决所有问题,但它让我们看到了这项技术未来可能走向哪里,那肯定算是一次重要时刻。</p><p data-type="paragraph"></p><p data-type="paragraph">但对我个人写代码而言,真正的突破时刻可能是去年 11 月或 12 月发布的 Opus 4.5。它从一种“聪明的自动补全工具”,变成了一个我真的可以把现实问题直接交给它处理的东西,而且我不再需要做太多提示词工程。</p><p data-type="paragraph"></p><p data-type="paragraph">对我来说,最大的变化还在于,我终于不需要再亲自编辑代码了。在那之前,我的工作流通常是让模型先写出大约 80%的代码,或者根据模型能力写出 70%,然后我还是要进入 IDE,完成最后的修改。后来,我突然不再需要做这一步了。那种感觉真的很疯狂。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Boris:我觉得这也是为什么那次变化让人感觉像一次巨大跃迁。那你现在的工作流是什么样的?</strong></p><p data-type="paragraph"></p><p data-type="paragraph">Nicholas:我的用法应该算比较基础。我通常会在终端里开很多个 Tmux 会话。每当我要做一些工作时,后台通常都会同时运行多个智能体。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Boris:你一般会开多少个终端标签页?</strong></p><p data-type="paragraph"></p><p data-type="paragraph">Nicholas:大概 5 到 10 个。我还会使用一些窗格,因为我喜欢单独保留一个终端来查看代码差异之类的信息。所以,我现在通常会配置成一个矩阵式工作区:一边是多个 Claude 会话,另一边是与它们对应的终端,并配合多个 Git 工作树使用。</p><p data-type="paragraph"></p><p data-type="paragraph">我们现在有几个非常大的单体代码仓库,而且还在逐步向这种架构迁移。但与此同时,我们仍然保留了数千个规模较小的多代码仓库。</p><p data-type="paragraph"></p><p data-type="paragraph">我的大部分工作都发生在这些单体代码仓库中,所以在任何时间,我通常都会同时运行几个 Claude 会话和终端。如果临时需要进入某个多代码仓库,我就会在那里再打开一个临时的 Claude 会话。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Boris:你觉得对于 Claude Code 来说,单体代码仓库和多代码仓库,哪一种更适合?</strong></p><p data-type="paragraph"></p><p data-type="paragraph">Nicholas:老实说,一开始我对单体代码仓库和智能体的组合有些担心。因为我们在使用早期工具时,遇到过代码索引方面的问题。而且,我们的代码仓库规模确实非常大,仅后端单体代码仓库就有超过 2000 万行代码。</p><p data-type="paragraph"></p><p data-type="paragraph">但事实证明,Claude 在这些代码仓库中的表现非常出色。我们发现,Claude 非常善于查看代码仓库中的其他代码,并从中寻找解决当前问题的参考和启发。</p><p data-type="paragraph"></p><h2 data-type="heading" data-id="heading1">代码增长速度是工程师人数的 7 倍,被迫寻找自动化解法</h2><p data-type="paragraph"></p><p data-type="paragraph"><strong>Boris:我还想聊聊你们构建的一些基础设施。Spotify 构建了 Honk(其内部开发的一套 AI 自动化程式开发系统)。从最早开始尝试模型到后来构建 Honk,再到基于 Agent SDK 开发后台智能体,你们总是比其他人更早看到未来。这和 Spotify 的文化有关,还是和参与这项工作的团队有关?</strong></p><p data-type="paragraph"></p><p data-type="paragraph">Nicholas:大约五六年前,我们发现,公司代码库的增长速度远远超过工程师人数的增长速度,大约快了 7 倍。</p><p data-type="paragraph"></p><p data-type="paragraph">这意味着,随着时间推移,需要维护的代码越来越多。而 Spotify 是一家不缺产品创意的公司,我们一直有大量想要交付给用户的功能。如果团队长期被维护工作拖住,那显然不是一个理想状态。</p><p data-type="paragraph"></p><p data-type="paragraph">所以,我们开始尝试尽可能自动化这些维护工作。其中很多工作其实非常枯燥,比如迁移到最新的 Java 版本、升级依赖库,或者完成类似的更新,还有很多工作是在整个代码库中把某个 API 迁移到另一个 API。于是,我们构建了一套称为“代码舰队管理(fleet management)”的基础设施。</p><p data-type="paragraph"></p><p data-type="paragraph">在此之前,每当需要进行一次迁移时,我们通常会把迁移说明或者教程发给所有团队,然后要求每个团队手动完成自己负责组件的迁移。但后来,我们开始想能不能换一种方式,直接对分布在数千个代码仓库中的整个代码库统一执行变更,而不是让每个团队重复完成相同的操作。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Boris:也就是说,数百个团队要在数千个组件上手动执行同一个操作。</strong></p><p data-type="paragraph"></p><p data-type="paragraph">Nicholas:没错。每次迁移都可能持续好几个月,我们一年可能只能完成 10 次左右这种迁移,甚至只能勉强保证自己仍在使用各类框架受支持的版本。所以,我们开始自动化这项工作,并为此构建了完整的基础设施。后来,我们合并了数以百万计的这类 PR。</p><p data-type="paragraph"></p><p data-type="paragraph">不过,这些变更最初全部依赖确定性脚本。脚本会被应用到代码库中,完成相应的代码修改或配置修改。但我们很早就发现,代码中的接口、调用方式和依赖关系极其复杂,一旦试图修改代码,难度会迅速上升。所以,我们很快就碰到了上限:仅靠确定性方法,究竟能完成多复杂的代码变更?即使只是替换一个方法或者 API,当它存在 5 种不同调用方式时,问题也会变得非常复杂。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Boris:也就是说,你们当时主要依赖传统的静态分析和抽象语法树转换来完成这些工作?比如一个 API 的返回结果可能先被赋值给某个变量,那么接下来就需要追踪变量和状态。</strong></p><p data-type="paragraph"></p><p data-type="paragraph">Nicholas:完全正确。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Boris:这会非常麻烦。</strong></p><p data-type="paragraph"></p><p data-type="paragraph">Nicholas:是的。为了迁移代码,我们编写的每一个脚本,最终都会膨胀到数千行,用来处理代码里的各种边界情况。这也是为什么我刚才提到早期大模型几乎一出现,我们就开始思考能不能把它们用到这个问题上。</p><p data-type="paragraph"></p><p data-type="paragraph">最开始的效果并不好。一方面是因为当时的模型能力还不够,另一方面是因为我们解决问题的方式也非常天真。我们基本上只是把代码直接放到模型面前,然后要求模型一次性完成修改。结果当然不理想。</p><p data-type="paragraph"></p><p data-type="paragraph">后来,模型能力不断提升,我们对这类问题的理解也逐渐深入。我们开始使用大模型评估器检查输出结果是否符合预期,也开始用不同方式拆解和分解任务。我们做了非常多轮迭代,也在公司内部进行了大量实验,尝试用不同方法解决这个问题。后来,我们逐渐把这些方法整合起来,最终形成了今天所说的 Honk。</p><p data-type="paragraph"></p><p data-type="paragraph">Honk 最初和现在非常不一样。它一开始并不是构建在 Claude 之上的,内部有很多我们自己开发的东西。但它让我们第一次看到了一线曙光:这个问题确实是可以解决的。</p><p data-type="paragraph"></p><p data-type="paragraph">此后,我们又对 Honk 做了很多轮迭代。现在我们发布的版本是 V2,但实际上它可能已经是 V8 左右了,只不过我们没有认真记录每一轮版本编号。</p><p data-type="paragraph"></p><p data-type="paragraph">Honk 一开始主要用于自动完成代码变更,并在所有代码仓库中调度和编排这些变更。但工程师很快就意识到,它也可以用来做其他事情。例如,有人希望直接在 Slack 里提到 Honk,让它帮自己完成某项任务,或者用它处理其他类似工作。发展到今天,Honk 已经成为 Spotify 内部一个使用范围非常广泛的工具。</p><p data-type="paragraph"></p><h2 data-type="heading" data-id="heading2">AI 编程最重要的不是生成,而是验证</h2><p data-type="paragraph"></p><p data-type="paragraph"><strong>Boris:能不能介绍一下 Honk 的整体架构?它主要由哪些部分组成?刚才你提到,其中有一个负责写代码的智能体,这个部分是基于 Claude Agent SDK 构建的吗?</strong></p><p data-type="paragraph"></p><p data-type="paragraph">Nicholas:是的。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Boris:除此之外,你们还曾经设置过验证步骤,比如一个智能体式验证器。能不能详细讲讲?</strong></p><p data-type="paragraph"></p><p data-type="paragraph">Nicholas:Honk 以前确实有一个评估器,但后来我们把它移除了。我们发现,从 Claude 4.5 开始,智能体和模型本身已经足够强,不再需要额外的评估器。不过,在 Honk 的早期版本中,评估器非常重要。如果我没记错的话,它让 PR 的成功率从大约 20%到 30%,提高到了 80%左右。</p><p data-type="paragraph"></p><p data-type="paragraph">这是一次非常显著的变化。但正如我们之前讨论的,后来模型能力追了上来,Agent harness 也追了上来,所以我们现在已经从 Honk 中移除了这个评估器。</p><p data-type="paragraph"></p><p data-type="paragraph">从架构上看,Honk 其实相当简单。Claude Agent SDK 运行在一个 Kubernetes 容器组中,并拥有一组工具的访问权限。在 V2 之前,这些工具是提前定义好的许可列表,只有我们信任的工具才会开放给智能体。到了 V2,用户可以自行添加工具。因此,现在智能体可以调用 Spotify 内部的任何工具。</p><p data-type="paragraph"></p><p data-type="paragraph">其中最重要的工具之一,是它可以执行验证流程,比如运行持续集成构建。这些构建既可以运行在 Linux 上,也可以运行在 macOS 上。macOS 对我们尤其重要,因为所有 iOS 开发都需要在 macOS 环境中完成构建。</p><p data-type="paragraph"></p><p data-type="paragraph"><strong>Boris:这里所说的验证,只是完成构建吗?还是你们会运行完整流程,比如启动 iOS 模拟器,让模型打开应用并进行操作?整个验证能深入到什么程度?</strong></p><p data-type="paragraph"></p><p data-type="paragraph">Nicholas:它可以执行这类测试。我们确实有一些场景,会把模拟器和 Claude 集成起来,自动完成从 Figma 设计稿到用户界面实现的整个过程。例如,我们一直在用这种方式,把电视端应用从现有的 iOS 应用移植过去。</p><p data-type="paragraph"></p><p data-type="paragraph">Boris:我觉得验证是一个我们经常讨论的话题。但在这种闭环开发中,智能体拿到任务后,可能需要展开任务、拆解任务,并在没有人类参与的情况下完成大量工作。这时,验证就是最重要的一件事。我看到很多公司常犯的一个错误,就是对验证闭环的投入不足。</p><p data-type="paragraph"></p><p data-type="paragraph">Nicholas:这确实非常普遍,对我们来说也同样如此。在推进这项工作的过程中,我们对工程实践做出的一项重大调整,就是强化自动化测试。</p><p data-type