Dify 中级实验(13):多 Agent 协作——如何编排多个智能体分工干活?
1. 业务场景
先讲一个我们实际遇到的场景。
一家咨询公司的合伙人每周要给客户交一份「企业全面分析报告」,里面要有市场、财务、技术三个维度的专业判断。以前这事靠三个分析师各写一块,再由合伙人汇总——成本高、周期长。他们想用 AI 替代:让一个 Agent 把整份报告写出来。结果呢?一个 Agent 干所有事,写出来的报告「样样通、样样松」:市场部分没有行业纵深,财务部分没有专业框架,技术部分浮于表面——一个模型很难同时具备三个专业领域的能力。
我们第一次接这类需求时,第一反应也是「让一个 Agent 把整份报告写完不就行了」。真正跑起来才发现——一个模型装不下三个专业领域:市场、财务、技术各有一套知识体系,塞给同一个 Agent,每个维度都只能泛泛而谈,报告「样样通、样样松」。
这不是个例。任何「需要多个专业视角、每个维度都需要专业知识」的场景都是这个模式:尽调报告要法律+财务+业务三路尽调、产品评审要设计+研发+运营三方意见、投资分析要宏观+行业+公司三层拆解——让一个 Agent 全包,不如让多个专业 Agent 各管一段、再汇总裁决。
2. 场景痛点
这个流程的痛点,在咨询公司的报告生产线上体现得最直接:
- 一个 Agent 专业深度不够:市场、财务、技术三个维度各需要一套专业知识,塞给同一个模型,每个维度都只能泛泛而谈,报告没有专业价值。
- 串行执行太慢:如果让一个 Agent 按顺序分析三个维度,总耗时是三段推理时间之和,客户等不起。
- 输出格式不统一:多个环节各自为政,有的输出散文、有的输出 JSON,汇总时解析失败,报告没法组装。
- 结论冲突没人裁决:市场分析师说「建议扩张」,财务分析师说「现金流紧张」,两个结论打架,报告里没人给出最终判断。
本质上,多 Agent 协作的问题不是「模型不够强」,而是「分工、并行、汇总裁决这套架构怎么搭」。
3. 方案:为什么是 Workflow 编排多 Agent
Dify 里怎么把多个 Agent 串起来?本实验给出两条可行路径:方案
A 用 HTTP 节点调用各 Agent 的 /v1/chat-messages
API(真实部署);方案 B 用代码节点模拟各 Agent
输出(导入即跑通,专注学编排逻辑)。
选它的理由:
- 并行执行省时间:三个专业分析师并行跑,总耗时 ≈ 最慢的那个节点,而不是三段串行之和;
- 职责单一、各管一段:每个分析师节点只吃自己的任务文本、只输出自己的专业结论,互不干扰;
- 汇总裁决有结构:首席分析师 LLM 拿到的三份结论带来源标注,冲突可以明确指出、给出判断,报告有专业味。
这篇文章我们就用它搭一个「多 Agent 报告生成器」:输入产品名 + 公司名 → 任务分发 → 市场/财务/技术三个专业分析师并行产出 → 首席分析师汇总成 Markdown 报告。
4. 整体架构
链路很清晰:入口收产品/公司名 → 任务分发拆成三个专业任务 → 三个分析师并行产出 → 首席分析师汇总裁决。关键设计是并行分支的输出变量名必须各不相同,否则汇合时互相覆盖,汇总结果必然错乱。
5. 模块设计
5.1 任务分发(Code)
def main(product_name: str, company_name: str) -> dict:
product = product_name or "目标产品"
company = company_name or "该公司"
return {
"market_task": "请对 {} 的 {} 产品进行市场分析(行业动态、竞品对比、市场趋势),输出 JSON 格式结果".format(company, product),
"finance_task": "请分析 {} 的财务数据(模拟数据:营收、成本、盈利、风险),输出 JSON 格式结果".format(company),
"tech_task": "请分析 {} 的 {} 产品的技术架构和成熟度(技术栈、优势、不足),输出 JSON 格式结果".format(company, product)
}5.2 专业分析师(Code 模拟,三节点同构)
每个节点只吃自己的任务文本,输出「报告文本 + JSON 串」双份,汇总与调试都有结构化数据可用:
def main(market_task: str) -> dict:
import json, time
time.sleep(0.5) # 模拟 Agent 推理耗时,便于观察并行
conclusion = {
"market_position": "行业跟随者(模拟结论)",
"competitors": ["竞品A", "竞品B"],
"trend": "上升",
"key_findings": ["目标市场年增速约15%", "竞品A 主打性价比", "本产品差异化空间在于服务"],
"market_report": "市场分析(模拟):任务「{}」→ 行业跟随者地位,主要竞品竞品A/B,趋势上升,建议聚焦差异化服务切入。".format(market_task[:20])
}
return {"market_report": conclusion["market_report"],
"market_json": json.dumps(conclusion, ensure_ascii=False)}财务、技术节点同理(finance_report/finance_json、tech_report/tech_json)。三个节点输出变量名必须不同,否则并行分支汇合时互相覆盖。
5.3 首席分析师汇总(LLM)
你是一个首席分析师。请综合以下三位专家的分析结果,生成一份完整的企业分析报告。
━━━ 市场分析 ━━━
{{market_report}}
━━━ 财务分析 ━━━
{{finance_report}}
━━━ 技术分析 ━━━
{{tech_report}}
要求:
1. 每个部分标注来源专家(市场分析师/财务分析师/技术分析师)
2. 如果专家之间有冲突观点,明确指出并给出你的判断
3. 最后给出综合结论和行动建议
4. 格式:Markdown 格式,包含标题、小节、要点
5. 直接输出报告正文,不要输出任何解释性文字
5.4 方案 A:HTTP 节点调 Agent API(真实部署)
方法: POST
URL: https://your-dify/v1/chat-messages
Headers:
Authorization: Bearer {{#env.DIFY_AGENT_API_KEY#}} # API Key 放环境变量,别硬编码
Content-Type: application/json
Body:
inputs: {}
query: "{{#cd_dispatch.market_task#}}"
response_mode: streaming # agent-chat 应用只支持 streaming
user: workflow-system6. 运行验证
| 输入 | 预期 | 实测 |
|---|---|---|
| product_name=智能客服系统,company_name=XX科技有限公司 | 三个分析师并行产出,总耗时 ≈ 最慢节点 | 三节点并行,约 0.5s 级完成 |
| 汇总报告含三节 | 市场/财务/技术各一小节并标注来源专家 | Markdown 三节齐全,来源标注明确 |
| 检查各分析师 JSON | market_json / finance_json / tech_json 可 json.loads | 全部可解析 |
| 换产品名再跑 | 三路任务文本同步更新 | 分发节点拼接正确,结论随之变化 |
7. 实战坑
| 坑 | 现象 | 修复 |
|---|---|---|
| 调 agent-chat 的 API 用 blocking | 调用失败/取不回结果 | response_mode 必须 streaming,HTTP 节点需解析 SSE 流;本地实验用方案 B 代码模拟(实测) |
| 并行分支输出变量同名 | 汇合后结果互相覆盖,汇总错乱 | 三个分析师节点输出不同名变量(market_/finance_/tech_ 前缀)(实验文档设计约束) |
| 各 Agent 输出格式不统一 | 汇总 LLM 拿到散文 + JSON 混合,解析失败 | 每个专业 Agent 的提示词里强制定义输出 JSON Schema(实验文档设计约束) |
| API Key 硬编码在 HTTP 节点 | 泄露风险 + 换 Key 要改流程 | 放环境变量,节点里
{{#env.xxx#}} 引用(实验文档设计约束) |
| 模拟节点不 sleep | 看不出并行效果,误以为串行 | 加 time.sleep(0.5)
让并行可见(实验文档设计约束) |
8. 实验文档及源码获取
- 实验文档(完整操作步骤):DIFY-14:多Agent协作编排.md
- 源码(可直接导入):dify102_14_多Agent报告生成器.yml
文章聚焦核心配置与采坑点;实验的完整分步操作(节点搭建/参数表/调试指引)见实验文档原文。
- Dify 中级实验(01):参数提取器实战——如何从自然语言中提取结构化数据?
- Dify 中级实验(02):问题分类器——智能路由引擎如何四路分发?
- Dify 中级实验(03):模板转换实战——如何用零 Token 完成文本加工?
- Dify 中级实验(04):迭代进阶——如何批量处理数据并守住性能边界?
- Dify 中级实验(05):并行执行——如何让多路任务同时跑?
- Dify 中级实验(06):变量聚合——如何确定性合并多路分支结果?
- Dify 中级实验(07):子工作流——如何把公共逻辑做成可复用积木?
- Dify 中级实验(08):代码节点进阶——如何用标准库处理文件与数据?
- Dify 中级实验(09):HTTP 节点进阶——如何搞定认证、分页与错误重试?
- Dify 中级实验(10):知识库深度调优——如何科学评估检索质量?
- Dify 中级实验(11):高级 RAG 流水线——如何搭建多路检索与精排?
- Dify 中级实验(12):Agent 深度配置——如何让智能体自主调用工具?
- Dify 中级实验(13):多 Agent 协作——如何编排多个智能体分工干活?
- Dify 中级实验(14):对话变量与状态管理——如何让工作流记住多轮对话的状态?
- Dify 中级实验(15):条件分支高阶策略——多条件路由如何避免分支爆炸?
- Dify 中级实验(16):错误处理与降级——工作流如何有尊严地失败?
- Dify 中级实验(17):调试监控与性能优化——响应慢和 Token 超支如何定位?
- Dify 中级实验(18):插件开发入门——如何把工作流变成 Agent 可调用的工具?
- Dify 中级实验(19):综合实战——如何把 19 个实验串成一条生产级流水线?
- Dify 中级实验(20):综合实战——自动化报告生成流水线如何从数据到周报一步到位?