人人都在谈论软件工厂:这个理念是指,AI 智能体可以被组装成一条流水线,自主产出可运行的软件,就像工厂把原材料变成成品一样。关于这到底是否可行、自动化究竟能走多远、以及人们演示的那些“循环”是否真有价值,争论从未停歇。有些人已经将其判定为失败。
与这条主线并行的,是一场更低调、也更令人担忧的讨论:开源维护者正在精疲力竭。AI 热潮让生成 issue、拉取请求和安全报告的成本几乎降为零,而维护者通读所有这些内容却要付出极其高昂的代价。过去那些维持项目健康运转的老办法,正在海量信息的重压下不堪重负。
每个人对这两个话题都有自己的高见。我们认为自己拥有更难得的东西:真实的结果。过去几个月里,我们在 Astro 仓库上运行了一条自动化分诊流水线。它读取新提交的 bug 报告,在沙箱中复现问题,诊断根本原因,并发布预览版本供报告者验证。支撑它的底层引擎已经发展成 Flue——一个用于构建这类智能体自动化的开放框架,你也可以用同一个工具来构建自己的自动化。
这并非一蹴而就的成功。但经过大量迭代,我们已经用它把未关闭的 issue 从 200 多个降到了约 30 个,预计下个月的某个时候能归零。那将是这个仓库 5 年多历史上第一次出现零未关闭 issue。
我们并不是靠宣布“issue 破产”、自动关闭冷门工单或无视报告才走到这一步的。我们靠的是在 GitHub Actions 内部直接运行一组相互隔离的 AI 子智能体,来自动化 issue 分诊。以下就是我们如何走到这一步的故事,以及你可以从中借鉴到哪些经验,用在自己的项目上。
从一个智能体技能开始
年初时,我们将重点放在自动化开发流程中的一个特定环节:问题分类(issue triage)。作为一个开源项目,人工进行问题分类往往是整个工作中最耗时、成就感最低的部分之一。有时仅仅复现一个问题就可能需要数小时,更不用说修复了。对我们而言,从这里开启自动化之旅是顺理成章的选择(尽管这一点常常被忽视)。
我们首先开发了一个智能体技能(agent skill)。这让我们能以维护者的身份在本地开发和测试自动化流程,在自己机器上运行编码工具链(coding harness)。随后,我们可以在仓库的 GitHub Action 中运行同一套工具链,从而完全复用完全相同的问题分类工作流技能。
该分类技能完整复刻了我们在人工处理问题时所采取的步骤:
- 复现:克隆提供的复现仓库,以验证所报告的问题。
- 诊断:对代码库进行插桩,并引入日志记录,以定位 bug 的根本原因。
- 验证:审查相关测试套件、代码注释和文档,以判断该行为究竟是真正的 bug 还是预期功能。
- 修复:将复现过程转化为失败的单元测试,通过架构指南确定合适的解决方案,并部署修复。
为防止 LLM 在 bug 可能并不实际存在时倾向于强行给出解决方案的常见偏差,每个阶段都由一个独立的子智能体(subagent)执行。这些子智能体通过将各自的发现汇总到 report.md 文件中,按顺序向前传递信息。
将技能转化为自动化
在完成分类技能的初步内部测试后,我们的工作重心转向构建一个完全自动化的流水线。我们特别希望将这一逻辑直接集成到 GitHub 工作流中,确保完全透明,使任何人都能轻松审查智能体的顺序推理过程和操作步骤。
在搭建过程中,我们意识到整个流水线本质上就是一个由 issue 标签驱动的状态机。每个新提交都以 `triage needed` 标签开始,一旦用户确认修复有效,状态就转为 `fix verified`。除了这些标签转换之外,流水线本身不持有任何状态;它只是通过回溯 issue 现有的评论来确定某个 issue 当前处于什么阶段、下一步应该做什么。
从那里开始,整个流程就自行运转了。当智能体找到修复方案后,流水线会通过 pkg.pr.new 生成一个预览版本,并把所有内容回帖到 issue 上:它发现了什么的摘要、完整日志,以及安装预览版的说明。原始提交者随后可以在自己的项目中尝试这个补丁,如果确认有效,自动化系统就会打开一个与该 issue 关联的 pull request。
从 triage 到框架
在构建这套系统的过程中,我们不断注意到,其中没有任何东西是真正与 GitHub 绑定的。响应事件、运行一系列相互隔离的子智能体、把它们的推理过程与允许执行的操作分离开来——这一切本质上只是一个工作流。这个工作流既可以由 GitHub issue 驱动,也同样可以从 Slack 消息、cron 任务或 webhook 触发。把这一认识推广成一个无论部署在哪里、驱动哪个模型都以相同方式运行的运行时,就成为了 Flue:一个开放的、与平台无关的框架,用于构建持久化智能体和工作流。
智能体自动化的好处
当我们最初推出这套自动化系统时,我们对它的有效性以及可能给开发者社区带来的负面影响有着共同的担忧。一个合理的顾虑是,依赖自动化机器人回复可能会显得缺乏人情味,并在我们作为维护者与用户群体之间制造又一层隔阂。
这种情况并没有发生。如果说有什么变化,那就是我们现在与用户的交流更多了,只是发生在更有价值的地方:
- 在 Discord 中直接与社区成员互动。
- 积极参与 RFC 讨论,处理新的功能请求。
- 与贡献者紧密合作,帮助他们把想法整合到框架中。
关于自动化补丁的质量,我们的核心理念是:AI 智能体应当能成功解决绝大多数新提交的问题。当智能体未能找到正确解决方案时,我们会将这种失败视为代码库中潜在架构或文档问题的信号,指向以下三个方向之一:
- 抽象不透明:如果智能体无法理解组件之间的边界,人类开发者也同样难以把握代码结构。
- 文档缺失:关键代码段缺少解释其实现背后逻辑的明确注释。
- 测试不足:代码库缺乏全面的测试覆盖,尤其是单元测试。
一个典型的例子发生在一系列相关的热模块替换(HMR)bug 上。分诊机器人反复尝试修改某个特定的 if 条件来解决问题。虽然这一改动修复了目标 bug,但由于该特定条件缺乏测试覆盖,它在其他地方引入了回归问题。当我们添加了一条描述性注释,解释该语句所遵循的确切逻辑后,机器人便适应了新的情况,不再尝试对该区域进行错误的修改。
每当我们追查这类失败并补上缺失的注释、测试或更清晰的边界时,机器人对代码库该部分的理解就会明显改善,下一个处理该部分的人类开发者也是如此。
将工作流转化为 GitHub Action
最初,我们的分诊逻辑直接存在于 Astro monorepo 中。这种耦合使得迭代变得困难;升级 Flue 或修改工作流就像在没有安全网的情况下对运行中的基础设施进行手术。为了解决这个问题,我们将逻辑解耦到一个独立的、可测试的仓库中:triagebot-action。这种隔离使我们能够引入自动化测试,并在触及主代码库之前确保稳定性。
如今,这一操作已为 Astro 的议题管理提供支持,并由此传播开来。其他几个团队也已采用它,有些直接使用,有些则将其分叉,构建出贴合各自项目的自动化“工厂”。第二条路径才是关键所在:triagebot-action 还很年轻,仍在积极演进中,所以我们分享它的方式,与其说是提供一个成品,不如说是一份可供你阅读、学习并改造的工作参考。
该操作本身的接线方式如下:
或者,你也可以让智能体直接指向该仓库,通读其设置,包括添加状态机所依赖的标签。
无论你选择哪条路径,核心理念比我们的具体实现更重要:一个可持续的反馈循环,让维护者得以专注于框架本身,而非管理积压的事务。代码是开放的。你可以分叉它、精简它,或者只借用其中适合你项目的部分。
想构建类似的东西吗?深入研究 triagebot-action 的代码,了解其运作方式,或者将其分叉,作为你自己仓库自动化的起点。如果你正在更认真地构建基于智能体的基础设施,那正是 Flue 的用武之地:深入 Flue 框架,构建你自己的方案。我们很期待看到你的成果。欢迎来 Astro Discord 分享你的“工厂”故事。