Workflow 还是 Chatflow
两种应用类型共用同一块画布和同一套节点。文档把大部分工作描述成拖动、连接和配置,只有逻辑需要时才写代码。区别在于人们怎样使用结果。
Workflow 接收一个输入,把整个流程跑一遍,返回一个结果,适合生成报告、处理数据和批量任务。Chatflow 在前面放一个聊天窗口:每条消息都先跑一遍流程再回复,适合助手和有引导的问答。
它们的开始和结束节点不同。Workflow 从 User Input 或 Trigger(触发器)开始,触发器可以按计划、由 Webhook 或由集成事件启动流程。Chatflow 总是从 User Input 开始,所以没有触发器。Chatflow 必须以 Answer 节点结束。Workflow 可以用 Output 节点结束,这个节点以前叫 End。文档称它为可选,但没有 Output 节点的分支不会给调用方返回任何数据。
最常用的节点
你在 User Input 节点里添加的每个字段,都会变成后面节点可以使用的变量。在任何文本框里输入 { 或 / 就能选变量,编辑器会替你写出 {{variable_name}} 这样的引用。
| 节点 | 作用 | 文档里的说明 |
|---|---|---|
| User Input | 收集用户输入的内容 | 每块画布只能有一个。Short Text 最多 256 个字符。其他字段类型有段落、下拉选择、数字、复选框、JSON 和文件 |
| LLM | 用你的提示词调用模型 | Temperature 从 0(确定性)到 1(有创意)。结构化输出会返回有名字的字段,供下一个节点读取 |
| Knowledge Retrieval | 搜索你的知识库 | 返回一个结果列表。把 LLM 节点的 Context 设为它。第 3 课会讲 |
| IF/ELSE | 让运行走向某一个分支 | IF、ELIF 和 ELSE 三种路径。条件可以用 AND 或 OR 组合 |
| Code | 运行 Python 或 JavaScript | 函数必须返回一个字典,里面包含声明过的输出 |
| HTTP Request | 调用外部 API | 支持 GET、HEAD、POST、PUT、PATCH 和 DELETE。认证、请求体和超时在每个节点里单独设置 |
| Template | 用 Jinja2 排版文本 | 按规则排版,不消耗 token |
| Output 或 Answer | 返回结果 | Workflow 用 Output,Chatflow 用 Answer |
搭建内容生成器
文档的30 分钟快速入门搭了一个工作流:它接收草稿、可选的文件、语气和风格、目标平台和语言,然后为每个平台返回一条帖子。它在 Dify Cloud 上运行,页面说在自托管的实例上照同样的步骤做就行。下面的步骤按它的顺序做了精简。Parameter Extractor(参数提取器)是让模型从自由文本里提取结构化数值的节点,这里它把用户随手输入的内容变成一份干净的平台列表。
# TASK DESCRIPTION
Parse platform names from input and output as a JSON array.
## PROCESSING RULES
- Support multiple delimiters: commas, semicolons, spaces, line breaks, "and", "&", "|", etc.
- Standardize common platform name variants (twitter/X→Twitter, insta→Instagram, etc.)
- Remove duplicates and invalid entries
- Preserve unknown but reasonable platform names
- Preserve the original language of platform names
## OUTPUT REQUIREMENTS
- Success: ["Platform1", "Platform2"]
- No platforms found: [No platforms identified. Please enter a valid platform name.]
## EXAMPLES
- Input: "twitter, linkedin" → ["Twitter", "LinkedIn"]
- Input: "x and insta" → ["Twitter", "Instagram"]
- Input: "invalid content" → [No platforms identified. Please enter a valid platform name.]- 在 Studio 里选“Create from Blank”>“Workflow”,命名为
Multi-platform content generator,点“Create”。 - 在 User Input 节点里添加五个字段。
draft是必填的段落,最大长度 2048。user_file是文件列表,收文档和图片。voice_and_tone是段落,platform是必填的短文本。最后的language是必填的下拉选择,选项是 English、日本語 和 简体中文。 - 添加一个 Parameter Extractor。把“Input Variable”设为
User Input/platform,添加一个名为platform、类型为 Array[String] 的提取参数,设为必填,再把上面的指令粘贴到“Instruction”里。 - 添加一个 IF/ELSE 节点,条件是
Parameter Extractor/platformcontainsNo platforms identified. Please enter a valid platform name.。在 IF 分支上放一个 Output 节点,返回Parameter Extractor/platform。这样平台名无效时,运行会提前结束,不会把 token 花在没用的内容上。 - 在 ELSE 分支上并排添加两个 List Operator 节点,输入都是
User Input/user_file。一个筛选类型为 Image,另一个筛选类型为 Doc。 - 文档这一支后面加一个 Doc Extractor,把 PDF 和 DOCX 文件转成纯文本,因为教程里的模型不能直接读取它们。
- 添加一个名为
Integrate Info的 LLM 节点。打开 Vision,把图片这一支设为视觉变量,让它把草稿、文档文本和图片整理成一份结构化的摘要。 - 添加一个 Iteration 节点。里面先放一个 LLM 节点
Identify Style,为Current Iteration/item写出平台风格指南,再放一个 LLM 节点Create Content,用结构化输出写帖子,输出包含platform_name和post_content。 - 在 Iteration 节点上,把输入设为
Parameter Extractor/platform,输出设为Create Content/structured_output。打开 Parallel Mode,最大并行数设为 10,让各个平台的帖子同时生成。
排版结果并运行
Iteration 节点返回的是一份原始的列表,里面是一对对平台和帖子。Template 节点用 Jinja2(一种模板语言)把这份列表变成易读的文本。快速入门提到,模型也能排版,但每次的结果不一样,而按规则写的模板不消耗 token。下面是快速入门里的模板,只去掉了开头的手机表情符号。
{% for item in output %}
# {{ item.platform_name }}
{{ item.post_content }}
{% endfor %}- 在 Iteration 节点后面添加一个 Template 节点。把
Iteration/output设为它的输入变量,命名为output,再粘贴上面的模板。 - 添加一个 Output 节点,把
Template/output设为它的输出变量。 - 确认 Checklist 已清空,再把你的画布和快速入门里的示意图对照一遍。
- 点右上角的“Test Run”,填好各个字段,点“Start Run”。文档建议的草稿是:“We just launched a new AI writing assistant that helps teams create content 10x faster.”再填上语气“Friendly and enthusiastic, but professional”,平台“Twitter and LinkedIn”,语言选 English。
Code 节点和 HTTP Request 节点
预设节点做不了的事交给 Code 节点。你声明输入变量和输出变量,函数必须返回一个字典,里面包含声明过的输出,和第 1 课里的 main 函数一样。输出超过下面任何一项限制,节点就会失败。
Code 和 HTTP Request 都有“Retry on failure”,最多重试 10 次,间隔最长 5000 毫秒。它们的“Error Handling”选项可以定义备用路径,这样其中一个失败时,流程的其余部分还能继续。
HTTP Request 节点在一个面板里设置方法、网址、请求头、查询参数、请求体和认证。认证方式是 No Auth 或 API Key,API Key 又分 Basic、Bearer 和 Custom 三种。请求体可以是 JSON、Form Data、Binary 或 Raw Text。响应会拆成几个变量返回:正文、状态码、响应头、文件和大小。Secret 类型的环境变量,在运行日志和这个节点的请求日志里会被遮蔽。
运行和调试工作流
你可以单独测试一个节点:选中它,在它的面板里给出测试输入,点“Run”。文档说 Answer 和 End 节点不支持单节点测试。End 是 Output 节点以前的名字,这页没有提到新名字,所以要检查 Output 节点,就跑一次整个流程。整个流程的运行和单个节点的运行都会留下记录,有四个工具来读取它们。
Variable Inspector(变量检查器)保存着每个节点产生的数据。逐个运行节点时,它们的输出缓存在这里,你可以修改大多数值,再用修改后的值运行下游节点,上游的节点不用重跑。快速入门说,点画布底部的“View cached variables”也能打开同一份列表。
| 工具 | 显示什么 | 用来做什么 |
|---|---|---|
| Last run | 一个节点的输入、输出、耗时和错误信息 | 找出哪个节点出了错,以及它收到了什么 |
| Variable Inspector | 已运行节点的输出变量。在这里改值,不会改动原节点的 Last run 记录 | 给某个节点试一个不同的输入。回退图标恢复单个变量,“Reset all”清空缓存 |
| Run History 的 Result 和 Detail | Result 是最终输出或错误,只适用于 Workflow 应用。Detail 是原始输入、最终输出和系统元数据 | 对比一次运行收到的和返回的 |
| Run History 的 Tracing | 哪些节点按什么顺序运行,各用多久,数据在哪里流动 | 在有分支或循环的流程里找出慢的一步 |
发布并保留版本
你的工作副本叫 Current Draft(当前草稿),用户看不到它。点“Publish”>“Publish Update”,草稿就成为 Latest Version(最新版本),也就是用户看到的那一版,同时你会得到一份新的草稿。更早的发布放在 Previous Versions(历史版本)下面。
在历史列表里,你可以给版本命名、添加发布说明、删除旧版本、把某个版本恢复到草稿里,或者用“Export App”导出。当前草稿和最新版本不能删除。恢复会把你现在的草稿整个替换掉,所以没保存的工作要先完成或导出。导出的版本不包含 Secret 类型环境变量的值。版本控制只适用于 Workflow 和 Chatflow 应用。
后面的课会加上知识库和智能体。第 4 课讲怎样把应用发布成网页应用、API 和嵌入组件。
常见错误
- 让某个分支没有 Output 节点。没有 Output 节点的工作流或分支,不会给调用方返回任何数据。
- 给两个 Output 节点取了同一个变量名。后面的会覆盖前面的值。
- 在 Answer 节点里随意排列变量。它会流式输出到第一个还没有值的变量为止,所以 Answer 里的顺序决定了先出现什么。
- 让模型去做按规则排版的事,而 Template 节点做同样的事不消耗 token。
- 为了测一处改动就重跑整个流程,其实改一下缓存的变量,再运行一个节点就够了。
- 手动输入聊天消息的变量。聊天机器人教程写的是
{{sys.query}},User Input 页面列的是userinput.query,所以要从你所用版本显示的列表里选。 - 运行不是你自己写的 Code 节点脚本。沙箱仍然能访问你 Dify 部署里的其他服务。
- 所有 Code 节点都报“network is disabled, please enable it in the configuration”。在自托管的安装里,这是因为
SANDBOX_ENABLE_NETWORK被设成了 false,默认值是 true。
自己试一试
- 把目标平台填成
ohhhhhh,确认 IF 分支返回的是错误信息,而不是帖子。 - 运行一次之后,打开 Variable Inspector,把平台列表改成只有一个平台,再单独运行 Iteration 节点。
- 发布这个流程,改一处提示词再发布一次。打开历史,给两个版本命名,再把第一个版本恢复到草稿里。
下一课
第 3 课给流程加上知识库,让 LLM 节点可以根据你自己的文档回答。它建立在 RAG 的思路上,对检索还不熟的话,先读那一课更好。
自测一下
哪个节点必须作为 Chatflow 的结尾?
查看答案
B. Answer 文档把 Answer 列为 Chatflow 必需的结尾,Output 是 Workflow 可选的结尾。
Workflow 的某个分支没有 Output 节点。调用方从这个分支得到什么?
查看答案
C. 没有任何数据 Output 页面说,没有 Output 节点的工作流或分支,不会给调用方返回任何数据。
你想看 Template 节点遇到另一份列表时的反应,又不想再为模型调用付费。该怎么做?
查看答案
A. 在 Variable Inspector 里修改缓存的变量,再运行这个节点 缓存的输出可以在 Variable Inspector 里修改,下游节点会用修改后的值运行,上游节点不用重跑。
在默认设置下,Code 节点返回了一个 500,000 个字符的字符串。会发生什么?
查看答案
D. 节点失败 Code 页面说,输出超过任何一项限制,节点就会失败,字符串的默认限制是 400,000 个字符。
常见问题
Dify 的 Workflow 和 Chatflow 有什么区别?
Workflow 一次拿到全部输入,返回 Output 节点里的内容,适合 API 调用或定时任务。Chatflow 回答对话里的每条消息,还能在多轮之间保存对话变量,这一点只有 Chatflow 支持。
怎样调试 Dify 工作流?
打开出错节点的 Last run,对比它收到的内容和你预期的内容。在 Variable Inspector 里修正上游的值,只重跑这一个节点。如果问题是某一步太慢,就看 Run History 里的 Tracing。
在 Dify 工作流里能用 Python 吗?
可以,用 Code 节点。Python 自带 json、math、datetime 和 re 这类标准库,文档还演示了导入 numpy 和 pandas。JavaScript 的用法相同。
能从我自己的代码里调用 Dify 工作流吗?
可以。从 User Input 开始的工作流可以发布成网页应用,也可以通过 API 对外提供,它的 Output 变量名会成为 API 响应里 outputs 对象的键。API 密钥在第 4 课讲。
资料来源
- Dify Docs (GitHub): Workflow & Chatflow https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/build/workflow-chatflow.mdx
- Dify Docs (GitHub): 30-Minute Quick Start https://github.com/langgenius/dify-docs/blob/main/en/quick-start.mdx
- Dify Docs (GitHub): User Input node https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/user-input.mdx
- Dify Docs (GitHub): LLM node https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/llm.mdx
- Dify Docs (GitHub): Knowledge Retrieval node https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/knowledge-retrieval.mdx
- Dify Docs (GitHub): If-Else node https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/ifelse.mdx
- Dify Docs (GitHub): Code node https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/code.mdx
- Dify Docs (GitHub): HTTP Request node https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/http-request.mdx
- Dify Docs (GitHub): Answer node https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/answer.mdx
- Dify Docs (GitHub): Output node https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/output.mdx
- Dify Docs (GitHub): Single Node https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/debug/step-run.mdx
- Dify Docs (GitHub): Variable Inspector https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/debug/variable-inspect.mdx
- Dify Docs (GitHub): Run History https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/debug/history-and-logs.mdx
- Dify Docs (GitHub): Version Control https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/build/version-control.mdx
