Importing a Dify app¶
Studio converts a Dify app export — the YAML file Dify's Export DSL writes — into a Kneo
version: v1 spec plus gap cards, the same way it converts an n8n workflow. What converts, what is
carded and why is below; the quickstart walks the rest of the pipeline — review,
govern and hand-off — which is the same for every source.
Dify import is new in 0.9.0. 0.8.0 and earlier answer a Dify import with
501 not_implemented.
Import it¶
- In Dify, open the app and choose Export DSL. Dify exports the app's draft, so unpublished edits are what Studio converts. Keep the secret values out of the export when Dify asks: Studio never carries a credential, and a literal one only adds a blocking card.
- In Studio, choose Import, pick Dify as the source, and choose the
.ymlor.yamlfile. Over the API it isPOST /api/projects/{project}/import/dify, with the same body and alias rules as an n8n import (the examples show both, and carry a Dify app to try first). - Read the gap cards. Blocking ones must be fixed in the draft and attested before the spec can be exported; manual ones need an acknowledgement; info ones only tell you.
Which exports Studio reads¶
Studio is verified against Dify 1.17.1, whose DSL is version 0.7.0. It converts every 0.x
DSL version up to 0.7.0, including those below 0.1.0 — the versions Dify itself imports without
asking for confirmation — and reads an export with no version as 0.1.0 (absent, null or
empty alike), as Dify does. A newer version (a newer 0.x, or another major such as 1.0.0 or
v1), a version that is not a string, and one Studio cannot parse are refused, with a message
naming which: Studio does not guess at a format it has not verified.
The support matrix¶
| App mode | Studio | What it becomes |
|---|---|---|
workflow |
converted | the graph: one Kneo step per node Kneo can run, the rest carded |
advanced-chat |
converted | the graph, as for workflow; each LLM's conversation memory is carded |
chat |
converted | one Kneo agent: the model and the prompt |
agent-chat |
converted | one Kneo agent: the model and the prompt. Its tools and its iteration bound are carded for you to set: a Dify tool has no backing Kneo can call, and the bound is not carried. An app with no strategy, or a router strategy, runs no agent in Dify and is carded, blocking |
completion |
converted | one Kneo agent: the model and the prompt |
agent |
carded | nothing: its prompt and tools live in the agent package the export carries under agent_packages, which Studio does not read |
Inside a graph, a node becomes:
| Dify node | In Kneo |
|---|---|
start, and the schedule, webhook and plugin triggers |
a start — Kneo runs are created by a caller, so a trigger's schedule or route is carded to recreate outside Kneo |
llm, parameter-extractor |
an agent that answers once; its prompt is the system prompt, its user messages are run input. Its model is the workflow's shared model variable when its model selector names one; a selector Dify cannot resolve is carded source_cannot_run, blocking |
agent on Dify's own function_calling or ReAct strategy |
an agent with its model and instruction; each enabled tool is carded, blocking (see Tools below); any other strategy is carded, blocking |
if-else, question-classifier |
graph edges, one per case, each condition carded, blocking, for you to write. A branch straight after the start has no step before it to branch from: only its first case is connected, and every other case's step is carded branching_shape, blocking |
| a node's error handling (a fail branch, a default value) or its retry | carded, blocking: a Kneo step fails the run. A fail branch's route is kept as an ordinary edge so there is something to repair |
answer, end |
nothing — flow passes through. What the caller received is carded, manual, whenever a Kneo run's bare reply is not it: a formatted answer, named outputs, an empty answer, an End with no outputs, and an answer of one reference such as {{#sys.query#}}. The one exception is an answer that is exactly {{#<step>.text#}} for the LLM or agent step just before it, with nothing around it and nothing after it, and no other answer able to reply in the same run: Dify sends the caller every answer a run reaches. That step must also be the last the run takes, since a Kneo run returns its last step's output. A terminal missing its answer or outputs field is one Dify cannot build: carded, blocking |
iteration, loop and everything inside them |
one carded region, blocking — never flattened into steps that would run once |
code, http-request, tool |
carded, blocking: Kneo cannot run an inline body, an HTTP call or a tool as a step |
knowledge-retrieval, template-transform, variable-aggregator, assigner, document-extractor, list-operator, human-input, the knowledge-pipeline nodes, Dify's new Agent node (in the export, type: agent with version: "2" and agent_node_kind: dify_agent; the editor titles it Agent, like the strategy agent, and its prompt, model and tools live in the agent package under agent_packages), and any node type Studio does not recognise |
carded, blocking: no Kneo equivalent |
| a canvas note | not imported, info |
The whole mapping, row by row and read from Dify's own source, is the Dify mapping table.
The cards a Dify import usually carries¶
- The model's settings (
completion_params) —manual. The temperature and token cap are listed with the Kneo field each belongs in; set them by hand or accept the provider's defaults. - Run input —
manual. A start form's variables, and an LLM's user message, are what each caller must now supply. Kneo runs take their input from the caller. - A prompt with a variable —
blocking.{{#node.variable#}}in a workflow,{{name}}in a chat or completion app, and any Jinja template are Dify's own syntax. Kneo does not interpolate them, so the prompt is not carried; the card quotes it for you to rewrite. - Conversation memory —
blocking. Everychatandagent-chatapp carries it, because Dify always sends such an app its history, and so does anyadvanced-chatLLM, parameter extractor or agent node that has memory set. A Kneo agent does not keep earlier turns. - A model provider Studio does not recognise —
manual. The card names it; setagent.model.providerandagent.model.nameyourself. - Tools —
blocking. A Kneo tool needs a backing — Python, an MCP server or another agent — that no export can carry, so someone with platform access has to supply it. - A fan-out —
blocking,branching_shape. A node whose output is wired to several steps, or a branch case wired to several, runs them all in Dify. So does a step wired straight on beside a branch: it runs with whichever case fires. A Kneo graph step follows one edge, the first that matches, so the rest would never run. The edges are kept for you to rebuild as one path, and writing the branch's conditions alone does not clear this card. One step per case is a choice, not a fan-out, and draws no card. Dify runs a step that several connections reach once, after all of them, so a start wired toaand tobbesidea → bconverts as the chaina → b. But if the converted workflow reachesbonly through a branch, it is carded. - The app's features — one card for each feature the app turns on, because a Kneo spec has no app features.
- Moderation (content moderation,
sensitive_word_avoidance) isblockingin a chat, agent-chat, completion or advanced-chat app. Dify refuses a flagged query and replaces a flagged answer, and the converted agent would do neither, so rebuild the protection first. - File upload and text to speech are
manual. So are the chat features of an advanced-chat app: the opener, the follow-up suggestions and speech to text. - A feature the app's mode never uses is
info, and so are citations beside a knowledge retrieval.
What to expect¶
Over 614 real Dify exports, 607 convert, and 43 of them — about 7 in 100 — carry no blocking
card. All 43 are workflow or advanced-chat apps in which an LLM does the work. No chat,
agent-chat or completion export converts without one: every chat app carries the memory card,
and most carry a prompt variable. The blockers you will meet most are:
- nodes with no Kneo equivalent (code, http-request, knowledge retrieval, templates);
- prompts and conditions written in Dify's variable syntax;
- conversation memory;
- tool steps;
- branches Kneo cannot hang from a step.
A clean import shows an info card for the start — on Dify a start is how a caller begins a run,
which a Kneo run already is — and manual cards for run input and the response format, plus one
for each app feature it turns on.
examples/dify/answer-workflow.yml
is one to compare against.