把 bug 当病人、把编码代理当医疗团队的五个月实践
摘要
Cockroach Labs 分享其为期五个月的实验:将 bug 视为病人、把编码代理组织成一支"医疗团队"(MOLT Sinai),使 MOLT 新增 IBM Db2 支持仅用不到两天、花费 $4172,相比此前 Oracle 支持耗时 9 个月、成本约 $16 万美元,速度快 164 倍、便宜 38 倍,且无人工编写代码、测试覆盖率相当。
暂无内容
查看缓存全文
缓存时间:
2026/10/11 00:35
# 五个月:把 Bug 当病人治,把编码代理当医疗团队用
来源:https://www.cockroachlabs.com/blog/experiment-running-hospital-code/
在四月的一个周三晚上到周五下午之间,MOLT (https://docs.cockroachlabs.com/docs/molt/migration-overview)——Cockroach Labs 发布的数据库迁移工具,用于将数据库迁移到 CockroachDB——获得了从 IBM Db2 源进行迁移的能力。
Db2 是最早可用的商用关系型数据库之一,拥有丰富的 SQL 方言、复杂的类型系统以及原生的线协议。在 MOLT 中支持 Db2 意味着需要一个新的模式转换器、一条新的 Fetch 路径用于拉取数据并将其导入 CockroachDB、一条新的 Verify 路径用于导入后比对数据、一个 vendored 的 ANTLR 语法、一个用于 CI 的 Docker 镜像,以及超过一万行的测试 fixtures。当我们 2024 年为 MOLT 工具添加 Oracle 支持时,类似的工作耗时 9 个月,工程时间成本约为 16 万美元。
而 Db2 只用了不到两天,而且没有人类编写任何代码。Token 账单为 $4,172:快了 164 倍,便宜了 38 倍。
一切始于一个描述需求的 GitHub issue:
支持 Db2 LUW 的 convert/fetch/verify #526 (https://images.ctfassets.net/00voh0j35590/6MhMseiC9Zdcvi77psvfsC/69471e2d6acea6a1ccdcc46ba0bd00e0/a1fcabf4-d49c-420f-afc2-adb321ce0209.png)
随后,一个规划代理读取了它,判断这个任务太大无法一次性处理,于是将其分解为十五个子 issue,并附带显式的依赖关系图:先打基础,然后是类型系统,然后是行迭代器,然后是 Fetch,然后是 Verify,然后是 Convert,然后是 CI,最后是测试数据。其中两个子 issue 在自己的工作项中也被认为太大,于是又进行了二次分解。在这个过程中,代理们针对自己的工作又提交了十几个 issue:fixture 缺口、一个类型映射 bug、以及一个隔离级别修复。当父 issue 关闭时,其下已经建立了三十二个子 issue,合并了二十七个 pull request,审查者将工作打回了五十五次,还有九个 issue 被升级处理,其中两个升级给了人类。以 PostgreSQL(我们测试最充分的方言)为基准衡量,测试覆盖率是等同的。
但这一切是怎么发生的?是什么在驱动这一切?更重要的是,是什么确保最终产出的质量?在我们为 Db2 支持创建 issue 之前,我们先构建了一个我们称之为 MOLT Sinai 的编码医院。MOLT 是 CockroachDB 迁移工具集 (https://www.cockroachlabs.com/migrations/) 的名称,一旦我们决定将流水线按照医院的模式来建模,MOLT Sinai 就成了一个太好的组合词,让人难以拒绝。因为 Mount Sinai 是多伦多和纽约的一所著名教学医院——而这两个城市正是我们生活的地方。这个名字被保留了下来,词汇体系也一并保留:Issue 是病人。合并是出院。负责的人类是科主任。
代理快速编写大量代码在业界并非这个故事独有的现象,因为软件工厂正在整个行业遍地开花(比如 OpenAI 的这个 (https://newsletter.pragmaticengineer.com/p/openai-software-factory))。我们案例的独特之处在于:是什么站在了代理与 main 分支之间,为什么我们把它设计成医院的样子,以及在真实工作上运行五个月后发生了什么。
## 为什么是教学医院
编码代理的问题在于:虽然它们完全有能力编写代码,但很难信任它们能产出经过充分测试、可维护、且在预期范围内的生产级代码。运行代理相对便宜,但当它们的代码最终要交付到客户手中时,这点安慰毫无意义。我们宁愿让代理运行更长时间(哪怕慢 10 倍),也不愿在客户的数据库迁移到 CockroachDB 的过程中引入错误数据。速度重要,但质量重要得多得多。
过去一年中出现了多种自动化代理编码的尝试,其中许多都是为吞吐量优化的。例如,Gas Town (https://github.com/gastownhall/gastown) 并行运行大量代理处理一个代码库,并有一个合并处理层来解决冲突。当瓶颈是代码编写速度时,这是一个好设计。还有 Cursor 的这个实验 (https://cursor.com/blog/agent-swarm-model-economics),他们快速重建了 SQLite,以至于需要自己编写一个版本控制系统来处理变更量。这是一个有趣的实验,但显然它并非为了向用户交付高质量的数据库代码而设计。在绝大多数早期代理自动化实验中,速度是主要驱动力。
我们的动机不同。我们构建的是一个分布式 SQL 数据库 (https://www.cockroachlabs.com/) 以及一套将工作负载迁移到该数据库的工具。迁移工具中的一个微妙 bug 可能会在数据进入一个以正确性为最高原则的数据库之前损坏用户数据。因此,我们关心的问题不是"每小时多少个 PR?",而是"这些 PR 中有多少个是我们自己合并了都会觉得不好意思的?"。有了这种重新定位,很显然以吞吐量优化的代理集群不是一个好的模型。
所以我们寻找了一个模型:它有着丰富的经验来管理由能力参差不齐的人员完成的高风险工作,有强制性的交接、强制性的第二意见,以及关于交接粗糙会出什么问题的文献积累。我们最终找到了教学医院。
这个隐喻给了我们以下角色:
围绕这个核心,还有你如果进过医院(或看过《The Pitt》)会预期看到的其他角色:一个每三十分钟巡视一次寻找卡住的病人的**主治护士(Charge Nurse)**,一个如果 main 分支挂掉就能封锁全楼所有工作流的**感染控制(Infection Control)代理**,一个每周撰写流程回顾并召开事故后复盘会议的**安全部门**,以及一个提议新工作的**研究部门**。
我们不声称这比集群模型更便宜,也不声称比单个代理更简单。但它确实能产出比两者都更高质量的产品。当你从事数据库行业时,你愿意为这种质量买单。正如你将在下面看到的,它也带来了教学医院令人遗憾的一面(官僚主义、等待时间和成本),但我们认为这些是值得的权衡。
## 架构设计
医院中的一切都运行在 GitHub Actions 上。每个病人的状态存储在其 issue 的标签上,以及医院为追踪每个病人进展而创建的一些临时文件中。
每个阶段都是一个 GitHub workflow,当它的"**label in**"出现在 issue 上时启动。代理完成后,写入一个"**label out**",而这个标签就是下一个阶段的"**label in**"。虚线箭头将工作打回:被拒绝的计划打回检查(workup),红色的 CI 运行或请求的修改打回治疗(treatment),卡住的阶段上报给科主任(Chief)。
(https://images.ctfassets.net/00voh0j35590/7IFHyCODsHKbRnpudgOksa/9eeeadd7d817b7eb31bff090a5e6153c/CleanShot_2026-10-07_at_10.09.17_AM_2x.png)
未显示:四个部门在这条流程之外按自己的时间表运行。主治护士重新运行停滞的阶段,感染控制在 main 分支挂掉时封锁医院,研究部门和安全部门创建新 issue 和策略 PR,它们像其他病人一样通过科主任进入流程。
添加标签会触发一个 GitHub workflow,加载特定角色的提示词(prompt),使代理以医院员工的身份行动。完成工作后,代理会在包含该 issue 病历(chart)的文件中添加一条结构化记录,并应用流程中的下一个标签。这条记录带有一个如`<!-- SINAI:TREATMENT_PLAN -->`的哨兵标记,以便后续代理能够找到并解析它。
一些基本的医院规则,编码在技能(skills)中,提供了大部分安全保障:
**没有计划不写代码,没有审查不通过计划。**在住院医师(Fellow)修复任何问题之前,它必须先复现问题、进行鉴别诊断(用医院术语来说)、运行任何能缩小范围的针对性调查,然后发布一份治疗计划:诊断、要修改的文件、要添加的测试、风险、未决问题。一位审查主治医师(Review Attending),即运行以挑错而非修复为目标的提示词的另一个代理实例,会阅读该计划并批准或拒绝。只有之后治疗才能开始。我们添加这道关卡,是因为一个自信地实施错误修复的代理,比一个停下来检查计划的代理浪费更多时间和 token。
**不要即兴发挥。**如果治疗过程中范围发生变化,住院医师必须停下来,发布修订后的计划,然后回到计划审查。技能文件中的指令只有两个词:"不要即兴发挥。"
**不要走捷径,尤其是在测试方面。**代理不得为了通过测试而禁用、跳过、削弱或修改测试。如果一个测试失败,那么在被证明之前,测试就是正确的。如果代理真诚地认为测试是错误的,那么对测试的修改必须是独立的提交,根据其自身的价值进行辩护,并与修复分开审查。同样,一个通过了但实际上没有执行变更的测试比没有测试更糟糕。所有代码审查都从禁用变更并确保所有新测试失败开始。如果它们没有失败,那它们要么超出了范围,要么就是错误的。
**永远不要盲目挣扎。**当住院医师卡住时,它不会更努力地挣扎。它会编写一份 I-PASS(疾病严重程度、患者摘要、行动清单、态势感知、综合概述)交接记录,这是一种直接借鉴自教学医院的结构化格式,然后升级给主治医师(Attending)。接收的代理必须在开始工作之前写下它对交接内容的理解。关于医院中 I-PASS (https://qualitysafety.bmj.com/content/30/10/769) 的研究表明,如果医生和护士以标准化的方式记录患者信息,换班期间的不良事件可以减少 50%。我们的代理遵循同样的协议。
**出院护士审查的是审查者,而非代码。**合并前的最后一道关卡不会重新审查代码。它验证的是审查是否正确执行:审批存在、审查模板已填写、没有未解决的讨论线程、CI 为绿色、提交历史干净。它会发布一个清单,准确显示它验证了什么,如果有任何一项无法勾选,出院就会失败,该项保持未勾选并附上说明。这条规则存在的原因是,当你将控制权交给代理时,你想确保它们在按要求行事,而有时它们并非如此。
**先查先例再去打扰科主任。**人类科主任做出的每一个可推广的决策都记录在一个仅追加的先例日志中。想要升级处理的代理必须先阅读该日志,如果有先例适用,它就遵循先例并引用它,而不是升级。只有人类才能创建先例。五个月来,这大大减少了代理升级到科主任的频率。
## 交付了什么
当我们开始使用 MOLT Sinai 时,我们创建了 MOLT 工具开发仓库的镜像。这个镜像随后成为了一个试验场,让我们可以测试医院模型的效果。以下是四月二十一日到九月十一日期间该仓库中发生的事情:
在不到 5 个月的时间里,医院流水线落地了远超一百万行代码,拆分为足够小的变更,使代理能够放心地进行审查。
你可能注意到上面表格中一个有趣的数字:1299。该仓库中创建的 issue 几乎有一半是由医院为医院自己创建的:分解的子项、住院医师在计划中范围外发现的后续工作、研究部门的提案、安全部门的纠正措施。这条流水线能自己生成待办事项。由人类决定哪些病人可以入院,但在第二个月,人类就不再是主要的工作来源了。
虽然 Db2 支持是我们首次通过医院处理的大型功能,但那只是一个实验。在自主运行的第一周之后,我们开启了"人类审批模式",这要求每次合并都要经过人类审查。只有在这个模式下,我们才能确信代码的质量足以交付给客户。有了这层额外的安全保障,我们开始着手做我们真正创建医院的目的:构建迁移助手 (https://docs.cockroachlabs.com/docs/continuum/migration-assistant-overview#migration-assistant-overview),这是一个 AI 工具,引导用户完成从 Postgres 到 CockroachDB 的完整迁移,包括模式转换、数据加载和验证、以及常规转换。迁移助手目前已在 Postgres 迁移中开放预览,几乎完全由医院的工作人员编写。
## 成本
自四月启动 MOLT Sinai 以来,它消耗了略超 $135,000 的 Claude token,平均每个病人(即 GitHub issue)约为 $84。Issue 通常在医院中停留一到两天,其中往往以等待人类审查者的时间为主。就 LLM 模型而言,医院随着模型的进步而不断进化。
按工作流类型统计的成本变化 (https://images.ctfassets.net/00voh0j35590/7sK6i2xASaSO62JwHSv8Jo/01818f0b10fdb068bb703414bf238d37/chart.png)
最初每个流水线阶段都运行 Opus 模型,但随着 Fable 的引入,现在规划阶段使用 Fable,由 Fable 生成的计划来选择实现阶段使用的模型。如果实现在 Sonnet 或 Opus 模型上遇到困难,可以升级到 Fable 模型。这有助于降低成本,同时在必要时仍然可以使用更昂贵(但更强大)的模型。
如上图所示,每次模型切换都需要一些工作来调整代理技能以优化成本。我们每隔几周执行一轮持续优化,这也是上图波动的原因之一。还有其他原因,比如特定时期内工作类型的组合(UI 任务成本更高,因为代理需要处理截图和其他视觉数据),以及我们 CI 环境的特殊情况,但这些细节太多,在一篇介绍性博客文章中不便展开。
## 医院的自我进化
当我们创建 MOLT Sinai 时,我们直接在镜像仓库中构建了初始的工作流、技能和提示词。不久之后,我们意识到所构建内容的价值,并怀疑公司里的其他人也会想要利用它。为了实现这一点,我们将"Sinai"代码(实际的医院流水线)从 MOLT Sinai 仓库(医院流水线的第一个使用者)中分离出来,放入一个独立的仓库,其他人如果想要使用医院模型,可以将其嵌入自己的仓库。今天,Sinai 仓库大约有 1,570 次提交。其中大约 1,340 次——85%——是由流水线自己完成的。
这并不是我们计划好的。框架本身有 bug,我们也像对待任何其他 issue 一样把它们送进了医院。每三十分钟巡视一次的主治护士工作流之所以存在,是因为一个代理在 GitHub Actions 的标签事件中遇到了竞态条件,提交了 issue,然后另一个代理设计并交付了修复。这也是快速演进医院模型的最直接方式,随着几乎每个病人都顺利出院,医院**模型**本身也变得更加健壮、高效和易用。
今天,Sinai 模型已在 Cockroach Labs 的四个仓库中部署,还有几个仓库计划在未来几个月内采用它。
相似文章
X AI KOLs Timeline
OpenAI 用 2 名工程师配合 Codex 和 GPT-5.5 将核心存储服务 Habitat 从 Python 重写为 Rust,CPU 效率提升 6 倍、内存效率提升 15 倍,并承担 95% 的生产请求,展示了 AI 编程对大型系统重构成本结构的潜在改变。
Reddit r/AI_Agents
来自不同公司的两个AI编码代理合作在一夜之间发现并修复了Bun中的一个bug,展示了自主软件开发能力。
TLDR AI
Meta 分享其 Catching JiTTests 方案在生产环境大规模部署的成果:利用 LLM 自动生成会失败的即时测试,在代码合入前捕获传统测试和 LLM 代码审查难以发现的 bug,并配套发布了详细论文。
TLDR AI
Cursor的Bugbot代码审查工具现速度提升超过3倍,成本降低22%,发现错误数量增加10%,大多数审查运行在3分钟内完成。此次更新还新增了在推送前运行审查以及仅审查新更改等功能。
X AI KOLs Timeline
一位开发者分享了在Cursor中使用Opus 4.8 Max Thinking模型与子代理框架的工作流,并介绍了一个包含可安装技能文件的GitHub仓库,其中包含一个名为'running-bug-review-board'的技能,可进行实时QA测试。