Cloudflare AI · 官方

我们如何构建软件工厂,将Astro的GitHub问题数降至零

How we built a software factory to drive Astro’s GitHub issue count to zero

二〇二六年八月四日 · 英文原文

Astro团队在GitHub仓库上运行自动化分诊流水线,通过隔离的AI子代理复现、诊断、验证并修复bug,将未解决问题从200多个降至约30个,预计下月归零。该引擎发展为Flue,一个平台无关的代理自动化框架,并解耦为triagebot-action供其他项目采用。团队强调,自动化失败常指向代码库的架构、文档或测试缺陷,修复后代理与人类开发者表现均提升。

大家都在谈论软件工厂:即AI代理可以被组装成一条流水线,自主生产出可工作的软件,就像工厂将原材料转化为成品一样。关于这是否真的可行、自动化能走多远,以及人们演示的“循环”是否有意义,争论不休。有些人已经将其视为失败。与此同时,还有一个更安静、更令人担忧的对话:开源维护者正在精疲力竭。AI热潮使得生成问题、拉取请求和安全报告几乎零成本,而维护者阅读所有这些内容却代价高昂。维持项目健康的旧方法在数量压力下不堪重负。每个人对这两个话题都有自己的高见。我们认为我们有一些更稀罕的东西可以提供:真实的结果。在过去的几个月里,我们在Astro仓库上运行了一个自动化的分诊流水线。它读取传入的bug报告,在沙箱中复现它们,诊断根本原因,并为报告者发布预览版本以供验证。其底层引擎发展成了Flue,一个用于构建此类代理自动化的开放框架,这也是你可以用来构建自己工具的工具。它并非一蹴而就。但通过大量迭代,我们已将其用于将未解决的问题从200多个减少到约30个,并预计在下个月的某个时候达到零。这将是该仓库5年多历史上首次出现零未解决问题。我们不是通过宣布“问题破产”、自动关闭冷门票或忽略报告来实现这一点的。我们是通过在GitHub Actions内部运行一组隔离的AI子代理来自动化问题分诊来实现的。以下是我们如何达到这一点的故事,以及你可能带回自己项目的经验。

从代理技能开始

年初,我们专注于自动化开发的一个特定领域:问题分诊。作为一个开源项目,手动问题分诊可能是工作中最耗时、回报最低的部分之一。单个问题有时可能需要数小时才能复现,更不用说修复了。这是我们开始自动化旅程的一个自然(但常常被忽视)的地方。我们首先开发了一个代理技能。这使我们能够作为维护者在本地开发和测试自动化,在我们自己的机器上运行编码框架。然后,我们可以在我们的仓库上的GitHub Action中运行相同的框架,并完全重用那个相同的分诊工作流技能。

分诊技能镜像了我们在手动问题解决过程中采取的确切步骤:

复现:克隆提供的复现仓库以验证报告的问题。 诊断:对代码库进行插桩并引入日志记录以定位bug的根本原因。 验证:审查相关的测试套件、代码注释和文档,以确定该行为是真正的bug还是预期功能。 修复:将复现转换为失败的单元测试,通过架构指南确定适当的解决方案,并部署修复。 为了防止LLM在bug可能不存在时倾向于强制解决方案的常见偏见,每个阶段由隔离的子代理执行。这些子代理通过将他们的发现编译到report.md文件中顺序传递信息。

将技能转化为自动化

在分诊技能的初步内部测试之后,我们的重点转向构建一个完全自动化的流水线。我们特别希望将此逻辑直接集成到GitHub工作流中,确保完全透明,以便任何人都能轻松审计代理的顺序推理和操作步骤。当我们连接它时,我们意识到整个流水线实际上只是一个由问题标签驱动的状态机。每个新提交都以标签“需要分诊”开始,一旦用户确认修复,它就会移动到“修复已验证”。除了这些标签转换之外,流水线本身不持有任何状态;它只是通过读取问题的现有评论来确定给定问题的位置以及接下来应该发生什么。从那里,流程自行运行。当代理确定修复方案时,流水线会使用pkg.pr.new启动一个预览版本,并将所有内容发布回问题:它发现的摘要、完整日志以及安装预览的说明。原始报告者然后可以针对他们自己的项目尝试补丁,如果他们确认有效,自动化会打开一个与问题关联的拉取请求。

从分诊到框架

随着我们构建这个,我们不断注意到它实际上并不特定于GitHub。响应事件、运行一系列隔离的子代理,并将它们的推理与它们被允许采取的行动分开——这一切都只是一个工作流。一个可以从Slack消息、cron作业或webhook运行的工作流,就像从GitHub问题运行一样。将这一认识推广到一个无论部署在哪里或驱动哪个模型都以相同方式工作的运行时,这就是Flue:一个用于构建持久代理和工作流的开放、平台无关的框架。

代理自动化的好处

当我们首次推出这个自动化系统时,我们对它的有效性以及可能对我们的开发者社区产生的负面影响有共同的担忧。有一个合理的担忧,即依赖自动化的机器人响应可能感觉不人性化,并在我们作为维护者与用户群之间造成又一个脱节。这并没有发生。如果有的话,我们现在与用户交谈更多,只是在更有用的地方:在Discord中直接与我们的社区成员互动。积极参与RFC讨论并处理新功能请求。与贡献者密切合作,帮助将他们的想法集成到框架中。

关于自动化补丁的质量,我们的核心哲学是,我们的AI代理应该成功解决绝大多数传入的问题。当代理未能找到正确的解决方案时,我们将这种失败解释为代码库中潜在架构或文档问题的指标,指向三个领域之一:

不透明的抽象:如果代理无法解释组件之间的边界,人类开发者可能也在代码结构上挣扎。 缺少文档:关键代码段缺乏解释其实现理由的明确注释。 测试不足:仓库缺乏全面的测试覆盖,特别是单元测试。 一个明显的例子发生在一系列相关的热模块替换(HMR)bug上。分诊机器人反复尝试修改一个特定的if条件来解决问题。虽然这个更改修复了目标bug,但由于缺乏对该特定条件的测试覆盖,它在其他地方引入了回归。一旦我们添加了一个描述性注释来解释控制该语句的确切逻辑,机器人就适应了,并停止在该区域进行不正确的修改。每次我们追查这些失败之一并添加缺失的注释、测试或更清晰的边界,机器人对该代码库部分的表现都会明显改善,下一个处理它的人类也是如此。

将工作流转化为GitHub Action

最初,我们的分诊逻辑直接存在于Astro monorepo中。这种耦合使得迭代变得困难;升级Flue或修改工作流感觉就像在没有安全网的情况下对实时基础设施进行手术。为了解决这个问题,我们将逻辑解耦到一个独立的、可测试的仓库中:triagebot-action。这种隔离使我们能够在触及我们的主要代码库之前引入自动化测试并确保稳定性。今天,这个action为Astro中的问题管理提供动力,并且已经从那里传播开来。其他几个团队已经采用了它,有些直接使用,有些则分叉它来构建他们自己针对项目定制的自动化“工厂”。第二条路径实际上是关键:triagebot-action还很年轻,仍在积极发展中,所以我们分享它更多是作为一个你可以阅读、学习和适应的参考实现,而不是一个成品。action本身的接线看起来像这样:

或者将你自己的代理指向仓库,让它阅读设置,包括添加状态机依赖的标签。无论你选择哪条路线,底层思想比我们的具体实现更重要:一个可持续的反馈循环,使维护者能够专注于框架本身,而不是管理积压。代码是开放的。分叉它,精简它,或者只借用适合你项目的部分。

想构建类似的东西吗?深入研究triagebot-action的代码,看看它是如何工作的,或者分叉它作为你自己仓库自动化的起点。如果你更认真地构建基于代理的基础设施,那正是Flue的用途:深入研究Flue框架来构建你自己的。我们很想看看你构建了什么。来Astro Discord分享你的“工厂”故事吧。

译自 Cloudflare AI · 官方 · 录于 二〇二六年八月四日