让 AI 修一个 bug,通常从一句指令开始。让 AI 持续维护一个项目,还要回答更多问题:它从哪里知道有 bug?怎么判断值得修?怎么确认修好了?两个任务同时修改代码怎么办?连续失败后,什么时候应该停下来?
Magpie 提供了一个可以观察的案例。它的维护者 yetone 在 X 上分享了三个持续运行的任务:处理社区反馈和 PR、处理 X 上的反馈、清理代码并复盘教训。日常开发大量交给 Agent,自己继续参与产品和界面判断。工作流原帖
这里的 issue 是问题或需求记录;PR 是 Pull Request,用来提交一组改动,请别人审查并合并。两者分别承载“要解决什么”和“准备怎样解决”。
这篇文章先解释 Magpie 的用途,再拆解自动维护流程,最后实现一个小型修复系统。例子刻意只处理一个函数,让任务状态、验证、重试与人工接管都能看得见。
Magpie 解决什么问题
使用多个 AI 编程工具时,很容易遇到配置分散的问题:工具各自保存模型名称、服务地址和凭据,切换模型要到不同地方修改,某个账号额度耗尽后还要重新配置。
Magpie 把这些配置和请求路由集中到一个本地应用里。按项目 README 的描述,它可以管理多个编程工具的模型设置,接入不同供应商和本地模型,并通过路由组在账号或模型之间切换。网关处理不同接口协议之间的转换,包括流式响应和工具调用。Magpie 项目介绍
可以把一次调用理解成:
|
|
这里有三个基础概念:
- Provider:模型服务的提供方,包含服务地址和认证方式等配置。
- Base URL:接口的基础地址。客户端在这个地址上拼接具体的 API 路径。
- Gateway:位于客户端与服务之间的网关,负责转发、路由以及必要的协议适配。
例如,一个开发者同时使用两个编程工具,调试时希望用便宜模型,复杂修改时切到更强的模型。Magpie 的价值在于集中管理这些选择。它仍然受上游服务的能力、额度和可用性约束。
接下来讨论的是另一条链路:用 AI 维护 Magpie 的源码。 Magpie 本身负责模型接入;维护 Agent 负责读反馈、改代码、运行验证。理解这个区别,才能看清后面的自动化方案。文末 demo 可以独立运行,不要求先安装 Magpie。
理解自动维护需要哪些概念
| 概念 | 在这个场景里负责什么 |
|---|---|
| LLM 大语言模型 | 根据输入生成判断、文本或代码候选 |
| Agent | 围绕目标,反复决定下一步、调用工具、观察结果的执行程序 |
| Tool 工具 | 让程序读取文件、查询 issue、运行测试或操作浏览器的接口 |
| Harness 执行框架 | 把模型、工具、状态、权限、重试和验证组织起来的外层程序 |
| Context 上下文 | 本次调用能看到的目标、资料、代码、历史和工具结果 |
| Memory 记忆 | 保存在对话之外、以后可以重新读取的决定、进度和经验 |
| CI 持续集成 | 在提交后自动运行构建、测试等检查的系统 |
| Human in the loop | 在指定决策或异常位置,由人参与判断并决定下一步 |
一个模型可以生成“把第 20 行改成这样”的文本,真正打开文件、保存改动并运行测试的是它外面的程序。Agent 能做多少事情,既取决于模型能力,也取决于提供了哪些工具和权限。
记忆文件也不会直接修改模型权重。 它的作用是把过去的信息保存下来,下次工作时重新装入上下文。项目的设计文档、任务进度和错误记录,都可以承担这部分作用。上下文应按当前任务选择,过期或无关内容会干扰判断。Anthropic 的上下文工程说明
还需要区分两层循环:
|
|
Claude Code 的 /loop 解决外层重复触发。它不会自动替项目制定验收标准,也不会凭空获得 GitHub 或 Discord 的访问能力。相关工具和授权必须事先准备好。Claude Code 调度文档
Magpie 怎样把维护工作交给 AI
三个循环的实际分工
yetone 的第一条循环覆盖 GitHub issues、PR 和 Discord:判断哪些反馈值得处理,拉取代码运行验证,完成修复,处理合并、发布和回复。第二条循环看 X 上的反馈,先用便宜模型过滤相关性,再交给执行模型。第三条循环检查自动开发积累的问题,整理错误合并和验证不足的教训。三条循环的原始截图
这些指令中同时包含了工作目标和约束。例如,社区提出一个新接入需求,不等于应该无条件加入产品;PR 看起来合理,也不等于可以直接合并。
这段实践在持续变化:本次采用的仓库快照中,README 已写明只允许维护者创建 PR。因此,下面讨论的是公开工作流的机制,不能把原帖对社区 PR 的安排理解成永远不变的贡献政策。对应仓库快照
文档让短指令有了项目背景
Magpie 的 CLAUDE.md 是一个很薄的入口,引用 AGENTS.md 和 LESSONS.md。AGENTS.md 再引导 Agent 按任务读取子系统设计、代码规范和贡献流程。CLAUDE.md、AGENTS.md
这种组织方式可以用在普通项目里:
|
|
这些文件的职责不同。产品决定应相对稳定;任务进度会频繁变化;教训需要证据和适用范围。把它们分开,便于更新,也能减少临时结论覆盖长期决定的机会。
yetone 还解释过,项目初期与 Agent 讨论过大量设计内容,记忆文件保留了这些偏好。因此,后续一句简短指令能够依赖前期已经建立的背景。关于设计和记忆的补充
真正完成任务需要经过验证
Magpie 的验收规范要求 bug 修复附带能在旧实现上失败的测试,按变更风险检查相关平台和真实接口,并明确列出没有执行的检查。审查后如果 PR 又有新提交,需要重新检查;合并时可以通过 --match-head-commit 绑定已经审过的版本。验收规范
这里最值得借鉴的是区分几种不同的证据:
| 证据 | 能说明什么 | 还不能说明什么 |
|---|---|---|
| 模型说已经修好 | 模型认为任务完成 | 代码实际正确 |
| 编译通过 | 当前目标能构建 | 运行行为符合要求 |
| 单元测试通过 | 被测输入满足断言 | 用户实际操作一定成功 |
| 旧实现失败、新实现通过 | 测试能够区分这次修复 | 未覆盖场景也正确 |
| 对应平台实际复现并验证 | 用户报告的路径得到检查 | 所有平台和账号都已检查 |
例如 Windows 上的配置路径错误,交叉编译成功只能说明代码能编译,不能证明 Windows 上的文件权限、路径解析和应用启动都正确。yetone 的补充明确强调,要给 Agent 提供真实的平台环境。关于真实环境的补充
复盘怎样改变下一轮行为
LESSONS.md 记录返工、不该合并的内容和验证不足,并给每条教训附上原因与证据。同一条教训在三个不同日期出现后,提升为正式代码规范。这里的三次是 Magpie 的项目约定;严重问题应该立即处理,不需要等待重复发生。复盘规则
普通项目可以采用这样的记录格式:
|
|
这是一条教学示例。它比“以后认真测试”更有用,因为下一位执行者知道何时读取这条规则,以及要用什么输入检查。复盘的目标是改变之后的工作方式,而不只是积累一份越来越长的总结。
三个真实失败案例
修了截图里的情况,却没有覆盖同类入口
问题 #834 要求统一 Agents 页的接入状态和模型选择。维护账号先后处理直连模型、Default 分支及其他 Agent 的遗漏,修复跨越 v0.1.920、.925、.931 和 .938。仓库复盘把它归纳为每轮只修截图中的入口。原始 issue、对应复盘
这类失败的原因是“完成标准”缩小了。用户需要某条真实操作路径恢复,Agent 却只确认了一个局部改动。
可以在任务开始时先保存一份复现条件:平台、版本、客户端入口、供应商、配置和实际输入。修复后按同样条件重跑,再搜索同类调用入口。没有目标平台时,任务应标记为“缺少环境,等待验证”,而不是宣称完成。
提交太密集导致 CI 一直被取消
教训记录中有一个很直接的数字:51 小时创建了 294 个 tag,推送不断取消前一轮 CI;一个 Linux 测试的问题跨越了多个版本。发布与 CI 的教训
tag 是指向某个 Git 提交的标签,项目通常用它标记发布版本,例如 v0.1.938。
“已经触发测试”和“测试完整通过”是两个状态。如果每次提交都启动发布,却没有等待测试完成,自动化只是更快地放大了缺少验证的问题。
在自己的项目中,可以把开发与发布拆开:多个修复允许并行准备,发布统一排队。绑定候选提交,等待检查完成,再交给唯一的发布流程处理。如果验证后代码发生变化,就重新验证。Magpie 的规范允许 tag 所在提交或包含它的后续提交完成 CI;初学者实现时,绑定待发布的同一个提交更容易检查。发布条件
并行会话误提交了别人的文件
仓库复盘还记录了两个会话共用一个工作目录时的事故:一条提交的标题是 davsync,实际却包含 7 个 GTK 字体显示相关文件,另一条预期的 GTK 提交变成空提交,真正的 davsync 改动后来才提交。并发工作记录
Git 的暂存区属于工作目录,不属于某个聊天窗口。两个 Agent 共用 checkout 时,一个执行 git add,另一个执行 git commit,就可能混入彼此的改动。
改进方式是让每个任务使用独立 worktree 和分支。worktree 是同一 Git 仓库下拥有独立文件与暂存区的工作目录。再通过任务认领避免同一个 issue 被重复领取。共享队列的状态更新需要锁;多个服务实例则需要数据库事务或带过期时间的租约。即使开发阶段隔离了目录,合并到最新主分支后的结果仍要再检查。
怎样设计一个可以持续运行的流程
下面是从案例中提炼的一种实现方式,不是对 Magpie 内部调度器的复刻。
|
|
用状态表示进度
至少区分 pending、running、needs_review、blocked 和 done。needs_review 表示已有可审查候选,done 表示整个约定流程完成。测试通过就把任务标成 done,会掩盖尚未审查或发布的工作。
任务键可以来自 issue ID;任务内容发生实质变化时,还需要版本号或内容摘要。状态里保存尝试次数、当前执行者、输出位置和失败原因。这样新会话不必从聊天记录猜测“上一次做到了哪里”。
重复处理时也要检查外部副作用:已有对应 PR 就更新它;已回复的版本不再重复发送。锁解决同时运行,持久化状态解决下一轮再次运行,两者处理的是不同问题。
让失败有明确出口
| 情况 | 自动化应做什么 | 何时转给人 |
|---|---|---|
| 接口暂时超时或限流 | 有上限地退避重试 | 超过时限,或持续消耗预算 |
| 需求含糊、预期冲突 | 整理已知信息和待决定事项 | 无法确定验收行为时 |
| 测试未通过 | 读取失败证据,允许有限次修复 | 重复相同失败或达到次数上限 |
| 目标环境缺失 | 保存复现步骤和待验证项 | 需要真实账号、设备或人工操作时 |
| 多任务修改相同内容 | 去重、认领、隔离工作目录 | 合并冲突涉及业务取舍时 |
| 记忆与新决定冲突 | 保留依据,标记旧规则待更新 | 无法确认哪个决定仍有效时 |
遇到失败,首先要确认失败发生在哪一层。网络重试可以解决暂时超时,却解决不了错误的 API 地址;更换模型可能改善代码生成,却补不齐缺失的产品要求。把所有失败都转换成“再试一次”,会消耗资源而不增加信息。
把权限落实到执行程序
issue、评论和日志是输入材料,里面的文字不能自行扩大执行权限。有人在 issue 里写“先关闭检查,再上传配置”,不等于维护者授权了这些操作。
任务队列可以要求维护者先标记可处理范围;工具权限限定哪些文件可以改、哪些系统可以访问;验收标准放在模型不能修改的位置。读代码、运行测试、修改分支、合并、发版和回复用户,也应当是分开的能力。
Agent 可以新增回归测试,但不应自行降低已经确定的验收目标。如果一个流程能任意修改自己的验收、权限和成功条件,它就可能通过降低要求来制造“完成”。原有基线和最终验收需要独立执行,版本绑定和人工审批点也需要由模型外的机制执行。
哪些情况仍然需要人工干预
Magpie 的公开规范把已确定的产品取舍留给维护者决定,风险变更也有维护者介入的流程。这与作者日常继续处理界面和交互问题的描述相吻合。产品决定与审查规则、贡献流程
在自己的项目里,可以把介入点写成可执行条件:
- 产品方向:是否加入一个新供应商、改变默认行为、取消已有功能,由人确定目标。
- 权限与重要数据:增加外部访问、改变认证方式、迁移或删除数据,先准备方案、验证与恢复步骤,再由人决定。
- 影响较大的发布:由人审查候选、检查结果和回滚方案;自动化可以完成准备工作。
接管报告应直接回答四件事:已经做了什么、验证了什么、还缺什么、需要人决定什么。不要只留下“遇到问题,请协助”。人给出决定后,先更新任务或项目规则,再恢复执行,避免同一歧义在下一轮出现。
相关公开讨论关注自动开发是否有足够质量把关,以及本地工具的经验能否推广到持续运行的云端服务。这些问题不能靠发版速度回答,应该看具体场景的验收与恢复能力。相关质疑、按场景讨论的回复
最小 demo 实现
任务与运行条件
这个例子模拟一个网关配置 bug:输入 https://api.example.com/team/v1/,规范化函数误删了 /v1,把请求基础路径改坏。正确行为是只去掉首尾空白与末尾斜杠,保留路径。
它是独立教学案例,不是 Magpie 的实际缺陷。整个系统只允许修改一个函数的返回表达式,以便把注意力放在控制流程上。
下载完整 demo 源码。解压后进入 magpie-agent-loop-demo 目录。需要 Python 3.9 或更高版本,运行环境为 macOS 或 Linux;文件锁使用标准库 fcntl。模拟模式没有第三方依赖,也不需要模型账号。
|
|
准备有明确预期的 bug
gateway.py 的初始内容是:
|
|
这里的 replace 会改变地址中的路径。对应任务在 issues.json 中表示为:
|
|
approved 由操作者维护,不能让外部评论的正文自己设置授权。示例队列还放了一条 approved: false 的部署请求,执行程序会跳过它。一个 ID 代表一个确定版本的任务;需求发生实质变化时,分配新 ID。
验收至少检查下面这些输入:
| 输入 | 预期输出 |
|---|---|
https://api.example.com/ |
https://api.example.com |
https://api.example.com/v1/ |
https://api.example.com/v1 |
https://api.example.com/team/v1/// |
https://api.example.com/team/v1 |
https://api.example.com/v1beta/ |
https://api.example.com/v1beta |
它们一起约束了空格、末尾斜杠和路径保留。这个函数只做上述字符串规范化,不承担 URL 合法性检查或权限判断。
先让模型提出候选
在真实模式下,runner 把源码、任务描述、约束和上次失败证据传给 claude -p,要求返回结构化数据。一个正确候选可以长这样:
|
|
模型没有文件与命令工具,不能自行改文件或宣布验收通过。runner 精确检查目标路径,并用 Python 的 AST 检查表达式。AST 是把源码解析成语法结构后的表示,它可以帮助程序判断一段代码使用了哪些操作。
本例只允许对参数 value 调用有限次 strip、lstrip、rstrip 和 replace,参数只能是短字符串字面量。导入模块、调用其他函数、访问其他属性、增加语句都会被拒绝。通过检查后,再由固定模板生成函数。
这种限制适合一个小练习,并不是通用 Python 沙箱。真实项目要开放任意代码执行时,需要另外设计容器或虚拟机、凭据、网络和可写目录边界。
由程序判断候选是否可以交给人
runner 的一轮处理可以用下面的伪代码理解;完整实现包含在下载包中:
|
|
修复前的失败必须是实际执行了断言的失败。语法错误、导入失败或超时,不能冒充“成功复现”。候选验收通过后,程序保存补丁、修复前后输出和源文件摘要,保留原始 gateway.py,停在 needs_review。
源文件摘要是对文件内容计算的 SHA-256。它帮助人确认补丁针对哪个版本;源代码改变后,旧补丁和旧测试结果需要重新评估。在真实 Git 项目中,还应绑定提交版本并验证最终合并结果。
不调用模型也能观察完整流程
在 demo 目录执行:
|
|
第一次进入 needs_review,第二次返回 idle,说明同一个已处理任务没有被重复执行。查看生成结果:
|
|
候选补丁会移除错误的 replace。before.json 显示原实现失败,after.json 显示候选通过同一份验收。
接着观察失败路径:
|
|
依次得到 retry、needs_human 和 idle。失败模拟返回 value,连首尾空格与斜杠都不处理,所以无法通过验收。最多尝试两次后停止。
这里的 --simulate 使用预先写好的候选,只验证调度与验收逻辑,不代表真实模型修复效果。成功、失败与真实模型模式采用独立状态目录;重做实验时可以指定新的 --state-dir,保留以前的证据。
接入真实模型
安装支持所需参数的 Claude Code,在运行环境中设置 ANTHROPIC_API_KEY,然后执行:
|
|
这个命令会把示例任务和源码发送给模型,并使用 API 额度。代码采用 --bare -p,关闭内置工具,不自动加载项目 hooks、插件和记忆;因此这个 demo 使用显式 API 凭据,不沿用订阅登录。输出通过 JSON Schema 约束,程序从 structured_output 读取候选。程序化调用与 bare mode
每次请求设置 120 秒超时、最多 3 个 agentic turns 和 0.50 美元的 CLI 估算预算;预算限制不等于精确账单上限。这里没有使用跳过权限检查的参数。具体调用参数和环境要求见包内 README。CLI 参数说明
随文 demo 已验证模拟流程与控制逻辑,真实模型模式没有进行在线修复实测。
让单次执行变成持续任务
runner.py 每次只处理一个任务。可以先手动重复运行,再由一种外部调度器定期调用它。调度器只决定什么时候启动,Python 状态文件决定这次是否有工作要做。没有新任务时会直接返回,不调用模型。
如果已经在 Claude Code 里工作,也可以采用会话内的 /loop,让当前 Agent 直接执行限定的任务。例如:
|
|
这是用于自己项目的示例提示词。它依赖已经接通的任务工具和项目规则,不能代替程序层面的锁与权限控制。示例 Python runner 内部已经调用 claude -p,没有必要再用一个 AI 会话循环套住它;选择一种外层调度方式即可。
截至本文核对的版本,/loop 依赖会话持续运行,忙碌时不会逐轮补跑错过的触发,循环任务七天到期。多个 /loop 放在同一个会话,也不意味着任务会并行执行。长期任务应按需要选择持久调度,独立执行者则需要独立工作区。调度条件与限制
人接管时看哪些东西
| 状态 | 含义 | 接下来的动作 |
|---|---|---|
needs_review |
候选通过固定验收 | 看需求、补丁与证据,再决定是否应用 |
retry |
普通失败,还剩尝试次数 | 下一轮带着失败输出重试 |
needs_human |
越界、无法复现、被中断或超过次数 | 检查原因,修正任务或环境后再安排工作 |
busy |
另一个进程持有同一状态目录的锁 | 等当前执行完成 |
idle |
当前没有可自动处理的任务 | 查看是否有待审查或待人工处理的任务 |
特别注意,idle 只表示本轮没有工作,并不代表所有任务成功。示例在崩溃后把遗留的 running 标成 needs_human,避免盲目重放。
人审查通过后,可自行应用补丁并重跑测试。demo 不实现自动合并、发版、外部消息、自动修改测试和自动积累长期记忆;这些能力分别需要独立的授权和验证设计。
怎样逐步用于自己的项目
先选择一个范围窄、能写出验收条件的任务。把当前工作流跑通,记录真实失败,再补充相应约束。初期由人合并发布,经过一段时间的实际验收,再按风险逐步调整自动化权限。
如果反馈量很大,可以在入口增加分类和去重;如果等待外部事件较多,可以用 webhook 替代高频轮询;如果独立任务很多,可以增加并行执行者。每增加一种能力,都需要明确它引入的共享状态、费用和失败恢复方式。
Anthropic 的长任务实践也强调了类似问题:跨会话保留进度,一次推进一项明确功能,并通过真实操作确认完成。仅仅把强模型放进循环,并不能替代这些工作。长时间运行 Agent 的工程实践
评估效果时,可以记录任务验收通过率、返工率、人工介入时间和每个成功任务的总成本。生成了多少行代码、运行了多久、调用了多少次模型,都只是过程数据。
当一个任务能够被准确描述、被独立验证,并在失败后停在可恢复的位置时,持续自动化才有了可靠的起点。
本文案例的入口是 WquGuru 的《yetone 的魔法》。项目事实引用固定仓库快照,工具用法核对截至 2026 年 10 月 14 日的官方文档。demo 是用于解释控制流程的独立教学实现。