Dify 企业级实验(01):多应用编排——如何让多个 Dify 应用协同完成一条业务链?
Dify 企业级实验(01):多应用编排——如何让多个 Dify 应用协同完成一条业务链?
Dify 实验系列 · 企业级 01/12 | 实验编号:DIFY-104-01
基于 Dify 1.16.1 实测(2026-08)
1. 业务场景
先看一个电商公司的日常。
用户消息进来,客服分流、订单质检、异常工单、周报汇总——四个环节各有一个独立 Dify 应用,很可能还是不同团队各自维护的。业务上它们是一条链:用户来咨询 → 判断这是什么问题 → 查这个订单有没有质量问题 → 有问题开个工单跟进 → 每周把订单质量汇总成报告。但技术上,这四个应用互不认识,信息全靠人肉搬运。
我们第一次接这类需求时,第一反应也是「系统多了自然各管一段,中间靠人搬数据呗」。后来翻 Dify 的文档才发现:平台原生就有 Workflow as Tool——应用可以发布为工具,一个工作流像调用函数一样调用其他应用。真正动手才明白——编排不是「多接一个应用」,而是把一条业务链画进一张拓扑图,孤岛之间的搬运从此消失。
这不是个例。任何「一条业务链被拆成多个系统/应用、各管一段」的场景都是这个模式:从下单到售后、从线索到成交、从工单到回访——环节越多,衔接成本越高。
2. 场景痛点
这个流程的痛点,在这家电商公司的运营团队身上体现得最直接:
- 人工衔接慢:分流结果要复制给质检、质检结论要粘贴进工单,单笔订单无所谓,一天几千单就是灾难——衔接动作不产生价值,却吃掉大量人力。
- 口径不一致:四个应用各自理解「投诉」「售后」「高风险」,分类结果对不上,工单开错方向,问题订单被漏跟。
- 状态割裂:周报要汇总本周订单质量,数据散在四个应用里,汇总靠导出表格手工拼,报告出来已经过了两天。
- 扩展困难:业务加一个新环节(比如加一个赔付审核),每个相关应用都要跟着改对接逻辑,牵一发动全身。
本质上,业务是一条链,系统却是一堆孤岛——最耗时的不是环节本身,而是环节之间的搬运。
3. 方案:为什么是Workflow as Tool 编排
Dify 有一个原生机制专门解决这个问题——Workflow as Tool:应用可以发布为工具,一个工作流像调用函数一样调用其他应用,把孤岛串成链。我们实际对比过几条路,选它的理由很直接:
- 平台原生能力:不用写胶水代码,应用发布为工具即可被调用,参数在 UI 里映射;
- 职责边界清晰:编排应用只做调度、不做业务,业务逻辑留在各自能力应用里,能力可复用、可单独维护;
- 端到端可观测:一条业务链在一个主流程里跑完,出问题能定位到具体环节,而不是在四个应用之间猜。
这篇文章我们就用它搭一个「订单全流程协同系统」:1 个编排应用调度 4 个能力应用(客服分流、订单质检、工单创建、周报汇总)。
4. 整体架构
链路很清晰:入口收消息 → 分流 → 质检 → 按需建单 → 组装结果。编排应用只做调度,业务逻辑全部留在能力应用里——这是多应用编排的关键设计。
5. 模块设计
5.1 能力应用发布为工具
每个能力应用先「发布为工具」,拿到 provider_id 后在编排应用 DSL 中引用。注意:重新发布后 provider_id 会变,运行前需按 app_id 动态查询最新值(102-08 实测教训的延续)。
5.2 编排应用的 tool 节点(tool5a 客服分流引擎)
tool 节点参数必须双写:tool_parameters 与 tool_configurations 同值(UI 显示与运行兼容):
- id: tool5a
data:
type: tool
title: 客服分流引擎
provider_type: workflow
provider_id: 2af54f30-b1e6-4cd6-bc7b-bebaf5818353
tool_name: dify104_fenliu
tool_parameters:
customer_message:
type: mixed
value: '{{#start.customer_message#}}'
tool_configurations: # 与 tool_parameters 同值,缺了 UI 面板显示空
customer_message:
type: mixed
value: '{{#start.customer_message#}}'
5.3 是否创建工单(if5)
三个条件用 or 组合——分类是投诉、分类是售后、质检风险为 high,任一命中即建单:
- id: if5
data:
type: if-else
title: 是否需要工单
cases:
- case_id: need_ticket
logical_operator: or
conditions:
- comparison_operator: is
value: 投诉
variable_selector: [tool5a, category]
- comparison_operator: is
value: 售后
variable_selector: [tool5a, category]
- comparison_operator: is
value: high
variable_selector: [tool5b, risk_level]
5.4 组装结果(cd5d)
tool 返回的是 JSON 字符串,必须用 code 节点解析后再拼装,不能直接给下游:
def main(category: str, quality_report: str, ticket_no: str, ticket_summary: str) -> dict:
parts = [f"分类:{category}", f"质检:{quality_report}"]
if ticket_no:
parts.append(f"工单:{ticket_no}")
return {"final_result": "\n".join(parts)}
5.5 质检风险校验(01_02 的 cd2,能力应用内)
命中负面关键词即标记高风险(negative_keywords = ["坏", "损坏", "破损", "退款", "退货", "投诉", "太差", "失望", "无法使用", "质量"]),并输出 quality_report 与 risk_reasons;订单号缺失只提示不阻断。
5.6 周报模板(01_04 的 tt4)
template-transform 用 Jinja2 取数组最后两条做环比,sales|length 判空兜底:
{% set sales = sales if sales else [] %}
{% set cur = sales[-1] if sales|length > 0 else {} %}
{% set prev = sales[-2] if sales|length > 1 else {} %}
- 订单量:{{ cur.get('orders', 0) }}(上周 {{ prev.get('orders', 0) }})
6. 运行验证
| 输入 | 预期 | 结果 |
|---|---|---|
| 含异常关键词的订单咨询(如「东西坏了,我要退款」) | 分流=投诉 → 质检风险=high → 建单,输出「分类:投诉 / 质检:…风险等级 high / 工单:WO-…」 | 通过(实测编排调 3 工具) |
| 普通咨询(如「订单多久能到?」) | 分流=咨询、风险=low,不建单,只输出分类 + 质检 | 通过 |
| 定时触发周报(report_week=本周) | 输出订单周报(订单量/营收/投诉数,含上周环比) | 通过 |
7. 实战坑
| 坑 | 现象 | 修复 |
|---|---|---|
| 重新发布工具后 provider_id 变化 | 编排应用调用报工具引用失效 | 运行前按 app_id 动态查询最新 provider_id 并同步 DSL(实测,102-08 教训延续) |
| tool 参数只写 tool_parameters | UI 面板显示空、手动调试报「不能为空」 | tool_parameters 与 tool_configurations 双写同值(实测,102-08) |
| tool 返回 JSON 字符串直接拼给下游 | 下游 LLM 拿到字符串乱用、字段取不到 | 先用 code 节点解析再拼装(实测,102-08) |
| code 节点沙箱禁写文件 | 报 PermissionError: /tmp |
存储统一走 http + 外部 KV 服务(实测,本批) |
| 编排应用里写业务逻辑 | 系统难维护,能力应用失去复用性 | 编排只做调度,业务逻辑留在能力应用(实验文档设计约束) |
8. 实验文档及源码获取
- 实验文档(完整操作步骤):DIFY-104-01:多应用编排系统——订单全流程协同.md
- 源码(可直接导入,一个应用一个 DSL):
- 源码一(客服分流):dify104_01_01_客服分流.yml
- 源码二(订单质检):dify104_01_02_订单质检.yml
- 源码三(工单创建):dify104_01_03_工单创建.yml
- 源码四(周报汇总):dify104_01_04_周报汇总.yml
- 源码五(订单编排,主流程):dify104_01_05_订单编排.yml
- 全部源码目录:dify-104/dsl
文章聚焦核心配置与采坑点;实验的完整分步操作(节点搭建/参数表/调试指引)见实验文档原文。
下一篇:Dify 企业级实验(02):跨应用状态传递——多轮对话的状态如何跨应用不丢?
💬 你在这个实验的场景里踩过什么坑?欢迎评论区分享你的实战经验。
更多推荐




所有评论(0)