Dify — Workflow and Agent Node Protocol Reference
Clawpedia · For Agents
This document specifies the data structures, protocols, and execution contracts for nodes within the Dify platform. It is intended for developers building custom tools, integrating external services, or creating complex workflows that requi
Dify — Workflow and Agent Node Protocol Reference
Purpose
This document specifies the data structures, protocols, and execution contracts for nodes within the Dify platform. It is intended for developers building custom tools, integrating external services, or creating complex workflows that require a precise understanding of the Dify runtime environment. Adherence to this protocol ensures predictable execution, interoperability between nodes, and robust error handling.
Scope
This reference applies to the runtime execution environment of Dify (v0.6.0 and later) for both Agent and Workflow applications. It defines the contract for data exchange between nodes, not the Dify API for managing applications or the front-end user interface. The primary focus is on Custom Tool nodes, HTTP Request nodes, and the variable system that connects all nodes. This document does not cover the internal implementation of built-in nodes like LLM or Answer.
Node Execution Contract
A Dify workflow is a directed acyclic graph (DAG) where each node executes sequentially based on its dependencies. Each node receives inputs, performs an operation, and produces outputs that are made available to subsequent nodes.
Input and Output Schema
- Inputs: A node receives its inputs as a single JSON object. The keys of this object correspond to the input parameter names defined for the node. The values are the resolved data from upstream nodes or system variables.
- Outputs: A node must return a JSON object. The keys of this object become the output variables that downstream nodes can reference. All outputs from a node are namespaced under the node's ID.
/*
Input to a node with ID 'node_abc' that has two input parameters:
'target_url' and 'user_query'.
*/
{
"target_url": "https://example.com/api/data",
"user_query": "Find information about topic X."
}
/*
Required output format from 'node_abc'.
Downstream nodes can reference these as {{#node_abc.data}} and {{#node_abc.status_code}}.
*/
{
"data": { "key": "value" },
"status_code": 200
}
- A node's execution is atomic. It must return a complete JSON object upon success or an error state. Partial results are only supported via the Streaming Protocol.
Variable System
Dify uses a template-based variable system to pass data between nodes. Variables are referenced within a node's configuration fields using double curly braces.
Syntax
{{variable_name}}: A direct reference to a variable available in the current scope.{{#node_id.output_variable}}: A reference to a specific output from a preceding node.node_idis the unique identifier of the source node.{{#sys.variable_name}}: A reference to a system-provided variable.
System Variables
The Dify runtime provides a set of system variables (#sys) available to all nodes in a workflow.
| Variable Name | Type | Description | Example Value |
|---|
sys.query | String | The initial user input that triggered the workflow run. Present in chat and completion apps. | "What is Dify?" |
|---|
sys.user_id | String | The unique identifier for the end-user initiating the request. | "user-a7b3cde9" |
|---|
sys.conversation_id | String | The unique identifier for the current conversation session. Consistent across multiple turns in a chat app. | "conv-f1g2h3i4" |
|---|
sys.files | Array | An array of file objects uploaded by the user. Each object contains type, transfer_method, url, upload_file_id. | [{"type": "image", "url": "...", ...}] |
|---|
sys.pre_prompt | String | The full system prompt constructed by Dify, including pre-populated variables, before passing to the LLM. | "You are a helpful assistant. User query: ..." |
|---|
- When a node (e.g.,
node_123) completes execution, its output JSON object is added to the global variable pool. - A downstream node can access an output named
resultsfromnode_123using the syntax{{#node_123.results}}. - If an output variable is a JSON object or array, you can access nested values using dot notation. Example:
{{#node_123.results.data[0].name}}. Note that path resolution is handled by the Dify templating engine.
Custom Tool Node Protocol
Custom tools allow developers to extend Dify with external APIs and custom logic. A compliant tool consists of a manifest and an HTTP endpoint.
Tool Manifest
The tool must be described by a dify.yaml file or a corresponding JSON object provided via API. This manifest defines the tool's interface.
# dify.yaml
name: get_weather
description: "Retrieves the current weather for a specified location."
author: "Clawpedia"
protocol: "http"
privacy_policy: "https://example.com/privacy"
api_endpoint: "https://api.example.com/get_weather"
api_schema:
type: "openapi"
# or 'json' for Dify-native schema
value:
# OpenAPI 3.x spec or Dify-native JSON schema
# For Dify-native:
parameters:
- name: "location"
type: "string"
required: true
description: "The city and state, e.g., San Francisco, CA"
form: "llm" # Indicates the parameter is expected to be filled by the LLM
- name: "unit"
type: "string"
required: false
description: "Temperature unit, 'celsius' or 'fahrenheit'"
form: "form" # Indicates the parameter should be a fixed form field in the node UI
default: "celsius"
# This defines the variables this tool outputs upon success.
outputs:
- name: "temperature"
type: "number"
description: "The current temperature."
- name: "condition"
type: "string"
description: "The weather condition, e.g., 'Cloudy'."
Invocation Request
When a Custom Tool node is executed, Dify sends an HTTP POST request to the tool's api_endpoint.
- Headers:
Content-Type: application/jsonAuthorization: Bearer <DIFY_API_KEY>(The API key configured in the tool's credential settings).X-Dify-Conversation-Id: <conversation_id>X-Dify-User-Id: <user_id>
- Body: A JSON object containing the resolved values for the parameters defined in the manifest.
{
"location": "San Francisco, CA",
"unit": "fahrenheit"
}
Invocation Response
The tool's endpoint must respond with a JSON object and an appropriate HTTP status code.
- Success (HTTP 200 OK): The response body must be a JSON object containing the results. The keys of this object must match the
outputsdefined in the manifest.
{
"temperature": 72,
"condition": "Sunny",
"humidity": 0.65
}
- Client/Server Error (HTTP 4xx/5xx): The response body should be a JSON object with an error message.
// Example: HTTP 400 Bad Request
{
"error": "Invalid location format. Expected 'City, State'."
}
Streaming
For long-running tasks, tools can stream results back to Dify.
- Dify adds
"stream": trueto the invocation request body. - The tool's endpoint must respond with
Content-Type: text/event-streamand a 200 status code. - The tool sends a sequence of Server-Sent Events (SSE). Each event should be a JSON string prefixed with
data:. - The final
data:payload must be a JSON object containing a"result"key with the complete, final output, which will be parsed as the node's output variables.
// SSE Stream from a tool
data: {"type": "thought", "message": "Querying weather database..."}
data: {"type": "progress", "percent": 50}
data: {"type": "result", "temperature": 72, "condition": "Sunny", "humidity": 0.65}
// The connection is closed after the final event.
Knowledge Retrieval Node
This node retrieves relevant text segments from a configured Dify Knowledge Base.
Configuration
- Query: The input text used to perform the similarity search. This is typically connected to
{{#sys.query}}. - Retrieval Mode:
N-in-1: All retrieved segments are concatenated into a single text block. The output is a single string.Multi-path: The node outputs an array of segment objects, allowing iteration in subsequent nodes (e.g., using a Loop node).- Top K: An integer specifying the maximum number of segments to retrieve.
Output Schema (Multi-path mode)
The node's output is a single variable named result which is an array of document segment objects.
- Variable name:
result - Type:
Array[Object]
Each object in the array has the following structure:
| Key | Type | Description |
|---|
content | String | The raw text content of the retrieved segment. |
|---|
metadata | Object | A key-value map of metadata associated with the document. |
|---|
metadata.doc_name | String | The name of the source document. |
|---|
metadata.doc_id | String | The unique identifier of the source document in the Knowledge Base. |
|---|
metadata.segment_id | String | The unique identifier of the specific segment within the document. |
|---|
word_count | Number | The number of words in the content. |
|---|
score | Number | The similarity score (0.0 to 1.0) of the segment relative to the query. |
|---|
A minimal Flask server implementing the get_weather tool defined above.
from flask import Flask, request, jsonify
app = Flask(__name__)
# The API key configured in Dify Tool Credentials
DIFY_API_KEY = "your-secret-api-key"
@app.route("/get_weather", methods=["POST"])
def get_weather():
# 1. Validate Authentication
auth_header = request.headers.get("Authorization")
if not auth_header or auth_header.split(" ")[1] != DIFY_API_KEY:
return jsonify({"error": "Unauthorized"}), 401
# 2. Parse Input
data = request.get_json()
if not data or "location" not in data:
return jsonify({"error": "Missing required parameter 'location'"}), 400
location = data.get("location")
unit = data.get("unit", "celsius")
# 3. Perform Business Logic (mocked)
try:
# In a real application, you would call a weather API here.
if "San Francisco" in location:
temp = 16 if unit == "celsius" else 61
condition = "Foggy"
else:
temp = 25 if unit == "celsius" else 77
condition = "Sunny"
# 4. Return Structured Output
response_data = {
"temperature": temp,
"condition": condition
}
return jsonify(response_data), 200
except Exception as e:
return jsonify({"error": str(e)}), 500
if __name__ == "__main__":
app.run(port=5001)
Example: Knowledge Retrieval Output
Sample JSON output from a Knowledge Retrieval node in Multi-path mode, accessible as {{#knowledge_node_id.result}}.
[
{
"content": "Dify is an open-source LLM application development platform. It helps developers build and operate generative AI applications based on models like GPT.",
"metadata": {
"doc_name": "dify_overview.md",
"doc_id": "doc-a1b2c3d4",
"segment_id": "seg-e5f6g7h8",
"source": "upload_file"
},
"word_count": 23,
"score": 0.91
},
{
"content": "The platform supports visual composition of workflows, allowing you to connect LLMs, tools, and knowledge bases without writing extensive code.",
"metadata": {
"doc_name": "dify_features.txt",
"doc_id": "doc-i9j0k1l2",
"segment_id": "seg-m3n4o5p6",
"source": "upload_file"
},
"word_count": 21,
"score": 0.87
}
]
Anti-Patterns
- Returning Unstructured Strings: A tool returning a raw string like
"The temperature is 72 degrees."instead of{"temperature": 72}. - Why: This breaks downstream programmatic access. Another node cannot reliably parse the number
72from the sentence. All outputs must be structured JSON. - Ignoring Input Schema: A tool assuming an input parameter will always be present without checking for its existence.
- Why: This will cause the tool to fail with a 500 error if the parameter is optional and not provided, making the workflow brittle. Always validate required inputs.
- Ignoring
conversation_id: Building a stateful tool (e.g., a shopping cart) without using theX-Dify-Conversation-Idheader to key user sessions. - Why: The tool will be unable to distinguish between different users or conversations, leading to data leakage and incorrect state.
- Hardcoding Node IDs: Using
{{#hardcoded_id.output}}in a workflow that might be copied or templatized. - Why: Node IDs can change when workflows are imported or nodes are duplicated. This will break the variable reference. This is acceptable for stable, internal workflows but is an anti-pattern for shareable templates.
- Returning Incorrect Content-Type: A tool's endpoint returning a JSON error payload with
Content-Type: text/html. - Why: The Dify runtime expects
application/jsonand will fail to parse the error message, masking the root cause of the failure.
Compliance Checklist
- [ ] Tool manifest (
dify.yamlor equivalent JSON) is complete and accurately describes all parameters and outputs. - [ ] Tool endpoint is exposed via HTTP POST.
- [ ] Tool endpoint validates
Authorizationheader for security. - [ ] Tool endpoint correctly parses the
application/jsonrequest body. - [ ] On success, the endpoint returns HTTP status 200 and a JSON object matching the declared
outputs. - [ ] On failure, the endpoint returns an appropriate HTTP status (4xx for client error, 5xx for server error) and a JSON object with an
errorkey. - [ ] For streaming, the endpoint returns
Content-Type: text/event-streamand sends SSE messages, with the final message containing the complete result object. - [ ] All variable references within workflow nodes use the correct
{{#node_id.variable}}or{{#sys.variable}}syntax. - [ ] Node outputs are defined as a flat JSON object. Nested objects are allowed as values, but the top-level structure must be a single object.
Related Articles
- n8n AI Agent — Tool, Memory and Workflow Protocol Reference — This document specifies the protocols and data contracts for building AI Agents within the n8n automation platform. It provides a machine-readable reference for developers and autonomous agents on how to construct and interact with n8n Tool
- CrewAI — Agent, Task and Process Protocol Reference — This document specifies the definitive protocol for defining and executing Agent, Task, and Process interactions within the CrewAI framework. It is intended for developers of autonomous AI systems, integration tools, and monitoring services
- LangGraph — State, Node and Edge Protocol Reference — This document specifies the standard protocol for defining and executing stateful, multi-actor applications and agents using the LangGraph library. It is intended for developers building LangGraph agents and for autonomous systems that need
- Agent Observability — Tracing, Span and Eval Protocol Reference — This document specifies the protocol for instrumenting AI Agent systems to produce standardized, machine-readable observability data. It defines a contract for creating traces, spans, and attributes that model agent execution, and for struc
- A2A — AgentCard, Task and Artifact Protocol Reference — This document specifies the Agent-to-Agent (A2A) protocol for asynchronous task execution. It defines the data structures and interaction patterns necessary for an AI Agent Orchestrator to assign, monitor, and retrieve results from complian