ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

多Agent协作如何重塑研发流程:从单模型硬伤到DevFlow AI实战

多Agent协作如何重塑研发流程:从单模型硬伤到DevFlow AI实战

1. 为什么研发协作需要多 Agent 而不是一个大模型

1.1 单模型处理研发流程的三个硬伤

很多团队一开始的想法很朴素:既然大模型能写代码、能读日志,那我直接拿一个通用模型,把 Issue 内容、PR diff、CI 日志全塞进上下文,让它一次性给出结论不就行了?我最早也是这么干的,实测下来有三个绕不过去的硬伤。

第一个是上下文污染。Issue 里往往夹杂着用户情绪化的描述、无关的截图说明、历史遗留的讨论串;PR diff 里是几百行结构化代码;CI 日志动辄几千行且大部分是噪音。这三类信息的"语言风格"和"关注重点"完全不同,塞进同一个上下文后,模型很容易被无关信息带偏。比如你让它审查 PR,它却开始复述 Issue 里用户抱怨的某个功能,因为它分不清当前任务边界。

第二个是职责冲突。分析 Issue 需要的是"归纳诉求、判断优先级、识别复现步骤";审查 PR 需要的是"代码规范、逻辑漏洞、边界条件、测试覆盖";CI 排障需要的是"日志模式匹配、错误链路定位、环境差异推断"。这三套能力对模型的提示词、输出格式、甚至温度参数要求都不一样。用一个模型一套提示词硬扛,结果就是每样都做得"差不多但不够好"。

第三个是可观测性差。单模型一把梭,出了问题你根本不知道是哪一步错了——是 Issue 理解偏了?还是 PR 审查漏了关键文件?还是 CI 日志解析时把关键行截断了?整个链路是个黑盒,调试成本极高。

1.2 多 Agent 分工的核心逻辑:让每个 Agent 只做一件事

多 Agent 架构的本质,是把上面那团乱麻拆成几条清晰的流水线。每个 Agent 有自己的系统提示词、自己的工具集、自己的输出契约,彼此通过结构化的消息传递协作。这样做的好处非常直接:

  • 每个 Agent 的上下文是干净的。Issue 分析 Agent 只看到 Issue 相关内容,PR 审查 Agent 只看到 diff 和仓库规范,CI 排障 Agent 只看到日志和构建配置。
  • 每个 Agent 可以独立调优。你觉得 PR 审查太宽松,就单独调它的提示词和阈值,不影响其他环节。
  • 每个 Agent 可以独立观测和替换。某个 Agent 效果不好,直接换掉或升级,其他部分不动。

打个比方,这就像把一个"全科医生"换成"分诊台 + 专科医生"的组合。分诊台负责判断你该去哪个科,专科医生只处理自己领域的问题,效率和准确率都高得多。

1.3 DevFlow AI 的整体架构长什么样

我设计的 DevFlow AI 由四个核心 Agent 加一个协调器组成,整体数据流是这样的:

组件职责输入输出
协调器 Orchestrator任务分发、状态管理、结果汇总事件触发(新 Issue / 新 PR / CI 失败)调度指令
Issue 分析 Agent归纳诉求、分类、优先级、复现步骤提取Issue 标题、正文、评论结构化 Issue 报告
PR 审查 Agent代码规范、逻辑风险、测试覆盖检查PR diff、仓库规范文件审查意见列表
CI 排障 Agent日志解析、错误定位、修复建议CI 日志、构建配置排障报告
汇总 Agent把各 Agent 结果整合成人类可读的评论各 Agent 的结构化输出最终评论/通知

协调器不直接做推理,它只负责"什么时候叫谁干活"。这种设计让整个系统像一个流水线工厂,而不是一个什么都干的杂货铺。

提示:协调器的状态管理建议用简单的状态机而不是复杂的编排框架。我一开始用了某编排框架,结果发现调试成本比收益还高,后来退回用几十行状态机代码,反而更稳。

2. Issue 分析 Agent:从一堆抱怨里提炼出可执行的需求

2.1 Issue 文本的脏乱差是常态

真实的 Issue 从来不是规规矩矩的"需求描述"。我统计过我们仓库近半年的 Issue,大概分布是这样的:约 30% 是纯 bug 报告但描述模糊("点了没反应"),约 25% 是功能请求但夹杂大量个人偏好,约 20% 是重复或已解决的问题,剩下的是文档问题、环境问题、以及完全跑题的讨论。

如果直接把原始文本丢给模型让它"分析一下",输出往往是一段正确的废话。所以 Issue 分析 Agent 的第一步不是理解,而是清洗和结构化。

2.2 分步提示词设计:先抽取,再判断,最后归纳

我的做法是把 Issue 分析拆成三个串行的子步骤,每个子步骤用独立的提示词调用,而不是一个提示词搞定所有事。

第一步:信息抽取。让模型只做一件事——从文本里抽出这些字段:问题现象、复现步骤、期望行为、实际行为、环境信息、附件链接。这一步不要求模型做任何判断,只做"找出来"。提示词里明确要求:找不到的字段填"未提供",不要脑补。

第二步:分类与去重判断。拿到结构化字段后,再让模型判断这是 bug / 功能请求 / 文档问题 / 环境问题 / 其他,并给出置信度。同时把标题和摘要与历史 Issue 库做向量相似度比对,相似度超过阈值的标记为"疑似重复"。

第三步:优先级与可执行性评估。最后一步才做价值判断:影响范围多大?有没有 workaround?是否阻塞核心流程?综合给出 P0-P3 的优先级建议,并明确标注"信息不足,需要补充哪些内容"。

这样拆的好处是,每一步的输出都可以单独验证。如果最终结果不对,你能快速定位是抽取错了、分类错了、还是优先级判断错了。

2.3 结构化输出的字段设计

Issue 分析 Agent 最终输出一个 JSON,字段设计如下:

{ "issue_id": "ISSUE-1234", "category": "bug", "category_confidence": 0.92, "priority": "P1", "priority_reason": "影响核心登录流程,无 workaround", "symptom": "用户点击登录按钮后页面无响应", "reproduce_steps": ["打开登录页", "输入正确账号密码", "点击登录"], "expected": "跳转到首页", "actual": "按钮无响应,控制台报错", "environment": "Chrome 120, Windows 11", "missing_info": ["是否有网络请求发出", "控制台完整报错"], "duplicate_candidates": ["ISSUE-1180"], "suggested_labels": ["bug", "auth", "P1"] }

这个 JSON 就是 Issue 分析 Agent 的"产品"。下游的汇总 Agent 直接读这个结构,不需要再去理解自然语言。

2.4 实测中容易翻车的两个点

第一个坑:模型过度脑补复现步骤。用户只写了"登录不了",模型却编出了五步复现步骤。解决办法是在提示词里加硬约束:"复现步骤必须能在原文中找到对应描述,否则返回空数组并在 missing_info 中标注。"加了这条之后,脑补现象基本消失。

第二个坑:优先级判断受情绪词影响。用户写"紧急!崩溃了!",模型就给 P0。但实际上那个"崩溃"只是某个边缘页面的样式错位。我的处理是让优先级判断只看客观字段(影响范围、是否阻塞、有无 workaround),把情绪化的原文单独隔离,不参与优先级推理。

注意:Issue 分析 Agent 的输出建议先以"草稿评论"形式发到 Issue 里,让人确认后再打标签。全自动打标签在早期很容易误伤,人工确认一轮能积累大量修正样本,反过来优化提示词。

3. PR 审查 Agent:不是让 AI 挑刺,而是让它守住底线

3.1 PR 审查的目标要收敛,别指望 AI 做架构评审

很多人对 PR 审查 Agent 的期待是"帮我找出所有问题",这个期待本身就是错的。AI 做不了架构评审,也判断不了业务逻辑是否符合产品意图。它能做且应该做的,是守住那些明确、可规则化、容易遗漏的底线。

我把 PR 审查 Agent 的职责收敛为四类:

  • 规范类:命名规范、文件组织、提交信息格式、是否更新了文档。
  • 风险类:明显的空指针、未处理的异常、硬编码密钥、危险的 SQL 拼接。
  • 测试类:新增逻辑是否有对应测试、测试是否覆盖了边界条件。
  • 一致性类:改动是否与仓库既有的模式一致(比如别人都用某个工具函数,你却又写了一个)。

超出这四类的,一律不报。宁可漏报,不可误报——误报多了,开发者就会直接忽略所有 AI 评论,这个 Agent 就废了。

3.2 diff 的预处理:先切块,再逐块审查

直接把整个 diff 丢给模型效果很差,因为一个 PR 可能改了 20 个文件。我的做法是先把 diff 按文件切块,再按"改动类型"分组:

  • 纯新增文件
  • 纯删除文件
  • 修改文件(再细分为:只改逻辑、只改样式、改配置、改测试)

然后对每一块单独调用审查提示词,最后合并结果。这样做的好处是,模型每次只需要关注一小段代码,注意力集中,判断更准。

对于超大 PR(超过 500 行改动),我会先让模型做一个"改动摘要",识别出这个 PR 主要动了哪些模块,然后只对核心模块做深度审查,边缘改动只做规范检查。这是基于实践的取舍——超大 PR 本来就该拆分,AI 没必要为它兜底。

3.3 审查意见的措辞直接影响采纳率

这一点是我踩了很多坑才悟出来的。同样一个问题,措辞不同,开发者的反应天差地别。

差的措辞好的措辞
这里有空指针风险第 42 行user.profile.name在 user 为 null 时会抛异常,建议加可选链或前置判空
缺少测试新增的calculateDiscount函数有 3 个分支,当前测试只覆盖了 1 个,建议补充边界用例
命名不规范变量d建议改为discountRate,与仓库其他文件的命名风格保持一致

核心原则:指出具体位置、说明具体后果、给出具体建议。模糊的批评只会引发防御心理,具体的建议才会被采纳。

3.4 如何避免"狼来了"效应

PR 审查 Agent 最大的敌人不是漏报,而是误报导致的信任崩塌。我做了三件事来控制误报:

第一,建立白名单机制。某些文件(如自动生成的代码、第三方库的封装)直接跳过审查。某些规则(如行长度)如果团队本来就不在意,直接关掉。

第二,分级输出。把意见分为"必须修改"和"建议考虑"两档。必须修改的才阻塞合并,建议考虑的只是评论。这样开发者不会因为一堆鸡毛蒜皮的建议而烦躁。

第三,定期复盘误报。我每周会看一遍 AI 评论被开发者标记为"无效"的记录,把高频误报模式加到提示词的负面示例里。这个反馈闭环是让 Agent 越用越准的关键。

提示:PR 审查 Agent 的提示词里一定要放几段"仓库自己的代码范例",让模型学习本仓库的风格。通用规范模型都知道,但"本仓库的习惯"只有喂了范例它才懂。

4. CI 排障 Agent:把几千行日志变成一句话结论

4.1 CI 日志的噪音比例高得离谱

一个典型的 CI 失败日志,真正有用的信息可能只占 5%。剩下的 95% 是:依赖下载进度、测试用例的通过输出、编译器的正常警告、以及各种时间戳和路径。如果直接把原始日志丢给模型,token 消耗巨大且效果差。

所以 CI 排障 Agent 的第一道工序是日志压缩。我的压缩策略分三层:

  • 第一层:按行过滤。用正则先剔除明显无用的行(下载进度、纯时间戳、已知的正常警告)。
  • 第二层:按块聚合。把连续的测试通过输出聚合成一行"XX 个测试通过"。
  • 第三层:错误上下文提取。定位到第一个 ERROR 或 FAILED 关键字后,向前后各取 50 行作为"错误上下文",这是最关键的输入。

经过这三层压缩,几千行日志通常能压到 100-200 行,信息密度大幅提升。

4.2 错误分类:先判断"是不是代码问题"

CI 失败的原因五花八门,但大致可以分成几类,处理策略完全不同:

失败类型典型特征处理策略
代码错误编译失败、测试断言失败定位到具体文件和行,给出修复方向
环境问题依赖下载失败、端口占用建议重试,标注为"疑似环境抖动"
配置问题变量未定义、路径不存在指出缺失的配置项
资源问题超时、内存不足建议调整资源或拆分任务
偶发失败无明确错误,重跑即过标记为 flaky,建议重试

这个分类非常重要,因为不是所有 CI 失败都需要开发者改代码。如果 Agent 把环境抖动也报成"代码有 bug",开发者会疯掉。我的做法是让 Agent 先做这个分类判断,只有"代码错误"和"配置问题"才 @ 相关开发者,"环境问题"和"偶发失败"只建议重试。

4.3 从错误日志到修复建议的推理链

CI 排障 Agent 最有价值的部分,是把错误日志翻译成"人话 + 修复方向"。我要求它的输出必须包含这条推理链:

  1. 失败发生在哪个阶段(安装依赖 / 编译 / 测试 / 打包 / 部署)
  2. 直接错误信息是什么(原文引用关键行)
  3. 根因推断是什么(基于错误信息的合理推断)
  4. 建议的修复动作是什么(具体到改哪个文件、加什么配置)

举个例子,日志里出现ModuleNotFoundError: No module named 'xxx',Agent 的输出应该是:

  • 阶段:测试阶段
  • 直接错误:导入 xxx 模块失败
  • 根因推断:依赖未安装,或 requirements 文件未更新
  • 修复建议:检查 requirements.txt 是否包含 xxx,若缺失则添加并重新提交

这种结构化的输出,比一句"CI 挂了,请检查"有用一百倍。

4.4 重试决策:什么时候该自动重试,什么时候该叫人

这是 CI 排障 Agent 里最需要谨慎的部分。我的策略是:

  • 明确的环境抖动(如依赖源超时、网络错误):自动触发重试,最多 2 次,重试成功则不打扰任何人。
  • 疑似偶发失败(无明确错误但失败):标记为 flaky,自动重试 1 次,若仍失败则通知。
  • 明确的代码/配置错误:不重试,直接通知相关开发者,附上排障报告。

这个策略的核心是减少无效通知。开发者最烦的就是"CI 挂了"的通知,点进去发现重跑一下就好了。自动重试能过滤掉大部分这类噪音。

注意:自动重试一定要有次数上限和冷却时间,否则遇到持续性的环境问题会陷入无限重试。我设的是最多 2 次、间隔 5 分钟,超过就转人工。

5. 多 Agent 之间的协作与状态管理

5.1 事件驱动还是轮询:我为什么选事件驱动

协调器怎么知道该干活了?两种方式:轮询(每隔几分钟检查有没有新 Issue/PR/CI 失败)和事件驱动(平台 webhook 触发)。

我选的是事件驱动,理由是延迟低且不浪费资源。轮询在仓库活跃度低的时候纯属空转,活跃度高的时候又可能漏掉事件。事件驱动则是"有事才干活",响应快,成本低。

但事件驱动有个坑:事件可能重复投递或乱序。所以协调器必须做幂等处理——每个事件带唯一 ID,处理过的 ID 记录下来,重复的直接丢弃。这个幂等层是必须的,否则同一个 PR 可能被审查两次,发出两条重复评论。

5.2 Agent 之间的消息契约

多 Agent 协作最容易出问题的地方,是 Agent 之间的"接口"不清晰。我的做法是给每个 Agent 定义严格的输入输出契约,用 JSON Schema 约束。

比如 PR 审查 Agent 的输入契约要求必须包含:pr_id、diff_chunks(已切块的 diff 数组)、repo_conventions(仓库规范文本)。输出契约要求必须包含:pr_id、findings(意见数组,每条含文件、行号、级别、描述、建议)。

有了这个契约,任何一个 Agent 都可以被替换或升级,只要它遵守契约,其他部分完全不用改。这就是多 Agent 架构的可维护性优势。

5.3 失败处理:某个 Agent 挂了怎么办

真实系统里,Agent 调用失败是常态(超时、限流、返回格式错误)。我的处理原则是降级而非中断。

  • Issue 分析 Agent 失败:发一条"自动分析暂不可用,请人工处理"的评论,不阻塞 Issue 流程。
  • PR 审查 Agent 失败:跳过 AI 审查,正常走人工 review,不阻塞合并。
  • CI 排障 Agent 失败:只发原始日志链接,不做分析。

核心思想是:AI 是辅助,不是关卡。任何 AI 环节挂掉,都不能阻塞研发主流程。这个原则在系统设计初期就要定下来,否则后期会变成"AI 一挂全组停工"的尴尬局面。

5.4 成本控制:不是每个 PR 都值得全量分析

多 Agent 系统跑起来之后,token 成本是个现实问题。我做了几层控制:

  • 小改动跳过深度审查。改动少于 10 行的 PR,只做规范检查,不做深度逻辑审查。
  • 草稿 PR 不触发审查。标记为 draft 的 PR 不消耗资源。
  • 同一 PR 的重复推送做增量分析。只分析新增的 commit,不重复分析已审过的部分。
  • 设置每日预算上限。超过上限后降级为只做基础检查。

这些策略让成本可控,同时不影响核心体验。

6. 落地过程中的真实踩坑记录

6.1 提示词里的"示例"比"规则"更管用

我一开始写提示词,喜欢列一堆规则:"你必须检查 A、B、C、D……"结果模型经常顾此失彼。后来我改成给示例:放 3-5 个"好的审查意见"和"差的审查意见"的对比,让模型模仿。效果立竿见影。

原因是,规则是抽象的,模型需要自己翻译成具体行为;而示例是具体的,模型直接模仿就行。对于输出格式要求高的任务,示例的效果远好于规则描述。

6.2 别让 Agent 输出自由文本,强制 JSON

早期我让 Agent 输出自然语言,然后自己写正则去解析。结果模型今天用"建议:"明天用"推荐:"后天用"可以考虑:",正则改到崩溃。后来全部改成强制 JSON 输出,配合 JSON Schema 校验,解析问题彻底消失。

如果模型偶尔输出非法 JSON,加一个"修复重试"环节:把非法输出和错误信息一起发回给模型,让它修正。通常一次就能修好。

6.3 人工反馈闭环是系统进化的唯一途径

多 Agent 系统上线只是开始,真正的价值在于持续优化。我在每个 Agent 的输出旁边都加了"有用/无用"的反馈按钮,收集到的反馈每周复盘一次。

复盘时重点看两类:误报(AI 报了但实际没问题)和漏报(人工发现了但 AI 没报)。误报加到负面示例里,漏报加到正面示例里。这个闭环跑上几周,Agent 的准确率会有肉眼可见的提升。

6.4 不要追求全自动,人机协作才是正解

最后说一个心态上的坑。我一开始总想着"全自动",让 AI 直接打标签、直接阻塞合并、直接关闭 Issue。结果出了几次误判,团队对系统的信任度骤降。

后来我调整了定位:AI 做初筛和建议,人做最终决策。AI 把 80% 的重复劳动干掉,人只需要处理那 20% 需要判断的部分。这个定位下,团队接受度高得多,系统也真正融入了工作流。

环节全自动做法人机协作做法(推荐)
Issue 打标签AI 直接打AI 建议,人确认
PR 审查AI 阻塞合并AI 评论,人决定是否阻塞
CI 排障AI 自动重试并通知AI 自动重试,失败才通知人
优先级AI 直接定AI 建议,人调整

这套人机协作的边界,是我踩了无数坑之后总结出来的。核心就一句话:AI 负责"快",人负责"准"。两者结合,才是研发协作效率提升的正解。

7. 从零搭建这套系统的实操路线

7.1 先跑通单 Agent,再谈多 Agent

如果你也想搭一套类似的系统,我的建议是千万别一上来就搞多 Agent。先选一个最痛的场景(通常是 PR 审查或 CI 排障),用单 Agent 跑通,验证价值,积累提示词经验。等单 Agent 稳定了,再考虑拆分和协作。

多 Agent 的复杂度主要来自协作,而不是单个 Agent。如果单 Agent 都没跑明白,多 Agent 只会让你更混乱。

7.2 技术选型的几个务实建议

  • 模型选择:不要迷信最大的模型。Issue 分类、日志解析这类任务,中等模型加好的提示词就够了,成本低很多。只有 PR 审查这种需要深度推理的,才值得上大模型。
  • 向量库:Issue 去重需要向量检索,用轻量级的本地向量库即可,不必上重型方案。
  • 编排:如前所述,简单的状态机代码往往比编排框架更实用。
  • 部署:先跑在单机上,用定时任务或 webhook 触发。等稳定了再考虑容器化和高可用。

7.3 衡量效果的三个指标

系统上线后,怎么判断它有没有用?我盯三个指标:

  • 采纳率:AI 提出的意见中,被开发者实际采纳的比例。低于 30% 说明误报太多,需要优化。
  • 响应时间:从事件触发到 AI 给出结果的时间。超过 5 分钟体验就差了。
  • 人工节省:粗略估算 AI 帮团队省下了多少重复劳动时间。这个指标用来向团队证明价值。

这三个指标每周看一次,持续优化。系统不是搭完就完事,而是要像养一个团队成员一样持续调教。

7.4 一个最小可行版本的搭建顺序

如果你现在就想动手,我建议按这个顺序来:

  1. 先接一个平台的 webhook,能收到事件。
  2. 写一个最简单的 PR 审查 Agent,只做规范检查(命名、提交信息)。
  3. 把结果以评论形式发回 PR。
  4. 收集反馈,逐步增加审查维度。
  5. 稳定后,再加 Issue 分析 Agent。
  6. 最后加 CI 排障 Agent 和协调器。

每一步都验证价值后再往下走,不要贪多。我见过太多团队一上来就设计一个宏大的多 Agent 架构,结果卡在第一个 Agent 的提示词调优上,最后不了了之。

这套系统我前后迭代了大半年,从最初的一个脚本,长到现在四个 Agent 协作。回头看,最大的收获不是技术本身,而是理解了AI 在研发流程里的正确位置——它不是替代人,而是把人从重复劳动里解放出来,去做真正需要判断力的事。这个认知,比任何架构设计都重要。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进