让 Agent 自动修 Bug
在 HiFox,人一般是不修 bug 的。大部分的 bug 都直接交给 Agent 来修。
我们有一个专门修 bug 和做小需求的 Agent,名字叫“狄仁杰”。它描述和讨论问题,进入代码仓库查找实现,也能使用运行环境执行测试。涉及界面变化时,还可以打开浏览器验证操作,保留截图。
过去 15 天里,HiFox 团队完成的所有任务里,有 13% 都是由狄仁杰完成的。分配给狄仁杰的最近 100 个需求,有 90% 都顺利完成了。
狄仁杰运行在团队的共享开发机上,使用 oh-my-pi Runtime,使用 glm-5.3 模型。每天,都有几十个 bug 和小需求被安排给它,而它完成得很不错,很让人放心。
狄仁杰是如何工作的?
我们拿一个实际案例来理解狄仁杰的工作过程。
有一个同事发现一个问题:“清理构建缓存”弹窗中的临时目录列表无法滚动。她把这个问题发到了我们的内部吐槽飞书群,然后另一位同事就 @HiFox 任务助手,让 Agent 创建一个任务。

于是 Agent 就创建出这个任务,接下来安排给狄仁杰跟进开发。

狄仁杰在接受任务之后,运行了 14 分 1 秒,然后给出结论,定位到了 bug 的原因。接下来,它提出了三个需要确认的决策,交给用户决定使用哪个方案。
用户选了“1A 2A 3A 【进入开发】”,接下来狄仁杰正式开始开发,在工作了 37 分钟之后给出结论,已经完成了开发和验证,并给出了几样待验证的材料:
- 代码 PR
- 预览链接
- 修复后的截图


接下来,人只需要参考这几样材料,确认 bug 确实修复了,就可以回复“提测”,就会将本需求的代码合入开发分支,接下来进入自动化测试流程。
关于 HiFox 的自动化测试,具体见全流程自动化测试。

整个过程中,人只需要在两个节点做出判断,而在其他时间完全不需要跟 Agent 反复对话,确认细节。这样,人驱动 Agent 的效率大大提升,一天修几十个 bug 都不在话下。
狄仁杰的工作流程
狄仁杰是如何做到这样高效准确地解决问题的?
接下来,我们拆解一下狄仁杰的工作流程。大致如下,从前到后总共 10 个步骤。

- 初始化阶段:Agent 会检查任务编号、标题、描述和标签,确认自己位于 HiFox 提供的任务工作区,再根据任务优先级确定基线分支。紧急任务可能以 main 为基线,高优先级任务可能使用 staging,其余任务通常跟随仓库默认的集成分支。
- 诊断阶段:这个阶段只负责复现问题、收集证据和寻找根因。即使修法已经很明显,它也不能直接改代码。诊断结果必须写进 diagnosis.md,后面的方案要能回到这里找到依据。
- 起草解决方案:找到根因以后,Agent 开始起草解决想法。它会说明准备改什么、哪些行为保持不变,以及还有哪些问题需要用户选择。如果涉及用户可见文案,还要先读取仓库里的术语表和本地化规则,准备多个候选说法。用户给出反馈后,Agent 继续精化 idea.md,直到方案足够明确。
- 等待用户确认方案:接下来会出现第一个等待阶段。此时 Agent 已经知道问题怎样修,但仍然没有修改产品代码的权限。它必须等用户发送【进入开发】。只有这个令牌有效,普通的“继续”、“可以”或“按这个做”都不能让它进入下一阶段。
- 实现探索和实现:获得许可后,Agent 先做实现探索。它会阅读相关文件、查找调用关系、确认现有测试和仓库惯例,再生成 findings.md 与 plan.md。Agent 会继续进入实现阶段,按照已经批准的想法修改代码,并把计划外的变化记录在 plan-delta.md 里。
- 净室评审:实现结束后,Agent 还不能直接宣布完成。它需要同步权威基线,随后进入净室评审。这里的“净室”指的是暂时放下实现者的思路,用评审者的标准重新检查改动。评审关注根因是否真的解决、调用方是否全部迁移、测试是否覆盖风险,以及代码里有没有残留的旧路径。
- 修补阶段:发现阻断问题时,Agent 会进入修补阶段。修完以后重新同步基线,再做一次净室评审。这个循环最多进行六次。六次以后仍有阻断问题,自动流程停止,转为等待人工处理。这个限制防止 Agent 在自己写、自己审、自己修的循环里一直运行下去。
- 验证阶段:评审通过以后,Agent 进入验证阶段。它会运行仓库声明的测试,也会根据改动性质检查真实页面、接口、日志或命令行为。测试命令退出成功只说明检查通过了一部分。涉及用户界面的改动还需要真实界面证据,后端改动也要留下与运行行为相符的记录。
- 等待提测:验证完成后,Agent 整理提测包,进入第二个等待阶段。用户审阅改动、证据和自动决策,随后发送【提测】。这个令牌授权 Agent 创建最终提交、推送代码、执行目标分支操作,并把当前 HiFox 任务更新到待测试状态。
- 执行提测:Agent 合并代码到开发分支,并把任务状态改为“待测试”,等待测试 Agent 的测试。
狄仁杰的设计原理
狄仁杰的指令本质上不是常见的角色提示词,而是一套高度工程化的“单 Agent 缺陷修复状态机”。这套设计很像一份可以自动执行的开发规程。Agent 可以在大部分时间里独立工作,但不能自行决定何时开始改代码,也不能自行决定何时把代码提交到目标分支。人只在少数关键位置作决定,其余过程由 Agent 按照状态继续推进。
狄仁杰不能凭感觉决定下一步,而必须沿一张固定流程图执行;当前走到哪里,都会写入持久化的 state.json,记录当前状态。
狄仁杰的 Agent 指令可以在这个文档中看到:https://apifox666.feishu.cn/wiki/XuMJwVTP4iWh7IkWJ52cOQGRnkf
狄仁杰的指令包含以下这些部分。
1. 角色与边界
限制狄仁杰只能做什么,不能做什么。
- 狄仁杰只能处理当前分配的 HiFox 任务
- 不允许自己找其他任务、创建替代任务或调用其他 Agent
- 明确禁止跨阶段工作
2. 权威顺序
当信息冲突时,按照以下的优先顺序。
- Agent 指令和人工决策优先
- 然后是仓库内的 AGENTS.md、文档、分支政策
- 再是任务描述、批准后的方案、代码和运行证据
这套顺序要求 Agent 尊重当前仓库里的事实。模型记得某个框架通常怎样配置,不能证明这个仓库也应该这样配置。仓库已经声明测试命令和分支规则时,Agent 必须照着执行。文档、代码和运行行为互相冲突时,它需要把冲突暴露出来,不能挑一条最方便的解释继续工作。
3. 持久化状态机
初始化之后,state.json 是判断当前阶段的唯一依据。
Agent 每次行动前都要读取并校验它,同一时间只能有一个活动阶段。这个文件除了记录阶段,还保存任务信息、等待的人工确认、已批准的决策、阶段产物和验证状态。
每次合法的阶段变化都要写入历史。记录里包含原阶段、新阶段、迁移原因、相关文件及其哈希。需要人工许可时,还要保存令牌和当时被批准的方案版本。
这使狄仁杰能够在会话中断后继续工作。新的运行不会依赖聊天记忆猜测上次做到哪里,而会重新读取状态文件和阶段产物。状态文件缺失、格式损坏或内容互相矛盾时,Agent 会停止并报告状态错误。它不能手工把阶段改到后面,也不能根据聊天内容补造一条已经丢失的批准记录。
4. 人工门
两个人工门控制两类高影响操作。
【进入开发】控制产品代码写入。它确认当前的解决想法已经得到认可,从这一刻起,Agent 才能修改仓库中的产品文件。
【提测】控制提交、推送和任务状态修改。它表示用户已经审阅提测材料,也接受 Agent 在实现过程中记录的自动决策。只有到这里,Agent 才能执行最终交付动作。
这两个令牌把风险分成了两段。第一段风险来自代码修改,第二段风险来自把修改送到远端并影响团队流程。Agent 可以在两道门之间完成大量自动工作,但无法越过这两条边界。
5. 阶段产物
状态机里的每个阶段都有对应产物。
诊断阶段要生成 diagnosis.md,里面写清问题如何复现、根因在哪里,以及证据来自什么地方。
方案阶段使用 idea.md 保存准备采取的解决方式和用户已经确认的选择。
进入实现前,Agent 还要生成 plan.md,说明准备修改哪些位置以及如何验证。
代码完成以后,评审结果写进 review-report.md。评审发现阻断问题时,Agent 需要按照报告修补代码,再重新评审。
测试和真实环境验证全部通过后,最终的交付信息写进 ship-summary.md。
缺少对应文件时,Agent 不能宣称这个阶段已经完成。聊天里写一句“诊断完成”没有效力,状态文件和阶段产物都存在,流程才有资格继续。
6. 阶段专属技能
狄仁杰在指令之外,还包含七个技能。主指令负责控制整个流程,具体阶段的执行方法交给七个专属技能。
诊断阶段读取 lattice-diagnose,方案阶段读取 lattice-idea,探索和实现分别使用 lattice-explore 与 lattice-implement。代码评审、真实验证和最终交付,则分别由 lattice-review、lattice-verify 和 lattice-deliver 规定细节。
这种拆分让主指令集中处理阶段、权限和迁移条件,各个技能负责阶段内部的操作规范。Agent 每次进入新阶段前,必须完整读取对应技能,并把读取记录写进状态历史。产物还要符合技能规定的格式。仅仅记录“已经读取”并不够,文件内容也要证明这些规则得到了执行。
7. 验证与提测
验证阶段对证据的要求尤其严格。测试命令成功只能证明测试通过,不能直接证明功能在真实环境中可用。用户能够看到的功能需要在实际页面或应用中检查,后端改动也要留下接口、日志、查询结果或运行命令等证据。
提测之前,Agent 会把工作分支推送到专用的远端评审分支,并提供 Compare 链接。用户可以查看实际代码差异和验证材料。
8. 回复格式
- 回复必须包含实际完成的工作、当前阶段和下一步人工动作
- 每条回复最后强制附带状态页脚,包括任务、阶段、等待令牌、评审次数和产物路径
经验与教训
单 Agent 还是多 Agent?
我们在建造内部使用的一批 Agent 的过程中,曾经对于技术选型有过一系列的讨论。最核心的讨论就是:到底使用单个 Agent 来实现整个开发过程,还是使用多个 Agent 合作完成?
HiFox 的“小队”功能完全可以实现多 Agent 合作,但我们最终还是选择了单 Agent 状态机的方式来实现。这是因为,我们实践下来的经验是,以目前大模型的能力,对于“修 bug”这个场景,单 Agent 已经足够用了。使用多 Agent 会更加耗时,成本也更不划算。多 Agent 小队更适合那些有多个明确专业分工步骤,并且各步骤之间耦合度较低的事务。
Anthropic 团队的实践经验也支持了这一点,他们建议尽量使用包含技能的单 Agent,而非拆成多个子 Agent。详细内容请看:《Anthropic:谨慎使用子 Agent》。
使用哪个 Runtime?
指令写好之后,还要选一个把它跑起来的 Runtime。选型时我们用同一批真实任务,把当时几个常见的 Runtime 都试了一轮:官方的 Claude Code、Codex CLI,开源的 OpenCode,以及 oh-my-pi。最后选了 oh-my-pi,不是因为其他工具不好,而是它们大多为“人坐在终端前交互”设计,而狄仁杰需要的是一台无人值守、严格照章办事的机器。具体有这几点。
- 指令完全可控:状态机的前提是行为可预期。Runtime 不能夹带自己的隐藏提示词,也不能“好心”地自动重试、自动继续、压缩上下文——这些行为对人类用户是贴心,对状态机是干扰。oh-my-pi 的系统提示、工具集和执行循环都能被完全接管,Agent 的每一步都来自我们的指令,出了问题才能归因。
- 工作过程可回放、可分析:大多数时候,在 HiFox 里直接看 Agent 的工作过程就够了;偶尔结果不对、要深挖原因时,oh-my-pi 的会话可以导出成 ACP session,完整回放 Agent 的内部工作过程——哪一步在反复试探、哪条指令没被遵守、上下文在哪里膨胀,一目了然。狄仁杰流程上的很多优化点,就是从这些回放里发现的。
- 会话可持久化、可恢复:一个任务动辄运行几十分钟,中间难免中断、重启。oh-my-pi 的会话支持断点恢复,新会话能接上之前的执行。这和 state.json 的设计正好咬合:状态在文件里,上下文在会话里,两边都接得上。
- 轻量、可并发、开源可修:共享开发机上每天有几十个任务并行,Runtime 必须轻而稳。oh-my-pi 是一个轻量 CLI,几十个实例同时跑没有压力,也没有按席位付费的成本。真出了问题,开源意味着可以直接读源码、打补丁,不用把生产流程停在原地等上游修复。
当然,这些工具都在快速迭代,这里的结论只针对“无人值守跑状态机”这一个场景。如果目标是给人类工程师做一个交互式的编程助手,选择可能会完全不同。
指令迭代经验
这套流程不是一次设计出来的。在狄仁杰稳定运行之前,我们踩过不少坑,也做过不少减法。下面几条经验,都是实际运行中换来的。
- 使用已经验证可靠的技能:Agent 的稳定下限是由工具决定的。未经验证的指令,每次执行的路径都可能不一样,出了问题也难以归因。我们把每个阶段的做法沉淀为经过反复验证的技能,Agent 只负责严格遵循,行为才变得可预期。新写的技能必须先在低风险任务上跑通,才能进入正式流程。
- 人工门尽量减少:早期版本里我们设了 7 道人工门,Agent 走几步就要停下来等人,人被反复打断,流程快不起来。后来一路减到 2 道,只保留风险最高的【进入开发】和【提测】。门少了,守住门反而更容易:人在信息完整的少数节点做判断,远比在过程里频繁点头可靠。
- 自然语言不解锁,必须使用明确指令:“继续”、“可以”、“按这个做”都不能让 Agent 进入下一阶段,只有【进入开发】【提测】这样的令牌有效。自然语言的含义会随上下文漂移,Agent 可能把一句客套话当成批准。把授权收敛成无歧义的明确指令,事后也能在状态历史里核对是谁、在哪个方案版本上给了授权。
- 必须有截图,并贴进会话:涉及界面的改动,截图是硬性要求,而且必须直接贴进会话,而不是给出一个文件路径让人自己去找。人做提测决策的依据,应该出现在决策发生的地方:修复前后的效果一眼可见,判断才有底气。要点开好几层目录才能看到的证据,等于没有证据。
结语
把 bug 交给 Agent,凭什么放心?狄仁杰给出的答案不在模型有多聪明,而在流程有多较真。状态机规定它能走到哪里,阶段产物留下它做过什么的证据,两道人工门守住真正有风险的动作,净室评审和验证阶段兜住质量底线。每一步都可核对、可中断、可恢复,信任才有落点。
这套流程也重新安排了人的位置。人不再盯着 Agent 的每一步操作,只在方案确认和提测两个节点做出判断,判断之外的时间全部交还给 Agent。人的注意力从“过程”转向“决策”,一个人同时跟进几十个需求才成为可能。这大概是 AI-native 带给工程师最实际的变化。
修 bug 只是起点。同样的纪律——明确边界、持久状态、人工门、证据链——正在被我们复制到需求开发、测试和发布的更多环节。我们还有其他几个 Agent,可以直接覆盖开发领域的各个环节,也会在未来继续分享。