Mindket

Dify workflow tutorial: build, run and debug a workflow

A black banner titled "Dify" over the line "Build AI apps and workflows without code".

A Dify Workflow is a chain of nodes that runs once, from an input to a result. You build it on a canvas by dragging nodes, connecting them and filling in their settings, then test it, read what each node did and publish it. This lesson builds the docs' own content generator, which turns a draft into one post per platform.

In this lesson

  • Pick Workflow for a one-shot job and Chatflow for a chat, because their first and last nodes differ.
  • Give rule-based steps to an IF/ELSE, Code or Template node and keep the model for steps that need judgment.
  • Run a single node and edit its cached inputs before you rerun the whole flow.
  • Publish only after a Test Run succeeds, and name the versions you may want back.
All courses
On this page
  1. Workflow or Chatflow
  2. The nodes you will use most
  3. Build the content generator
  4. Format the result and run it
  5. Code and HTTP Request nodes
  6. Run and debug a workflow
  7. Publish and keep versions
  8. Common mistakes
  9. Try it yourself
  10. Next
  11. Check yourself
  12. Frequently asked questions
  13. Sources

Workflow or Chatflow

Both app types share one canvas and one set of nodes. The docs describe most of the work as drag, connect and configure, with code only where your logic calls for it. The difference is how people use the result.

A Workflow takes an input, runs the whole flow and returns a result, so it suits report generation, data processing and batch jobs. A Chatflow puts a chat window in front: each message runs the flow before a reply goes out, so it suits assistants and guided Q&A.

They start and end on different nodes. A Workflow begins at User Input or at a Trigger, which starts it on a schedule, from a webhook or from an integration event. A Chatflow always begins at User Input, so it has no Triggers. A Chatflow must end at an Answer node. A Workflow may end at an Output node, the node that was named End before. The docs call it optional, but a branch with no Output node returns nothing to the caller.

The nodes you will use most

Every field you add to the User Input node becomes a variable that later nodes can use. In any text box, type { or / to pick a variable, and the editor writes the {{variable_name}} reference for you.

From the node pages of the Dify docs: User Input, LLM, Knowledge Retrieval, If-Else, Code, HTTP Request and the Quick Start.
NodeJobWhat the docs say
User InputCollects what a person entersOne per canvas. Short Text takes up to 256 characters. Other field types are paragraph, select, number, checkbox, JSON and files
LLMCalls a model with your promptTemperature runs from 0, deterministic, to 1, creative. Structured output returns named fields the next node can read
Knowledge RetrievalSearches your knowledge basesReturns a result list. Set the LLM node's Context to it. Lesson 3 covers this
IF/ELSESends the run down one branchIF, ELIF and ELSE paths. Conditions combine with AND or OR
CodeRuns Python or JavaScriptThe function must return a dictionary holding the declared outputs
HTTP RequestCalls an outside APIGET, HEAD, POST, PUT, PATCH and DELETE. Authentication, body and timeouts are set per node
TemplateFormats text with Jinja2Rule-based formatting at zero token cost
Output or AnswerReturns the resultOutput in a Workflow, Answer in a Chatflow

Build the content generator

The docs' 30-Minute Quick Start builds a workflow that takes a draft, optional files, a voice and tone, target platforms and a language, then returns one post per platform. It runs on Dify Cloud, and the page says to follow the same steps on a self-hosted instance. The steps below condense it, in its order. A Parameter Extractor is a node that asks a model to pull structured values out of free text, and here it turns whatever a person types into a clean list of platforms.

# 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. In Studio, choose Create from Blank > Workflow, name it Multi-platform content generator and click Create.
  2. In the User Input node add five fields. The field draft is a required Paragraph (max length 2048), and user_file is a File list for documents and images. The field voice_and_tone is a Paragraph, and platform is a required Short Text. The last one, language, is a required Select with English, 日本語 and 简体中文.
  3. Add a Parameter Extractor. Set Input Variable to User Input/platform, add an extract parameter named platform of type Array[String], mark it required and paste the instruction above into the Instruction field.
  4. Add an IF/ELSE node with the condition Parameter Extractor/platform contains No platforms identified. Please enter a valid platform name. Put an Output node on the IF branch that returns Parameter Extractor/platform. A bad platform name now ends the run early, before tokens go on useless content.
  5. On the ELSE branch add two List Operator nodes in parallel. Both take User Input/user_file as input. One filters type in Image and the other type in Doc.
  6. After the document branch add a Doc Extractor, which turns PDF and DOCX files into plain text, because the tutorial's model cannot read them directly.
  7. Add an LLM node named Integrate Info. Turn on Vision, set the image branch as the vision variable and ask it for a structured summary of the draft, the document text and the images.
  8. Add an Iteration node. Inside it, an LLM node Identify Style writes guidelines for Current Iteration/item, then an LLM node Create Content writes the post with structured output holding platform_name and post_content.
  9. On the Iteration node set the input to Parameter Extractor/platform and the output to Create Content/structured_output. Turn on Parallel Mode and set the maximum parallelism to 10, so the platforms are written side by side.

Format the result and run it

The Iteration node returns a raw list of platform and post pairs. A Template node turns that list into readable text with Jinja2, a templating language. A model can format output too, but the quick start warns that its results can be inconsistent, while a rule-based template costs no tokens. This is the quick start's template, without its phone emoji.

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

{% endfor %}
  1. Add a Template node after the Iteration node. Set Iteration/output as its input variable, name it output and paste the template above.
  2. Add an Output node and set Template/output as its output variable.
  3. Make sure the Checklist is clear and compare your canvas with the quick start's diagram.
  4. Click Test Run at the top right, fill in the fields and click Start Run. The docs suggest this draft: "We just launched a new AI writing assistant that helps teams create content 10x faster." Add the voice "Friendly and enthusiastic, but professional", the platforms "Twitter and LinkedIn" and the language English.

Code and HTTP Request nodes

A Code node covers what no preset node does. You declare input variables and output variables, and the function has to return a dictionary holding the declared outputs, like the main function in lesson 1. An output over any limit below fails the node.

Both Code and HTTP Request have Retry on failure: a failed run tries again up to 10 times, and the interval can be set up to 5000 milliseconds. Their Error Handling option defines a fallback path, so the rest of the flow can continue when one of them fails.

The HTTP Request node sets the method, URL, headers, query parameters, body and authentication in one panel. Authentication is No Auth or API Key, and API Key has Basic, Bearer and Custom subtypes. The body is JSON, Form Data, Binary or Raw Text. The response comes back as separate variables: the body, the status code, the headers, any files and the size. A Secret-type environment variable is masked in the run logs and in this node's request log.

Default limits on a Code node output

400,000

characters in one string

Source: Dify Docs (GitHub): Code node (read November 6, 2026)

5 levels

of object nesting

Source: Dify Docs (GitHub): Code node (read November 6, 2026)

30

items in an array[string] or array[object]

Source: Dify Docs (GitHub): Code node (read November 6, 2026)

1,000

items in an array[number]

Source: Dify Docs (GitHub): Code node (read November 6, 2026)

Run and debug a workflow

You can test one node alone: select it, give it test input in its panel and click Run. The docs say Answer and End nodes don't support single node testing. End is the Output node's old name and the page does not mention the new one, so check an Output node with a whole-flow run. Whole-flow runs and single-node runs both leave records, and four tools read them.

The Variable Inspector holds the data each node produced. When you run nodes one at a time, their outputs are cached there, and you can edit most values and run a downstream node again with your edit, without rerunning anything upstream. The quick start opens the same list through View cached variables at the bottom of the canvas.

From the docs' Single Node, Variable Inspector and Run History pages.
ToolWhat it showsUse it to
Last runA node's inputs, outputs, timing and any error messageFind which node failed and what it received
Variable InspectorThe output variables of nodes that ran. Editing a value leaves the original node's Last run unchangedTry a different input on one node. The revert icon restores one variable and Reset all clears the cache
Run History: Result and DetailResult is the final output or the error, for Workflow apps only. Detail is the original input, the final output and system metadataCompare what a run received with what it returned
Run History: TracingWhich nodes ran, in what order, how long each took and where data flowedFind a slow step in a flow with branches or loops

Publish and keep versions

Your working copy is the Current Draft, and users never see it. Click Publish > Publish Update and the draft becomes the Latest Version, the one users see, and you get a fresh draft. Older publishes sit under Previous Versions.

From the history list you can name a version, add release notes, delete old versions, restore one into your draft or export it with Export App. You can't delete the Current Draft or the Latest Version. Restoring replaces your current draft completely, so finish or export unsaved work first. A version export never includes the values of Secret-type environment variables. Version control exists for Workflow and Chatflow apps only.

The next lessons add a knowledge base and an agent. Lesson 4 covers publishing as a web app, an API and an embed.

Common mistakes

  • Leaving a branch without an Output node. A workflow or branch with none returns no data to the caller.
  • Giving two Output nodes the same variable name. The later one overwrites the earlier value.
  • Ordering variables carelessly in an Answer node. It streams text up to the first variable that has no value yet, so the order inside the Answer decides what appears first.
  • Asking a model for rule-based formatting that a Template node does at no token cost.
  • Rerunning the whole flow to test one change, when editing the cached variable and running one node is enough.
  • Typing the chat message variable by hand. The chatbot tutorial writes {{sys.query}} while the User Input page lists userinput.query, so pick the variable from the list your version shows.
  • Running Code node scripts you did not write. The sandbox can still reach other services inside your Dify deployment.
  • Seeing every Code node fail with "network is disabled, please enable it in the configuration". On a self-hosted install, SANDBOX_ENABLE_NETWORK is set to false. The default is true.

Try it yourself

  • Enter ohhhhhh as the Target Platform and check that the IF branch returns the error message instead of posts.
  • After a run, open the Variable Inspector, edit the platform list to a single platform and run the Iteration node alone.
  • Publish the flow, change one prompt and publish again. Open the history, name both versions and restore the first into your draft.

Next

Lesson 3 adds a knowledge base to a flow, so an LLM node can answer from your own documents. It rests on the idea behind RAG, and that lesson is worth reading first if retrieval is new to you.

Check yourself

  1. Which node must end a Chatflow?

    Show answer

    B. Answer The docs list Answer as the required end of a Chatflow. Output is the optional end of a Workflow.

  2. One branch of a Workflow has no Output node. What does the caller get from that branch?

    Show answer

    C. No data The Output page says a workflow or branch without an Output node returns no data to the caller.

  3. You want to see how the Template node reacts to a different list without paying for the model calls again. What do you do?

    Show answer

    A. Edit the cached variable in the Variable Inspector and run that node Cached outputs can be edited in the Variable Inspector, and a downstream node then runs with the edited value without rerunning upstream nodes.

  4. A Code node returns a string of 500,000 characters with the default settings. What happens?

    Show answer

    D. The node fails The Code page says an output that exceeds a limit fails the node, and the default string limit is 400,000 characters.

Frequently asked questions

What is the difference between a Dify workflow and a chatflow?

A Workflow gets its inputs once and returns whatever its Output nodes hold, which suits an API call or a scheduled job. A Chatflow answers each message of a conversation and can keep conversation variables between turns, which only Chatflows support.

How do I debug a Dify workflow?

Open the failing node's Last run and compare what it received with what you expected. Fix the upstream value in the Variable Inspector, run just that node again, and read Tracing in Run History if the trouble is a slow step.

Can I use Python in a Dify workflow?

Yes, with a Code node. Python includes standard libraries such as json, math, datetime and re, and the docs also show importing numpy and pandas. JavaScript works the same way.

Can I call a Dify workflow from my own code?

Yes. A workflow that starts from User Input can be published as a web app or exposed through an API. The names of its Output variables become the keys of the outputs object in the API response. Lesson 4 covers the API key.

Sources

  1. Dify Docs (GitHub): Workflow & Chatflow (read November 6, 2026)https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/build/workflow-chatflow.mdx
  2. Dify Docs (GitHub): 30-Minute Quick Start (read November 6, 2026)https://github.com/langgenius/dify-docs/blob/main/en/quick-start.mdx
  3. Dify Docs (GitHub): User Input node (read November 6, 2026)https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/user-input.mdx
  4. Dify Docs (GitHub): LLM node (read November 6, 2026)https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/llm.mdx
  5. Dify Docs (GitHub): Knowledge Retrieval node (read November 6, 2026)https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/knowledge-retrieval.mdx
  6. Dify Docs (GitHub): If-Else node (read November 6, 2026)https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/ifelse.mdx
  7. Dify Docs (GitHub): Code node (read November 6, 2026)https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/code.mdx
  8. Dify Docs (GitHub): HTTP Request node (read November 6, 2026)https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/http-request.mdx
  9. Dify Docs (GitHub): Answer node (read November 6, 2026)https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/answer.mdx
  10. Dify Docs (GitHub): Output node (read November 6, 2026)https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/nodes/output.mdx
  11. Dify Docs (GitHub): Single Node (read November 6, 2026)https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/debug/step-run.mdx
  12. Dify Docs (GitHub): Variable Inspector (read November 6, 2026)https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/debug/variable-inspect.mdx
  13. Dify Docs (GitHub): Run History (read November 6, 2026)https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/debug/history-and-logs.mdx
  14. Dify Docs (GitHub): Version Control (read November 6, 2026)https://github.com/langgenius/dify-docs/blob/main/en/self-host/use-dify/build/version-control.mdx

Share this lesson

Find more open-source projects

Mindket's Kits collect open-source projects with plain setup notes. Dify is one of them.

Browse kits

This lesson as Markdown · Dify tutorial: build AI apps and workflows without code · All courses