# Dify 工作流教程：搭建、运行和调试一个工作流

> Dify 的 Workflow（工作流）是一串节点，从一个输入运行一次，得到一个结果。你在画布上拖动节点、把它们连起来、填好设置，然后测试，查看每个节点做了什么，再发布。这一课搭的是文档自己的内容生成器，它把一份草稿变成每个平台各一条帖子。

Mindket 编辑部 · 发布于 2026-11-06 · 更新于 2026-11-06 · https://mindket.com/cn/learn/dify/dify-workflow

## 要点

- 一次性的任务选 Workflow，聊天选 Chatflow，因为两者的第一个和最后一个节点不同。
- 有固定规则的步骤交给 IF/ELSE、Code 或 Template 节点，模型只负责需要判断的步骤。
- 先单独运行一个节点，改它缓存的输入，再重跑整个流程。
- Test Run 成功之后再发布，可能要回退的版本先起好名字。

## 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 分钟快速入门](https://github.com/langgenius/dify-docs/blob/main/en/quick-start.mdx)搭了一个工作流：它接收草稿、可选的文件、语气和风格、目标平台和语言，然后为每个平台返回一条帖子。它在 Dify Cloud 上运行，页面说在自托管的实例上照同样的步骤做就行。下面的步骤按它的顺序做了精简。Parameter Extractor（参数提取器）是让模型从自由文本里提取结构化数值的节点，这里它把用户随手输入的内容变成一份干净的平台列表。

````markdown
# 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.]
````

1. 在 Studio 里选“Create from Blank”>“Workflow”，命名为 `Multi-platform content generator`，点“Create”。
2. 在 User Input 节点里添加五个字段。`draft` 是必填的段落，最大长度 2048。`user_file` 是文件列表，收文档和图片。`voice_and_tone` 是段落，`platform` 是必填的短文本。最后的 `language` 是必填的下拉选择，选项是 English、日本語 和 简体中文。
3. 添加一个 Parameter Extractor。把“Input Variable”设为 `User Input/platform`，添加一个名为 `platform`、类型为 Array[String] 的提取参数，设为必填，再把上面的指令粘贴到“Instruction”里。
4. 添加一个 IF/ELSE 节点，条件是 `Parameter Extractor/platform` contains `No platforms identified. Please enter a valid platform name.`。在 IF 分支上放一个 Output 节点，返回 `Parameter Extractor/platform`。这样平台名无效时，运行会提前结束，不会把 token 花在没用的内容上。
5. 在 ELSE 分支上并排添加两个 List Operator 节点，输入都是 `User Input/user_file`。一个筛选类型为 Image，另一个筛选类型为 Doc。
6. 文档这一支后面加一个 Doc Extractor，把 PDF 和 DOCX 文件转成纯文本，因为教程里的模型不能直接读取它们。
7. 添加一个名为 `Integrate Info` 的 LLM 节点。打开 Vision，把图片这一支设为视觉变量，让它把草稿、文档文本和图片整理成一份结构化的摘要。
8. 添加一个 Iteration 节点。里面先放一个 LLM 节点 `Identify Style`，为 `Current Iteration/item` 写出平台风格指南，再放一个 LLM 节点 `Create Content`，用结构化输出写帖子，输出包含 `platform_name` 和 `post_content`。
9. 在 Iteration 节点上，把输入设为 `Parameter Extractor/platform`，输出设为 `Create Content/structured_output`。打开 Parallel Mode，最大并行数设为 10，让各个平台的帖子同时生成。

## 排版结果并运行

Iteration 节点返回的是一份原始的列表，里面是一对对平台和帖子。Template 节点用 Jinja2（一种模板语言）把这份列表变成易读的文本。快速入门提到，模型也能排版，但每次的结果不一样，而按规则写的模板不消耗 token。下面是快速入门里的模板，只去掉了开头的手机表情符号。

````jinja
{% for item in output %}
# {{ item.platform_name }}
{{ item.post_content }}

{% endfor %}
````

1. 在 Iteration 节点后面添加一个 Template 节点。把 `Iteration/output` 设为它的输入变量，命名为 `output`，再粘贴上面的模板。
2. 添加一个 Output 节点，把 `Template/output` 设为它的输出变量。
3. 确认 Checklist 已清空，再把你的画布和快速入门里的示意图对照一遍。
4. 点右上角的“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 类型的环境变量，在运行日志和这个节点的请求日志里会被遮蔽。

**Code 节点输出的默认限制**

- **400,000** 个字符，一个字符串 (来源：[Dify 文档（GitHub）：Code 节点](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/code.mdx), 2026-11-06 查阅)
- **5 层** 对象嵌套 (来源：[Dify 文档（GitHub）：Code 节点](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/code.mdx), 2026-11-06 查阅)
- **30** 项，array[string] 或 array[object] (来源：[Dify 文档（GitHub）：Code 节点](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/code.mdx), 2026-11-06 查阅)
- **1,000** 项，array[number] (来源：[Dify 文档（GitHub）：Code 节点](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/code.mdx), 2026-11-06 查阅)

## 运行和调试工作流

你可以单独测试一个节点：选中它，在它的面板里给出测试输入，点“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 课](https://mindket.com/cn/learn/dify/dify-agent)讲怎样把应用发布成网页应用、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 课](https://mindket.com/cn/learn/dify/dify-knowledge-base)给流程加上知识库，让 LLM 节点可以根据你自己的文档回答。它建立在 [RAG](https://mindket.com/cn/learn/rag/rag-tutorial) 的思路上，对检索还不熟的话，先读那一课更好。

## 自测一下

1. 哪个节点必须作为 Chatflow 的结尾？

   A. Output
   B. Answer
   C. Code
   D. Template

   答案：B。 文档把 Answer 列为 Chatflow 必需的结尾，Output 是 Workflow 可选的结尾。

2. Workflow 的某个分支没有 Output 节点。调用方从这个分支得到什么？

   A. 一个空字符串
   B. 最后一个节点的输出
   C. 没有任何数据
   D. 发布时报错

   答案：C。 Output 页面说，没有 Output 节点的工作流或分支，不会给调用方返回任何数据。

3. 你想看 Template 节点遇到另一份列表时的反应，又不想再为模型调用付费。该怎么做？

   A. 在 Variable Inspector 里修改缓存的变量，再运行这个节点
   B. 把一个旧版本恢复到草稿里
   C. 打开 Parallel Mode
   D. 重新发布这个流程

   答案：A。 缓存的输出可以在 Variable Inspector 里修改，下游节点会用修改后的值运行，上游节点不用重跑。

4. 在默认设置下，Code 节点返回了一个 500,000 个字符的字符串。会发生什么？

   A. 它被截成 400,000 个字符
   B. 它变成一个文件变量
   C. Iteration 节点把它拆开
   D. 节点失败

   答案：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 文档（GitHub）：Workflow 与 Chatflow](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/build/workflow-chatflow.mdx) (2026-11-06 查阅)
- [Dify 文档（GitHub）：30 分钟快速入门](https://github.com/langgenius/dify-docs/blob/main/en/quick-start.mdx) (2026-11-06 查阅)
- [Dify 文档（GitHub）：User Input 节点](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/user-input.mdx) (2026-11-06 查阅)
- [Dify 文档（GitHub）：LLM 节点](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/llm.mdx) (2026-11-06 查阅)
- [Dify 文档（GitHub）：Knowledge Retrieval 节点](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/knowledge-retrieval.mdx) (2026-11-06 查阅)
- [Dify 文档（GitHub）：If-Else 节点](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/ifelse.mdx) (2026-11-06 查阅)
- [Dify 文档（GitHub）：Code 节点](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/code.mdx) (2026-11-06 查阅)
- [Dify 文档（GitHub）：HTTP Request 节点](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/http-request.mdx) (2026-11-06 查阅)
- [Dify 文档（GitHub）：Answer 节点](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/answer.mdx) (2026-11-06 查阅)
- [Dify 文档（GitHub）：Output 节点](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/output.mdx) (2026-11-06 查阅)
- [Dify 文档（GitHub）：单节点测试](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/debug/step-run.mdx) (2026-11-06 查阅)
- [Dify 文档（GitHub）：变量检查器](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/debug/variable-inspect.mdx) (2026-11-06 查阅)
- [Dify 文档（GitHub）：运行历史](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/debug/history-and-logs.mdx) (2026-11-06 查阅)
- [Dify 文档（GitHub）：版本控制](https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/build/version-control.mdx) (2026-11-06 查阅)

[浏览 Kits](https://mindket.com/cn/kits)
