mcpField
D
dify-workflow-skills

dify-workflow-skills

github.com/mango-svipAgent 工作流3236 次安装42 周前更新
代码仓库

关于 dify-workflow-skills

用于创建、编辑和验证 Dify 工作流 DSL 文件的技能,面向构建 Dify 自动化工作流的场景。内容涵盖节点、连接、变量及错误处理模式。

主要功能

  1. 01根据描述生成工作流 YAML
  2. 02编辑节点与连接
  3. 03验证 DSL 结构
  4. 04设计分支、循环和错误处理
  5. 05查阅节点类型与工作流模式

适用场景

  1. 01创建新的 Dify 自动化工作流
  2. 02在现有工作流中增删节点
  3. 03检查节点 ID、连接和变量引用

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mango-svip/dify-workflow-skills --skill dify-workflow-skills

安装后在 Claude Code 中输入/dify-workflow-skills确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
simple_llm_workflow.yml
error_handling_workflow.yml
conditional_workflow.yml
references/
node_types.md
node_positioning.md
workflow_structure.md
edge_types.md
scripts/
generate_id.py
validate_workflow.py

详细介绍

Dify 工作流 DSL 构建器

构建、编辑和验证 Dify 工作流 DSL(领域特定语言)文件,以创建 AI 驱动的自动化工作流。

此技能基于 Dify 开源平台的工作流引擎,该引擎通过基于 React Flow 的可视化编辑器为 Workflow 应用和 Advanced Chat 应用提供支持。

架构概览

Dify 工作流采用基于队列、事件驱动的架构,包含:

后端(Python - 执行引擎)
  • GraphEngine:负责管理工作流执行的中央协调器
  • WorkerPool:用于并行执行节点的线程池
  • VariablePool:集中管理各节点间的变量
  • EdgeProcessor:处理条件路由和分支选择
  • Graph Validator:在执行前确保工作流完整性
前端(React/TypeScript - 可视化编辑器)
  • React Flow:基于画布的节点图编辑器
  • Zustand Store:管理节点、边和视口状态
  • WorkflowContext:向组件树提供工作流状态
  • BaseNode:所有节点类型的通用封装,包含连接点、标题栏和交互功能
  • 面板系统:为每种节点类型提供动态配置面板
  • Hook 注入模式:将 UI 与执行逻辑解耦(草稿同步、工作流运行)
集成层
  • workflow:核心画布引擎(通用 React Flow 实现)
  • workflow-app:应用封装层(业务逻辑、API 集成、生命周期管理)
  • 草稿管理:自动保存,并通过防抖和 sendBeacon 提高安全性
    • 使用防抖同步,避免过多 API 调用
    • 卸载时取消待处理的同步,避免竞态条件
    • 使用 isWorkflowDataLoaded 标志跟踪加载状态
  • 功能系统:与工作流集成的可选功能(文件上传、语音转文本、引用)
  • 触发器状态管理:独立的存储,用于跟踪触发器节点的启用/禁用状态
    • 可独立启用或禁用触发器节点
    • 状态会在工作流编辑器会话之间保留
    • 用于 webhook、计划任务和插件触发器

核心功能

  1. 创建新工作流 - 根据描述生成完整的工作流 YAML 文件
  2. 编辑现有工作流 - 添加、修改或移除节点和连接
  3. 验证工作流 - 检查 DSL 语法和结构
  4. 设计复杂流程 - 构建包含 LLM 节点、代码执行、分支、循环和错误处理的工作流
  5. 错误处理策略 - 实现失败分支、重试或默认值错误处理

快速参考

节点类型:完整列表请参阅 references/node_types.md,包括:

  • 核心流程:start、end、answer
  • LLM 与 AI:llm、agent、parameter-extractor
  • 逻辑与控制:if-else、question-classifier、loop、iteration
  • 数据处理:code、template-transform、variable-aggregator、assigner、list-operator、document-extractor
  • 外部集成:http-request、tool、knowledge-retrieval、knowledge-index、datasource
  • 高级:trigger-webhook、trigger-schedule、trigger-plugin、human-input

边类型与连接:以下内容请参阅 references/edge_types.md:

  • 源句柄类型(source、true/false、success-branch/fail-branch、loop)
  • 边的数据属性和验证规则
  • 常见连接模式

节点定位:以下内容请参阅 references/node_positioning.md:

  • 画布坐标系和间距指南
  • 布局模式(线性、分支、错误处理、迭代)
  • 位置计算公式

常见节点属性:所有节点都支持以下内部属性(以 _ 为前缀):

  • _runningStatus:当前执行状态(running、succeeded、failed)
  • _connectedSourceHandleIds/_connectedTargetHandleIds:连接跟踪
  • _isSingleRun:用于调试的单次执行模式
  • _isCandidate:拖动连接时显示的虚拟节点
  • _children:容器类型节点(iteration、loop)的子节点
  • _iterationLength/_iterationIndex:迭代状态跟踪
  • _loopLength/_loopIndex:循环状态跟踪
  • _retryIndex:当前重试次数
  • _waitingRun:排队等待执行的 human-input

工作流结构:完整的 DSL 格式请参阅 references/workflow_structure.md

边类型:连接模式和句柄类型请参阅 references/edge_types.md

节点定位:布局指南请参阅 references/node_positioning.md

模板:请查看 assets/ 中的工作流示例

创建新工作流

步骤 1:了解需求

询问用户:

  • 工作流应该做什么?
  • 输入和输出是什么?
  • 需要哪些处理步骤?
  • 是否需要条件逻辑或错误处理?
步骤 2:设计节点流程

规划工作流结构:

  1. 开始节点 - 定义输入变量
  2. 处理节点 - LLM、代码、工具等
  3. 控制流 - 使用 if-else 分支,使用 loop 迭代
  4. 错误处理 - 在代码节点上使用 fail-branch
  5. 输出聚合 - 使用 variable-aggregator 合并分支
  6. 结束节点 - 定义输出
步骤 3:生成节点 ID

使用 scripts/generate_id.py 创建唯一的节点 ID:

python3 scripts/generate_id.py 5  # Generate 5 unique IDs

或者使用 Python/JavaScript 生成:

# Python
import time
node_id = str(int(time.time() * 1000))
// JavaScript (used in Dify frontend)
const nodeId = `${Date.now()}`

容器节点的特殊 ID 模式:

  • 迭代/循环开始节点:${parentNodeId}start
  • 示例:如果迭代节点 ID 为 1736668800000,其开始节点 ID 为 1736668800000start
步骤 4:构建工作流

创建完整的 YAML 结构,包括:

  • 顶层元数据(kind、version、app)
  • App 部分(名称、描述、图标)
  • 包含 features 和 graph 的 Workflow 部分
  • 包含位置的节点数组
  • 用于连接节点的边数组

使用的模板:从 assets/simple_llm_workflow.yml 开始构建基本流程

步骤 5:验证

检查工作流结构是否存在常见问题:

  • 所有节点都有唯一 ID
  • 所有边都引用现有节点 ID
  • 开始和结束节点都存在
  • 必需字段均已填写
  • 变量引用使用正确的语法:{{#node_id.field#}}

常见工作流模式

模式 1:简单 LLM 流程

开始 → LLM → 结束

使用场景:基础问答、文本生成

模板:assets/simple_llm_workflow.yml

模式 2:错误处理流程

开始 → 代码(带失败分支)→ [成功 → 聚合器] / [失败 → LLM 恢复 → 重试 → 聚合器] → 结束

使用场景:通过错误恢复实现可靠的数据处理

模板:assets/error_handling_workflow.yml

要点:

  • 在代码节点上设置 error_strategy: fail-branch
  • 失败分支提供 error_message 和 error_type 变量
  • 使用变量聚合器合并成功和失败分支
  • 在结束节点中引用聚合器输出
模式 3:条件路由

开始 → If-Else → [真 → 处理器 A] / [假 → 处理器 B] → 聚合器 → 结束

使用场景:根据内容/类型路由请求

模板:assets/conditional_workflow.yml

要点:

  • If-else 有 true 和 false sourceHandles
  • 使用比较运算符:contains、starts_with、is_empty 等
  • 使用 logical_operator: "and" 或 "or" 组合条件
模式 4:循环处理

开始 → 循环 → [处理项目] → 循环结束 → 结束

使用场景:通过中断条件进行迭代处理

要点:

  • 设置 loop_count 以指定最大迭代次数
  • 定义 break_conditions 以提前退出
  • 循环会在各次迭代之间保留状态

编辑现有工作流

添加节点
  1. 读取现有工作流文件
  2. 生成新的唯一节点 ID
  3. 将节点添加到 workflow.graph.nodes 数组中,并包含:
    • 唯一 ID 和位置
    • 节点类型和配置
    • 正确的 sourcePosition/targetPosition
  4. 添加边,将新节点连接到 workflow.graph.edges
  5. 更新任何依赖节点(例如结束节点的输出)
删除节点
  1. 确定要删除的节点 ID
  2. 从 workflow.graph.nodes 中删除节点
  3. 删除所有引用该节点 ID 的边(作为源或目标)
  4. 更新引用了已删除节点输出的下游节点
修改连接
  1. 根据源节点和目标节点 ID 查找边
  2. 更新边的 source、target、sourceHandle 或 targetHandle
  3. 更新边的 data.sourceType 和 data.targetType,使其与实际节点类型匹配
  4. 更新边的 id,遵循命名约定:{source_id}-{handle}-{target_id}-target

变量引用语法

变量由集中式的 VariablePool 管理,格式为:{{#node_id.field_name#}}

变量类型(VarType)

Dify 支持以下变量类型,以实现类型安全的数据流:

基本类型:

  • string:文本数据
  • number:浮点数
  • integer:整数
  • boolean:true/false 值
  • secret:加密的敏感数据(API 密钥、密码)

复杂类型:

  • object:JSON 对象
  • file:单个文件引用
  • array:通用数组
  • array[string]:字符串数组
  • array[number]:数字数组
  • array[object]:对象数组
  • array[boolean]:布尔值数组
  • array[file]:文件数组
  • array[any]:混合类型数组
  • any:任意类型(请谨慎使用)

特殊类型:

  • contexts:知识检索结果
  • iterator:迭代输入变量
  • loop:循环输入变量
文件上传配置

使用文件输入类型(file、files、file-list)时,可以配置上传设置:

默认文件上传设置:

allowed_file_upload_methods: ['local_file', 'remote_url']
max_length: 5  # Maximum number of files
allowed_file_types: ['image']  # Options: image, document, audio, video, custom
allowed_file_extensions: []  # e.g., ['.pdf', '.docx']

上传方式:

  • local_file:从本地系统直接上传文件
  • remote_url:从 URL 上传文件

文件类型类别:

  • image:图像文件(JPG、PNG、GIF 等)
  • document:文档文件(PDF、DOCX、TXT 等)
  • audio:音频文件(MP3、WAV 等)
  • video:视频文件(MP4、AVI 等)
  • custom:自定义文件类型(指定扩展名)
输入变量类型(InputVarType)

开始节点使用以下输入类型作为面向用户的变量:

  • text-input:单行文本输入
  • paragraph:多行文本输入
  • select:下拉选择
  • number:数字输入
  • checkbox:布尔复选框
  • url:带验证的 URL 输入
  • files:多文件上传
  • file:单文件上传
  • file-list:多文件列表
  • json:JSON 输入(对象或数组)
  • json_object:带模式验证的 JSON 对象
  • contexts:知识检索上下文
  • iterator:迭代变量
  • loop:循环变量
变量选择器模式

变量模式正则表达式:{{#[a-zA-Z0-9_]{1,50}(?:\.[a-zA-Z_][a-zA-Z0-9_]{0,29}){1,10}#}}

选择器结构:[node_id, variable_name, ...optional_nested_keys]

  • 第一个元素:生成该变量的节点 ID
  • 第二个元素:变量名称或输出字段
  • 其他元素:嵌套对象键或数组索引(适用于 FileSegment/ObjectSegment)

ValueSelector:DSL 中使用的数组格式(例如,['1732007415808', 'text'])

  • 在 YAML 中表示为数组:value_selector: ['node_id', 'field_name']
  • 在提示词中转换为模板语法:{{#node_id.field_name#}}
系统变量

可通过 sys 节点 ID 使用:

  • {{#sys.query#}} - 用户查询/输入
  • {{#sys.files#}} - 上传的文件
  • {{#sys.conversation_id#}} - 当前对话 ID
  • {{#sys.user_id#}} - 用户标识符
  • {{#sys.dialogue_count#}} - 对话轮数
  • {{#sys.app_id#}} - 应用 ID
  • {{#sys.workflow_id#}} - 工作流 ID
  • {{#sys.workflow_run_id#}} - 当前执行 ID
  • {{#sys.timestamp#}} - 当前时间戳
按节点类型划分的常见输出字段

LLM 节点:

  • {{#node_id.text#}} - 生成的文本响应(类型:string)
  • {{#node_id.usage#}} - Token 使用信息(类型:object)
  • {{#node_id.reasoning_content#}} - 模型推理内容(如已启用)(类型:string)

Agent 节点:

  • {{#node_id.usage#}} - Token 使用信息(类型:object)

代码节点:

  • {{#node_id.output_name#}} - 节点配置中定义的命名输出
  • {{#node_id.error_message#}} - 错误消息(仅失败分支)(类型:string)
  • {{#node_id.error_type#}} - 错误类型(仅失败分支)(类型:string)

开始节点:

  • {{#node_id.variable_name#}} - 开始节点中定义的输入变量

条件分支节点:

  • {{#node_id.condition_result#}} - 布尔条件结果

循环节点:

  • {{#node_id.output#}} - 循环输出数组
  • {{#node_id.iteration#}} - 当前迭代次数

HTTP 请求节点:

  • {{#node_id.body#}} - 响应正文(类型:string)
  • {{#node_id.status_code#}} - HTTP 状态码(类型:number)
  • {{#node_id.headers#}} - 响应标头(类型:object)
  • {{#node_id.files#}} - 响应为文件时下载的文件(类型:array[file])

工具节点:

  • {{#node_id.text#}} - 工具输出文本(类型:string)
  • {{#node_id.files#}} - 工具输出文件(类型:array[file])
  • {{#node_id.json#}} - 工具输出 JSON(类型:array[object])

知识检索节点:

  • {{#node_id.result#}} - 检索到的知识片段(类型:array[object])

模板转换节点:

  • {{#node_id.output#}} - 转换后的输出(类型:string)

问题分类器节点:

  • {{#node_id.class_name#}} - 分类结果(类型:string)
  • {{#node_id.usage#}} - Token 使用信息(类型:object)

参数提取器节点:

  • {{#node_id.__is_success#}} - 提取成功标识(类型:number)
  • {{#node_id.__reason#}} - 提取失败原因(类型:string)
  • {{#node_id.__usage#}} - Token 使用信息(类型:object)
  • 以及节点配置中定义的自定义提取参数

变量聚合器:

  • {{#node_id.output#}} - 合并分支的聚合输出

文件对象结构(使用文件类型时):

  • name - 文件名(类型:string)
  • size - 文件大小,单位为字节(类型:number)
  • type - 文件类型类别(类型:string)
  • extension - 文件扩展名(类型:string)
  • mime_type - MIME 类型(类型:string)
  • transfer_method - 使用的传输方式(类型:string)
  • url - 文件 URL(类型:string)
  • related_id - 相关资源 ID(类型:string)

知识检索结果结构:

{
  "content": "",
  "title": "",
  "url": "",
  "icon": "",
  "metadata": {
    "dataset_id": "",
    "dataset_name": "",
    "document_id": [],
    "document_name": "",
    "document_data_source_type": "",
    "segment_id": "",
    "segment_position": "",
    "segment_word_count": "",
    "segment_hit_count": "",
    "segment_index_node_hash": "",
    "score": ""
  }
}
环境变量和对话变量

环境变量(在应用级别定义):

  • 通过特殊节点 ID 访问:env
  • 示例:{{#env.API_KEY#}}

对话变量(会话状态):

  • 通过特殊节点 ID 访问:conversation
  • 示例:{{#conversation.user_context#}}
变量用法示例
# In LLM prompt template
prompt_template:
  - role: system
    text: "You are a helpful assistant."
  - role: user
    text: "Process this input: {{#1732007415808.user_input#}}"

# In code node
variables:
  - ["1732007415808", "user_input"]
  - ["1732007420123", "processed_data"]

# Accessing nested object fields
text: "File name: {{#upload_node.files.name#}}"
text: "API response status: {{#http_node.status_code#}}"

节点定位

在画布上定位节点,确保视觉清晰:

布局常量(来自 Dify 前端):

  • NODE_WIDTH:240 像素
  • X_OFFSET:60 像素(水平间距)
  • NODE_WIDTH_X_OFFSET:300 像素(节点宽度 + 间距)
  • Y_OFFSET:39 像素
  • START_INITIAL_POSITION:{ x: 80, y: 282 }
  • NODE_LAYOUT_HORIZONTAL_PADDING:60 像素
  • NODE_LAYOUT_VERTICAL_PADDING:60 像素
  • NODE_LAYOUT_MIN_DISTANCE:100 像素

容器节点内边距:

  • 迭代/循环容器:
    • 上:65,右:16,下:20,左:16
  • 迭代/循环的 Z-index:1(容器),1002(子节点)

水平间距:相连节点之间为 300-400 像素
垂直间距:

  • 同一层级:y 坐标相同
  • 分支:偏移 150-200 像素

位置示例:

Start: x=80, y=282 # Initial position
LLM: x=380, y=282  # Start + NODE_WIDTH_X_OFFSET
Code: x=680, y=282
End: x=980, y=282

分支示例:

If-else: x=380, y=300
True branch: x=680, y=200
False branch: x=680, y=450
Aggregator: x=980, y=300

容器节点(迭代/循环):

  • 容器内的起始节点:{ x: 24, y: 68 }(相对于容器)
  • 子节点的 parentId 设为容器 ID
  • 子节点的 Z-index(1002)高于容器(1)

详细布局模式和公式请参阅 references/node_positioning.md。

可视化编辑器集成

你创建的 DSL 会在基于 React Flow 构建的 Dify 可视化工作流编辑器中渲染。

DSL 如何映射到 UI

节点 → 画布上的可视化块,包括:

  • 图标和标题(来自 type 和 title 字段)
  • 连接手柄(根据节点类型和 error_strategy)
  • 配置面板(右侧栏中的节点专属表单)
  • 状态指示器(运行中、成功、失败)

边 → 连接节点的贝塞尔曲线,包括:

  • 根据状态设置视觉样式(悬停、选中、运行中)
  • 分支路径标签(true/false、分类标签)
  • 成功/失败分支的颜色编码

视口 → 画布视图设置:

viewport:
  x: 0      # Pan offset X
  y: 0      # Pan offset Y
  zoom: 1.0 # Zoom level (0.1 to 2.0)
前端组件架构

将 DSL 加载到编辑器时:

  1. WorkflowContextProvider 使用节点/边初始化 Zustand 存储
  2. ReactFlow 使用自定义节点组件渲染画布
  3. BaseNode 为每个节点封装通用 UI(连接手柄、标题栏)
  4. 面板系统 在选中节点时显示配置表单
  5. Hook 系统 管理草稿自动保存和执行
DSL 中不包含的 UI 功能

这些仅限 UI 的属性由前端管理(不要包含在 DSL 中):

  • _hovering、_connectedNodeIsHovering:鼠标交互状态
  • _connectedSourceHandleIds、_connectedTargetHandleIds:根据边计算得出
  • _runningStatus、_singleRunningStatus:运行时执行状态
  • _isCandidate:连接拖动过程中的临时虚拟节点
  • selected:节点选中状态

重要:DSL 中只包含持久化属性(id、type、title、position、configuration)。运行时 UI 状态由编辑器计算。

错误处理策略

错误策略

Dify 支持在节点配置中定义多种错误处理策略:

1. fail-branch(推荐用于代码/HTTP 节点):

  • 出错时创建备用执行路径
  • 提供 error_message 和 error_type 变量
  • 在边配置中使用 sourceHandle: "fail-branch"
  • 成功路径使用 sourceHandle: "success-branch"
  • 需要使用变量聚合器在继续到结束节点之前与成功路径合并
  • 支持平稳恢复错误和自定义错误处理逻辑

2. default-value:

  • 出错时返回预定义的默认值
  • 继续主执行路径,不进行分支
  • 比 fail-branch 简单,但可靠性较低
  • 适用于可接受回退值的非关键操作

3. abort(默认):

  • 失败时停止整个工作流的执行
  • 无需额外配置
  • 用于无法恢复的错误

4. retry:

  • 可配置重试逻辑,包括最大重试次数和间隔
  • 在节点的 retry_config 部分定义
  • 适用于暂时性故障(网络问题、速率限制)
  • 支持的节点:仅限 LLM、工具、HTTP 请求和代码节点

重试配置结构:

retry_config:
  max_retries: 3        # Maximum retry attempts (default: 3)
  retry_interval: 100   # Interval between retries in ms (default: 100)
实现 fail-branch 错误处理

在节点配置中:

error_strategy: fail-branch

在边数组中:

# Success path
- id: code_node-success-branch-next_node-target
  source: code_node_id
  target: aggregator_id
  sourceHandle: success-branch
  targetHandle: target

# Failure path
- id: code_node-fail-branch-error_handler-target
  source: code_node_id
  target: error_handler_id
  sourceHandle: fail-branch
  targetHandle: target

fail-branch 中可用的错误变量:

  • {{#node_id.error_message#}} - 人类可读的错误说明
  • {{#node_id.error_type#}} - 错误类型分类

验证清单

在完成工作流之前,请验证:

结构验证
  • 所有节点 ID 均唯一且格式正确(数字字符串或有效标识符)
  • 工作流恰好有一个根节点(开始、数据源或触发器节点)
  • 工作流至少有一个结束节点
  • 所有边均引用节点数组中存在的有效源节点和目标节点 ID
  • 不存在会造成无限循环的循环依赖(有意使用的循环节点除外)
  • 根节点已正确识别且可访问
边和连接验证
  • 所有边 ID 均唯一
  • 边的 sourceHandle 值与节点类型相匹配:
    • 标准节点:"source"(默认)
    • If-else/问题分类器:"true"、"false" 或分类标签
    • 带错误处理的代码/HTTP 节点:"success-branch" 或 "fail-branch"
    • 循环节点:用于继续执行的 "loop"
  • 对于大多数节点,边的 targetHandle 通常为 "target"
  • 边的 data.sourceType 与实际源节点类型相匹配
  • 边的 data.targetType 与实际目标节点类型相匹配
  • 分支路径(来自 if-else、问题分类器)均为所有可能结果配置了边
  • 使用 error_strategy: fail-branch 时,存在 fail-branch 边
变量和数据流验证
  • 变量引用使用正确语法:{{#node_id.field#}}
  • 所有引用的变量均存在于上游节点(在当前节点之前执行的节点)中
  • 变量选择器与引用节点的实际输出字段相匹配
  • 系统变量使用正确的 sys 前缀:{{#sys.query#}}
  • 如有需要,环境变量使用 env 前缀
  • 不存在会导致运行时错误的未定义变量引用
错误处理验证
  • 使用 error_strategy: fail-branch 的节点同时具有成功边和失败边
  • 分支路径在到达结束节点之前通过变量聚合器合并
  • 变量聚合器接收来自所有分支路径的输入
  • 使用 error_strategy: default-value 时,已提供默认值
  • 使用重试策略时,重试配置有效(最大重试次数、间隔)
节点配置验证
  • 每种节点类型都包含必填字段(参见 node_types.md)
  • 设置节点位置以进行可视化布局(x、y 坐标)
  • LLM 节点具有有效的模型配置(provider、name、mode)
  • Code 节点指定了有效的语言(python3 或 javascript)
  • HTTP 请求节点具有有效的 URL 和方法
  • Loop 节点具有有效的 loop_count 和中断条件
  • If-else 节点具有结构正确且运算符有效的条件
工作流执行验证
  • 没有不可达节点(所有节点都能从根节点到达)
  • 所有执行路径最终都会到达 end 节点或 answer 节点
  • 容器节点(iteration、loop)具有正确的开始/结束节点对
  • 人工输入节点使用得当(工作流会暂停以等待输入)
  • Trigger 节点(webhook、schedule)不能与标准 start 节点混用

节点执行类型

Dify 根据节点的执行行为对其进行分类。了解这些类型有助于设计正确的工作流:

EXECUTABLE(标准逻辑节点)

执行逻辑并生成输出。最常见的节点类型。

  • 示例:llm、code、http-request、knowledge-retrieval、template-transform
  • 行为:满足所有输入依赖项后执行
  • 源句柄:"source"(或在错误处理中使用 "success-branch"/"fail-branch")
  • 输出:由节点类型定义(参见“变量参考”部分)
BRANCH(条件路由节点)

根据条件在多条路径中进行选择,以控制流程。

  • 示例:if-else、question-classifier
  • 行为:评估条件并激活一条或多条输出边
  • 源句柄:
    • If-else:"true"、"false"
    • Question-classifier:分类标签(自定义)
  • 重要提示:未选中的路径会标记为“skipped”,其下游节点不会执行
CONTAINER(子图管理)

通过迭代或循环管理嵌套执行上下文。

  • 示例:iteration、loop
  • 行为:多次执行内部子图
  • 组件:
    • 父容器节点
    • 内部开始节点(iteration-start、loop-start)
    • 内部结束节点(iteration-end、loop-end)
  • 源句柄:"loop",用于继续迭代/循环
  • 状态管理:维护循环变量和迭代次数
RESPONSE(输出流)

实时向用户流式传输输出。

  • 示例:answer、end
  • 行为:输出结果,并可能完成工作流
  • 用法:Answer 节点可以出现在工作流中途;End 节点会终止执行
ROOT(入口点)

作为工作流的入口点。

  • 示例:start、datasource、trigger-webhook、trigger-schedule、trigger-plugin
  • 行为:第一个执行的节点;没有入边
  • 重要提示:每个工作流只能有一个根节点
  • 约束:标准 start 节点和 Trigger 节点不能共存
支持输出变量的节点

以下节点类型可以生成供其他节点引用的输出变量:

  • Start、TriggerWebhook、TriggerPlugin
  • LLM、Agent
  • KnowledgeRetrieval
  • Code
  • TemplateTransform
  • HttpRequest
  • Tool
  • VariableAssigner、VariableAggregator
  • QuestionClassifier
  • ParameterExtractor
  • Iteration、Loop
  • DocumentExtractor(DocExtractor)
  • ListFilter(list-operator)
  • DataSource

注意:不在此列表中的节点(如 if-else、end、answer)通常不会生成可复用的输出变量,不过其中一些节点可能具有有限的内部状态。

工作流执行模型

执行流程
  1. 初始化:GraphEngine 将根节点加入 ReadyQueue
  2. 工作线程执行:工作线程从 ReadyQueue 拉取节点并执行
  3. 事件发出:工作线程将事件(started、succeeded、failed)推送到 event_queue
  4. 边处理:Dispatcher 处理事件并识别下游节点
  5. 依赖解析:依赖满足时,将下游节点加入 ReadyQueue
  6. 并行执行:多个工作线程并发执行互不依赖的节点
  7. 完成:End 节点执行完毕或执行失败时,工作流结束
边状态

执行期间,边可能处于以下三种状态:

  • UNKNOWN:初始状态,尚未评估
  • TAKEN:边已遍历(条件满足或路径已选定)
  • SKIPPED:边未遍历(条件不满足或选择了替代路径)
工作流执行状态

工作流会经历以下状态:

  • SCHEDULED:已排队但尚未启动
  • RUNNING:正在执行
  • SUCCEEDED:已完成且无错误
  • FAILED:因未处理的错误而终止
  • PARTIAL_SUCCEEDED:已完成,但存在已处理的错误(通过 fail-branch 或 default-value)
  • STOPPED:已手动停止或中止
  • PAUSED:正在等待人工输入(human-input 节点)
节点运行状态

单个节点会通过以下状态跟踪其执行状态:

  • NOT_START:节点尚未开始执行
  • WAITING:节点已排队,正在等待执行
  • LISTENING:节点正在监听事件(触发器节点)
  • RUNNING:节点正在执行
  • SUCCEEDED:节点已成功完成
  • FAILED:节点因未处理的错误而失败
  • EXCEPTION:节点执行失败,但错误已得到处理
  • RETRY:节点在失败后重试
  • STOPPED:节点执行已停止

重要的 UI 状态属性(仅运行时,不在 DSL 中):

  • _runningStatus:当前执行状态
  • _singleRunningStatus:运行单个节点时的状态
  • _waitingRun:节点已排队等待执行
  • _retryIndex:当前重试次数
  • _isSingleRun:节点处于单次运行调试模式
执行最佳实践
  1. 并行与顺序:互不依赖的节点会自动并行执行。需要时使用边强制按顺序执行。
  2. 错误边界:在关键节点上使用 fail-branch,防止工作流中止
  3. 合并点:在分支汇合前,始终使用 variable-aggregator 合并分支
  4. 循环安全性:设置合理的 loop_count 限制和明确的中断条件
  5. 人工输入:使用 human-input 节点时,应考虑工作流暂停状态

资源

scripts/
  • generate_id.py - 为工作流生成唯一的节点 ID
  • validate_workflow.py - 验证工作流 DSL 语法(需要 PyYAML)
references/
  • node_types.md - Dify 所有节点类型的完整参考及示例
  • workflow_structure.md - DSL 结构和格式规范详解
assets/
  • simple_llm_workflow.yml - 基本的 start→LLM→end 模板
  • error_handling_workflow.yml - 包含 fail-branch 错误处理的模板
  • conditional_workflow.yml - 包含 if-else 分支的模板

成功提示

  1. 从简单开始:先构建基本流程,再逐步增加复杂性
  2. 使用模板:改造现有模板,而不是从头开始
  3. 尽早验证:添加大量节点前先检查结构
  4. 规划错误处理:考虑可能发生的错误以及如何处理
  5. 清晰命名:使用描述性节点标题,便于维护
  6. 参考文档:查阅 node_types.md,了解字段要求
  7. 逐步测试:逐步构建并测试工作流

评论

支持 Markdown