← 返回动态
How building software is changing at Anthropic
AI辅助开发可提升效率,小团队模式仍有效。
关键标注
关键数据
Bun有535,496行Zig代码。用另一种语言重写需要一个小型工程师团队整整一年时间。
关键数据:Bun代码库规模及传统重写所需时间,凸显AI重写的效率提升。
原文全文 (高亮 = 关键标注)
在Anthropic,软件构建方式正在如何改变
深入探讨这家领先AI实验室在软件制作方式上的变化。越来越多的代码审查和测试由AI完成,双比萨团队依然活跃,以及更多细节。来自Anthropic内部的消息
大幅改进的AI工具正在改变我们构建软件的方式,我想一窥软件工程的未来可能如何在它的影响下展开。还有什么地方比科技界最“AI化”的团队——AI实验室本身——更适合观察呢?
因此,我访问了两家领先的AI实验室,了解团队和工程师的日常工作。在这篇文章以及即将发布的后续文章中,我将分享我所了解的AI如何重塑我们许多人习惯的软件工程原则——以及在AI浪潮中哪些方面基本保持不变。
在后续文章中,我们将比较Anthropic和OpenAI的发现,看看他们的工作方式可能对软件工程的总体方向意味着什么。
感谢Anthropic让我参观他们在旧金山的实验室。我与四个人进行了交谈:
- Katelyn Lesse,Claude平台工程主管,其组织拥有Claude运行的基础设施
- Jarred Sumner,Bun的创建者,现在在Anthropic从事Bun和Claude Code的工作
- Thariq Shihipar,负责Claude Code工程和教育
- David Hershey,在Anthropic的应用AI组织担任类似销售工程师的角色,与Cursor、Cognition和Perplexity等客户合作
感谢他们,我了解了这家领先AI实验室的发展方向——可能也是整个行业的方向。
在继续之前,《务实工程师》将在接下来的一周半内放暑假。这意味着本周四没有文章,下周也没有文章。感谢您的理解和支持!
回到今天的深度探讨,我们涵盖:
- 复杂且耗时:Claude托管代理。最复杂的项目之一花了Claude平台团队六个月才发布,并在代理基础设施层面创建了一个新的原语。基础设施项目仍然需要在途中重新架构,并且需要时间才能做好。
- 十二个月的项目在11天内完成:Bun重写为Rust。将超过50万行的项目迁移到另一种语言过去需要一个小团队一年时间,使其不切实际。借助Fable和16.5万美元的令牌,该项目创建者最近在不到两周内完成。
- 工程实践的变化。在这家拥有超过3500名员工的AI实验室内部,原型设计更加灵活,验证比实现更耗时,代码审查和测试越来越多地由AI完成。
- 团队层面的变化。设计更加持续而非前期,团队处理更多项目,每个项目最多两名工程师,等等。
- 仍然相同:双比萨团队,规划很重要,PRD在复杂项目中相关,上下文切换是一个挑战,编码与测试的时间比例变化不大。
- 改变“杰出”软件工程师的原型?深入理解,包括比你工作层面低一层的知识,以及协调工作的能力,都是有价值的。
- AI会取代软件工程吗?在实验室中,软件工程师越亲身体验AI,他们就越不担心自己的工作会消失。
1. 复杂且耗时:Claude托管代理
Claude平台团队在过去一年中最复杂的项目是构建Claude托管代理,这是一个用于生产代理的预构建框架,运行在由Anthropic管理的云基础设施上,或者运行在你团队自己的基础设施上,使用你选择的任何沙箱。该项目从构思到4月发布大约花了六个月时间。Claude平台工程主管Katelyn Lesse分享了故事。
Claude 平台
该团队位于模型/加速器层(Claude 模型在 GPU 上运行)和产品/应用层(包括 Claude Code 和 Claude Cowork 等产品)之间:
Katelyn 谈平台团队的职责:
“我们处于‘token 热路径’上。提示词输入后,我们对其进行分词。然后,诸如安全防护和计费等功能都在我们的层中完成。”
Claude 团队所称的“平台”,我更倾向于理解为“API”。Claude 平台运营 API,并承担 API 应有的职责。当然,该团队的工作不止于此,Claude Managed Agents 就是我们在本文中介绍的一个案例。
平台层正在从 Python 迁移到 Rust。最初,该层使用 Python 编写,原因与 AI 公司通常的选择一致:Python 是一种便捷的语言,且 AI 研究人员已在使用 Python,这有助于快速迭代。但 Python 是单线程的,在大规模场景下,当 API 处于高负载时,其性能不如 Rust。
满足基础设施需求
Katelyn 表示,该项目源于客户希望拥有自己的“基础设施”:
“我们最初提供了一种模式:你通过一个 API 定义 agent,再通过另一个 API 启动与 agent 的会话。但当前世界的实际需求是人们运行自己的基础设施。因此,我们开始构建自托管沙箱。
然而,我们随后从许多客户那里听到,他们正在尝试自行拼凑基础设施,运行自己的‘基础设施’,这启发了我们开发 Claude Managed Agents。”
最重要的部分:规划
Katelyn 表示,在这个项目中,最重要的事情是规划:
“有些产品可以直接进入原型设计阶段,但有些产品则需要从正确的架构设计开始。例如,如果我们构建一个 TypeScript CLI——对于需要构建的内容来说相当简单——我们可以直接进行原型设计。但对于 Claude Managed Agents,我们首先需要弄清楚我们要做什么。
当然,我们为 Managed Agents 做了一些前期原型设计:进行了一些尝试和探索。但原型设计本身更多是为了理解需求。
我们的规划过程更像典型的 AI 之前的规划过程。你知道每个团队都有这样的项目:每个人都提出类似想法的某个版本,大家不断讨论和酝酿,直到最终付诸实施?Managed Agents 对我们团队来说就是这样的项目。当我们启动该项目时,我们已经有了可追溯到两年前的关于想法和建议的文档。
规划完成后,项目正式启动,并创建了 PRD(产品需求文档):
“最终,是我们 API Agents 团队的产品经理和技术负责人决定启动这个项目。我们会聚在一个房间里,逐项讨论并达成一致。但这不仅仅是我们的事:我们还需要与业务部门、其他云提供商以及其他工程团队协调。例如,平台组织内有一个沙箱团队:由于该产品会生成大量沙箱,因此我们咨询了该团队关于 Managed Agents 的设计。
和以前一样,我们有一个 PRD,它是一个 Google 文档。我们使用 Google 文档是因为需要协调所有相关人员。这种做法并未消失。
同样,我和我的产品对应方会进行产品评审。”
AI 之前的一些流程,如 PRD,在当今的复杂项目中仍然有用,可以让大量人员保持一致。
首先为内部客户构建
规划完成后,团队决定进行“探索”并压力测试想法和架构,通过构建基于 Web 的 Claude Code 后端来实现。使用 agent 框架远程执行代码与他们想要为客户解决的问题具有相似的形态。他们的思路是首先为 Claude Code 团队解决这个问题,然后再以更通用的方式为客户解决。
内部团队比AI出现之前更加灵活。Katelyn:
“在AI之前,我们可能会给Claude Code团队一堆庞大的需求文档,然后他们再给我们一堆文档。现在容易多了:我们团队有人构建了几个组件,带到Claude Code团队那边,他们就开始围绕它进行开发。我们可以弄清楚这个组件如何接入他们产品的这一部分,反之亦然。让这个产品的第一个内部版本启动并运行,过程更快、更简单。
与其他团队在接口上保持一致仍然很重要,而且更容易了。过去,你必须带着一个完全规格化的接口来使用。现在,我们可以更灵活地操作:我们可以先搭建一个影子流量的存根服务,然后与Claude Code团队一起逐步完善接口。他们做了一些开发并给出反馈,我们在构建接口下的服务时进行修改,然后再回去让它正常工作。”
他们为Claude Code的移动应用启动了一项服务,用于创建沙箱、启动Claude Code并运行它。该服务投入生产,Claude Platform团队从中吸取了经验。
中途重新架构
许多工程师可能都熟悉这样一个场景:在规划项目并开始实施后,你发现需要更改架构。这个项目也遇到了这种情况。
平台团队最终根据Claude Code“试探性项目”的经验对Managed Agents进行了重新架构。重新架构意味着将Claude的“大脑”及其框架与“手”(执行操作的沙箱和工具)和“会话”(事件日志)解耦。每个部分都成为一个接口,彼此之间很少做假设。
团队还围绕保险库和凭证构建了一个抽象层。凭证可以安全地存储在保险库中。所有使用凭证的调用都通过一个拥有会话令牌的代理进行。代理从保险库中获取正确的凭证:凭证永远不会被代理、沙箱或会话看到。凭证仅在调用服务时在出口边界注入:
内部“吃狗粮”有助于发现需要解决的难题。几个例子:
- 可靠性和可扩展性:对于代理来说,这些真的很难做好,因为如果与沙箱的连接丢失,整个代理就会死亡,你会丢失状态
- 凭证和访问控制:也很困难且有问题,尤其是在首次构建服务时
Managed Agents团队分享了更多关于这个重新架构项目的信息。
该项目耗时约六个月,绝非快速过程。Katelyn强调,在AI之前,这样的项目可能需要两年时间。Managed Agents是Claude Platform团队构建的最大项目之一,而且比看起来更复杂:例如,增加了对在AWS、GCP和Azure上运行代理的支持。
2. 十二个月的项目在11天内完成:Bun重写为Rust
如前所述,Jarred Sumner是Bun的创建者,Bun是一个流行的JavaScript运行时,目前每月有2200万次下载,并且依赖Claude Code。
Bun是用Zig编写的,Zig是一种高性能、高效的语言。然而,它并不内存安全,内存问题不断出现。Jarred认为将项目重写为同样高性能、内存安全的语言(如Rust)可能是一个选择——尽管过去这样的重写往往以失败告终。Jarred(强调为我所加):
“从历史上看,重写是一个糟糕的主意。排除注释,Bun有535,496行Zig代码。用另一种语言重写需要一个小型工程师团队整整一年时间。这意味着在那段时间内冻结错误修复、安全修复或功能开发。要获得可交付成果,风险最小的方法是机械地将Zig移植到Rust,尽量减少行为变化,并使用我们已有的用于测试Bun的相同测试套件。”
幸运的是,Bun 自身的测试套件是用 TypeScript 编写的,这意味着它不依赖于运行时的编程语言。
我们无法考虑一年内对用户零影响的选择。因此,通过代码风格来强制执行以修复稳定性问题是我们最好的选择,这也是我们在将受 Rust 启发的智能指针添加到 Bun 代码库时的计划。
但老实说,我并不想这样做。自制的智能指针比 Rust 的体验更差,而且没有任何保证。
但后来,Jarred 询问 AI 是否能完成繁重的工作,并想知道迁移速度能提高多少。最终,他在 11 天内完成了从开始到合并的重写,使用了 64 个并行代理,按 API 价格花费了 165,000 美元的 token。以下是 Jarred 对其 AI 密集型重写的比较:
“手动完成这项工作,我认为需要三位对代码库有全面了解的工程师大约一年的时间,在此期间我们将无法改进 Node.js 兼容性、修复错误、修复安全问题或实现新功能。我们绝不会那样做。现实的选择是什么都不做,永远修复本文开头提到的错误。”
这个项目远不止输入“...不犯任何错误”的提示:
- Jarred 制定了详细的迁移计划和风格指南
- 他设置了项目,使代理不使用 Git worktrees(他发现这很慢),而是在同一代码库的不同文件上工作
- 他创建了一个编排系统,每个 AI 代理提出更改建议,但不修改文件以避免冲突;一个编排 AI 代理创建提交
- 大部分时间和 token 用于修复编译错误、测试和验证一切正常
- Bun 本身有一个非常强大的测试框架:当所有测试通过时,这是一个高置信度的信号,表明重写有效
- 关键是,Jarred 是 Bun 的终极领域专家:他创建了这个项目,并且比任何人都更了解代码库
这次重写已投入生产,并为今天的 Claude Code 提供支持。
我们在《我们能从 Bun 使用 AI 快速重写 Rust 中学到什么》中对此进行了更多讨论。
3. 改变工程实践
那么,与 AI 时代之前相比,Anthropic 的团队构建软件的方式发生了哪些变化?这是本文的问题,似乎很多事情都不同了。让我们逐一分析:
AI 实验室特有的实践
在 Anthropic 等 AI 实验室中,一些像呼吸一样正常的事情,从外部视角来看却显得不同:
- 每个人始终运行多个 AI 代理。运行 3-10 个并行代理是常态。我交谈过的人都在后台或云端运行他们的代理。
- 没有 token 预算,使用情况不被跟踪。AI 实验室与其他所有人的一个主要区别是,确实没有 token 限制或促进 token 最大化的 token 排行榜;人们已经一直在使用代理。
- 非常高的自主权。AI 实验室内部的工作变得更加结构化,但与大型科技公司和大多数初创公司相比,仍然有巨大的自主权。当每个人都有无限的 token 时,原型化任何想法都非常容易。
原型设计和“试探”更加流畅
为 Claude Managed Agents 原型化早期方法的速度快了数倍。同样,Katelyn 告诉我,实现 Claude Code 移动端后端的“试探”也比 AI 时代之前快得多。
验证比实现花费的时间更长
Jarred 在 11 天重写为 Rust 的过程中指出了实现与验证之间的划分。大致如下:
将代码从 Zig 重写为 Rust 的“实现”部分花费了大约 15% 的时间,而 85% 的时间用于修复问题:使其编译通过、修复测试、验证其正常工作。
大多数token不再用于实现
Thariq:
“我们发现很少有token用于实际实现。大部分token用于发现未知、原型设计、模拟,以及验证和测试。”
Jarred对Bun的重写也印证了这一点:他花在修复实现和验证其正确性上的token比花在实现本身上的还要多!
AI进行代码审查和更多测试
Jarred:
“用智能体批判代码和测试是一种我们更常采用的新方法。当你合并大量代码时,我考虑了很多关于信任的问题。如何每天合并100多个PR,并确保代码正常工作?在这种速度下,你需要在无法亲自阅读所有代码的情况下信任代码。我认为这涉及几个方面:
代码审查:它需要非常好且自动化。我显然是在自夸,但我发现Claude的代码审查确实非常好。Claude的代码审查能捕获那些我需要仔细阅读代码一小时才能发现的bug。但缺点是它很昂贵!
安全扫描:对于这次Rust重写,我们运行了11次Claude安全扫描器。
模糊测试:我们还进行了不同类型的模糊测试,让Claude为解析器模糊测试等编写模糊测试器。
在编码之外的不同进程/会话中运行测试,是建立对代码信任的一种方式。我期待更多这样的做法。”
新模式:将工作分发给AI
Jarred描述了他的一种新工作方式:
“我正在使用的一种新方法是同时将大量工作分发给多个Claude。我在Bun重写中这样做了,但我也将其用于其他工作。这种方法对我来说非常有效,我觉得它还没有被充分利用。”
由智能体驱动的省时自动化更加普及
Jarred列出了Bun团队为以小型团队运行活跃的开源项目而设置的几种省时自动化,同时团队在Claude Code上工作:
- 每当有人提交issue时,Claude会运行以尝试复现该问题。如果成功,它会启动另一个容器,然后尝试修复问题并提交PR。
- 负责提交PR的智能体必须编写一个测试,该测试在系统版本(未打补丁的版本)的Bun中失败,而在打了补丁的调试构建中通过,之后才允许提交PR。
- 还有其他自动化,比如如果没有测试,PR会被自动拒绝;所有linter都会运行:Claude Code审查、CodeRabbit的代码审查都会运行,智能体在GitHub pull request上来回互动。
PR自动合并:即将到来?
当所有质量门通过时,PR会手动合并,但这在某个时候可能会变成自动的。一旦上述所有检查通过,所有(AI)代码审查评论得到处理,新代码添加了测试等。有趣的是,很多GitHub活动是Claude与Claude之间的对话!
但在低风险情况下,手动合并可能会消失,至少对于Bun项目是这样。Jarred告诉我:
“今天,由人按下‘合并’按钮,但几个月内,我预计:
- 自动审查者LGTM
- → 另一个拥有新上下文窗口的Claude判断是否简单且影响范围小
- → 如果是:自动合并!”
用每一代模型检验假设
在Anthropic内部,团队不断检验他们的先验假设。Thariq给出了一个有趣的例子:
“对于智能体,你必须重新审视你做出的任何假设,因为随着新一代模型的出现,这些假设可能会改变。因此,我们最近删除了Claude Code系统提示的80%,因为模型变得更聪明了。
使用HTML是另一个我们需要重新审视的假设。HTML是Claude比我们许多人预期的要聪明得多的东西之一。我开始更喜欢HTML作为输出格式而不是Markdown,并且看到Claude Code团队的其他成员也在使用它。”
与Markdown相比,HTML可以传达更丰富的信息,HTML文档更易于阅读和共享。”
4. 团队层面的变化
在Anthropic,与AI时代之前相比,工程团队的运作方式也发生了变化。