dify-workflow-skills について
DifyのワークフローDSLファイルを作成、編集、検証するスキルです。Difyで自動化ワークフローを構築するためのノード、接続、変数、エラー処理パターンを扱います。
主な機能
- 01説明からワークフロー YAML を生成
- 02ノードと接続の編集
- 03DSL 構造の検証
- 04分岐、ループ、エラー処理の設計
- 05ノードタイプとパターンの参照
活用シーン
- 01Difyの自動化ワークフローを新規作成
- 02既存ワークフローのノードを追加・削除
- 03ノードID、接続、変数参照を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mango-svip/ dify-workflow-skills --skill dify-workflow-skillsインストール後、Claude Code で/dify-workflow-skillsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/simple_llm_workflow.ymlerror_handling_workflow.ymlconditional_workflow.ymlreferences/node_types.mdnode_positioning.mdworkflow_structure.mdedge_types.mdscripts/generate_id.pyvalidate_workflow.py詳細
Dify Workflow DSL Builder
AI を活用した自動化ワークフローを作成するための Dify ワークフロー DSL(ドメイン固有言語)ファイルを作成、編集、検証します。
このスキルは、Workflow アプリと Advanced Chat アプリの両方を支える、React Flow ベースのビジュアルエディターを備えた Dify のオープンソースプラットフォームのワークフローエンジンに基づいています。
アーキテクチャの概要
Dify のワークフローは、次の要素を備えたキューベースのイベント駆動型アーキテクチャを採用しています。
バックエンド(Python - 実行エンジン)
- GraphEngine:ワークフローの実行を管理する中央オーケストレーター
- WorkerPool:ノードを並列実行するためのスレッドプール
- VariablePool:ノード間で変数を一元管理
- EdgeProcessor:条件に応じたルーティングと分岐の選択を処理
- Graph Validator:実行前にワークフローの整合性を確認
フロントエンド(React/TypeScript - ビジュアルエディター)
- React Flow:キャンバスベースのノードグラフエディター
- Zustand Store:ノード、エッジ、ビューポートの状態管理
- WorkflowContext:コンポーネントツリーにワークフローの状態を提供
- BaseNode:ハンドル、ヘッダー、インタラクションを備えた、すべてのノードタイプ共通のラッパー
- Panel System:各ノードタイプに対応する動的な設定パネル
- Hook Injection Pattern:UI と実行ロジックを分離(ドラフト同期、ワークフローの実行)
統合レイヤー
- workflow:コアのキャンバスエンジン(汎用的な React Flow の実装)
- workflow-app:アプリケーションラッパー(ビジネスロジック、API 統合、ライフサイクル管理)
- Draft Management:デバウンスと
sendBeaconによる安全な自動保存- デバウンス付き同期により、過剰な API 呼び出しを防止
- 競合状態を避けるため、アンマウント時に保留中の同期をキャンセル
isWorkflowDataLoadedフラグで読み込み済み状態を追跡
- Features System:ワークフローに統合されたオプション機能(ファイルアップロード、音声テキスト変換、引用)
- Trigger Status Management:トリガーノードの有効/無効状態を追跡する独立したストア
- トリガーノードは個別に有効または無効にできます
- ワークフローエディターのセッションをまたいで状態が保持されます
- Webhook、スケジュール、プラグインのトリガーに使用されます
主な機能
- 新しいワークフローの作成 - 説明からワークフロー全体の YAML ファイルを生成
- 既存のワークフローの編集 - ノードや接続を追加、変更、削除
- ワークフローの検証 - DSL の構文と構造を確認
- 複雑なフローの設計 - LLM ノード、コード実行、分岐、ループ、エラー処理を含むワークフローを構築
- エラー処理戦略 - fail-branch、リトライ、またはデフォルト値によるエラー処理を実装
クイックリファレンス
ノードの種類:全種類の一覧については、references/node_types.mdを参照してください。以下の種類が含まれます。
- 基本フロー:start、end、answer
- LLM と AI:llm、agent、parameter-extractor
- ロジックと制御:if-else、question-classifier、loop、iteration
- データ処理:code、template-transform、variable-aggregator、assigner、list-operator、document-extractor
- 外部連携:http-request、tool、knowledge-retrieval、knowledge-index、datasource
- 高度な機能:trigger-webhook、trigger-schedule、trigger-plugin、human-input
エッジの種類と接続:references/edge_types.mdを参照してください。以下の情報が記載されています。
- ソースハンドルの種類(source、true/false、success-branch/fail-branch、loop)
- エッジデータのプロパティと検証ルール
- 一般的な接続パターン
ノードの配置:references/node_positioning.mdを参照してください。以下の情報が記載されています。
- キャンバスの座標系と間隔のガイドライン
- レイアウトパターン(直線、分岐、エラー処理、反復)
- 位置計算式
一般的なノードのプロパティ:すべてのノードは、以下の内部プロパティ(_が先頭に付くもの)をサポートしています。
_runningStatus:現在の実行ステータス(running、succeeded、failed)_connectedSourceHandleIds/_connectedTargetHandleIds:接続の追跡_isSingleRun:デバッグ用の単一実行モード_isCandidate:接続のドラッグ中に表示される仮ノード_children:コンテナー型(iteration、loop)の子ノード_iterationLength/_iterationIndex:反復状態の追跡_loopLength/_loopIndex:ループ状態の追跡_retryIndex:現在の再試行回数_waitingRun:実行待ちのキューに追加済み(human-input)
ワークフローの構造:DSL 形式の全体については、references/workflow_structure.mdを参照してください。
エッジの種類:接続パターンとハンドルの種類については、references/edge_types.mdを参照してください。
ノードの配置:レイアウトのガイドラインについては、references/node_positioning.mdを参照してください。
テンプレート:ワークフローの例はassets/で確認できます。
新しいワークフローの作成
ステップ 1:要件を把握する
ユーザーに次の点を確認します。
- ワークフローで何を行いますか?
- 入力と出力は何ですか?
- どのような処理手順が必要ですか?
- 条件分岐やエラー処理は必要ですか?
ステップ 2:ノードのフローを設計する
ワークフローの構造を計画します。
- Start ノード - 入力変数を定義します
- 処理ノード - LLM、code、ツールなど
- 制御フロー - 分岐には if-else、反復には loop を使用します
- エラー処理 - code ノードで fail-branch を使用します
- 出力の集約 - variable-aggregator で分岐を統合します
- End ノード - 出力を定義します
ステップ 3:ノード ID を生成する
scripts/generate_id.pyを使用して、一意のノード ID を生成します。
python3 scripts/generate_id.py 5 # Generate 5 unique IDs
または、Python/JavaScript で生成します。
# Python
import time
node_id = str(int(time.time() * 1000))
// JavaScript (used in Dify frontend)
const nodeId = `${Date.now()}`
コンテナーノードの特別な ID パターン:
- Iteration/Loop の開始ノード:
${parentNodeId}start - 例:Iteration ノード ID が
1736668800000の場合、その開始ノード ID は1736668800000startです。
ステップ 4:ワークフローを構築する
以下を含む YAML 構造全体を作成します。
- トップレベルのメタデータ(kind、version、app)
- App セクション(name、description、icon)
- features と graph を含む Workflow セクション
- 位置情報を含む Nodes 配列
- ノードを接続する Edges 配列
使用するテンプレート:基本的なフローはassets/simple_llm_workflow.ymlを基にします。
ステップ 5:検証する
よくある問題がないか、ワークフローの構造を確認します。
- すべてのノードに一意の ID がある
- すべてのエッジが既存のノード ID を参照している
- Start ノードと End ノードが存在する
- 必須フィールドがすべて含まれている
- 変数参照に正しい構文を使用している:
{{#node_id.field#}}
一般的なワークフローパターン
パターン 1:シンプルな LLM フロー
Start → LLM → End
用途:基本的な質問応答、テキスト生成
テンプレート:assets/simple_llm_workflow.yml
パターン 2:エラー処理フロー
開始 → コード(失敗ブランチあり)→ [成功 → アグリゲーター] / [失敗 → LLM によるリカバリー → 再試行 → アグリゲーター] → 終了
ユースケース:エラーリカバリーを伴う堅牢なデータ処理
テンプレート:assets/error_handling_workflow.yml
重要なポイント:
- コードノードに
error_strategy: fail-branchを設定します - 失敗ブランチでは
error_message変数とerror_type変数が提供されます - variable-aggregator を使用して成功ブランチと失敗ブランチを統合します
- 終了ノードではアグリゲーターの出力を参照します
パターン 3:条件付きルーティング
開始 → If-Else → [True → ハンドラー A] / [False → ハンドラー B] → アグリゲーター → 終了
ユースケース:コンテンツや種類に基づいてリクエストを振り分けます
テンプレート:assets/conditional_workflow.yml
重要なポイント:
- If-Else には
trueとfalseの sourceHandles があります - 比較演算子を使用します:contains、starts_with、is_empty など
logical_operator: "and"またはlogical_operator: "or"で条件を組み合わせます
パターン 4:ループ処理
開始 → ループ → [項目を処理] → ループ終了 → 終了
ユースケース:終了条件を伴う反復処理
重要なポイント:
- 最大反復回数として
loop_countを設定します - 早期終了するための
break_conditionsを定義します - ループは反復間で状態を保持します
既存のワークフローの編集
ノードの追加
- 既存のワークフローファイルを読み込みます
- 新しい一意のノード ID を生成します
- ノードを
workflow.graph.nodes配列に追加し、以下を設定します:- 一意の ID と位置
- ノードの種類と設定
- 適切な sourcePosition/targetPosition
- 新しいノードを接続するエッジを
workflow.graph.edgesに追加します - 依存するノード(例:終了ノードの出力)を更新します
ノードの削除
- 削除するノード ID を特定します
- ノードを
workflow.graph.nodesから削除します - そのノード ID を参照するすべてのエッジを(ソースまたはターゲットとして)削除します
- 削除したノードの出力を参照していた下流ノードを更新します
接続の変更
- ソースとターゲットのノード ID からエッジを特定します
- エッジの
source、target、sourceHandle、またはtargetHandleを更新します - エッジの
data.sourceTypeとdata.targetTypeを、実際のノードの種類に合わせて更新します - エッジの
idを次の命名規則に従って更新します:{source_id}-{handle}-{target_id}-target
変数の参照構文
変数は VariablePool で一元管理され、次の形式を使用します:{{#node_id.field_name#}}
変数の種類(VarType)
Dify は、型安全なデータフローを実現するために次の変数の種類をサポートしています:
プリミティブ型:
string:テキストデータnumber:浮動小数点数integer:整数boolean:true/false の値secret:暗号化された機密データ(API キー、パスワード)
複合型:
object:JSON オブジェクトfile:単一ファイルの参照array:汎用配列array[string]:文字列の配列array[number]:数値の配列array[object]:オブジェクトの配列array[boolean]:ブール値の配列array[file]:ファイルの配列array[any]:複数の型を含む配列any:任意の型(使用は必要最小限にしてください)
特殊型:
contexts:ナレッジ検索の結果iterator:反復処理の入力変数loop:ループの入力変数
ファイルアップロードの設定
ファイル入力型(file、files、file-list)を使用する場合、アップロード設定を構成できます:
デフォルトのファイルアップロード設定:
allowed_file_upload_methods: ['local_file', 'remote_url']
max_length: 5 # Maximum number of files
allowed_file_types: ['image'] # Options: image, document, audio, video, custom
allowed_file_extensions: [] # e.g., ['.pdf', '.docx']
アップロード方法:
local_file:ローカルシステムから直接ファイルをアップロードしますremote_url:URL からファイルをアップロードします
ファイルの種類:
image:画像ファイル(JPG、PNG、GIF など)document:ドキュメントファイル(PDF、DOCX、TXT など)audio:音声ファイル(MP3、WAV など)video:動画ファイル(MP4、AVI など)custom:カスタムのファイル形式(拡張子を指定します)
入力変数の型(InputVarType)
開始ノードでは、ユーザー向けの変数に次の入力型を使用します。
text-input:1 行のテキスト入力paragraph:複数行のテキスト入力select:ドロップダウン選択number:数値入力checkbox:ブール値のチェックボックスurl:検証機能付き URL 入力files:複数ファイルのアップロードfile:単一ファイルのアップロードfile-list:複数ファイルのリストjson:JSON 入力(オブジェクトまたは配列)json_object:スキーマ検証付き JSON オブジェクトcontexts:ナレッジ検索コンテキストiterator:反復変数loop:ループ変数
変数セレクターのパターン
変数パターンの正規表現:{{#[a-zA-Z0-9_]{1,50}(?:\.[a-zA-Z_][a-zA-Z0-9_]{0,29}){1,10}#}}
セレクターの構造:[node_id, variable_name, ...optional_nested_keys]
- 最初の要素:変数を生成したノード ID
- 2 番目の要素:変数名または出力フィールド
- 追加の要素:ネストされたオブジェクトのキーまたは配列インデックス(FileSegment/ObjectSegment 用)
ValueSelector:DSL で使用される配列形式(例:['1732007415808', 'text'])
- YAML では配列として表現されます:
value_selector: ['node_id', 'field_name'] - プロンプトではテンプレート構文に変換されます:
{{#node_id.field_name#}}
システム変数
sys ノード ID から利用できます。
{{#sys.query#}}- ユーザーのクエリ/入力{{#sys.files#}}- アップロードされたファイル{{#sys.conversation_id#}}- 現在の会話 ID{{#sys.user_id#}}- ユーザー識別子{{#sys.dialogue_count#}}- 対話ターン数{{#sys.app_id#}}- アプリケーション ID{{#sys.workflow_id#}}- ワークフロー ID{{#sys.workflow_run_id#}}- 現在の実行 ID{{#sys.timestamp#}}- 現在のタイムスタンプ
ノードタイプ別の共通出力フィールド
LLM ノード:
{{#node_id.text#}}- 生成されたテキスト応答(型: string){{#node_id.usage#}}- トークン使用量情報(型: object){{#node_id.reasoning_content#}}- モデルの推論(有効な場合)(型: string)
エージェントノード:
{{#node_id.usage#}}- トークン使用量情報(型: object)
コードノード:
{{#node_id.output_name#}}- ノード設定で定義された名前付き出力{{#node_id.error_message#}}- エラーメッセージ(失敗ブランチのみ)(型: string){{#node_id.error_type#}}- エラータイプ(失敗ブランチのみ)(型: string)
開始ノード:
{{#node_id.variable_name#}}- 開始ノードで定義された入力変数
条件分岐ノード:
{{#node_id.condition_result#}}- ブール型の条件結果
ループノード:
{{#node_id.output#}}- ループ出力配列{{#node_id.iteration#}}- 現在の反復番号
HTTP リクエストノード:
{{#node_id.body#}}- 応答本文(型: string){{#node_id.status_code#}}- HTTP ステータスコード(型: number){{#node_id.headers#}}- 応答ヘッダー(型: object){{#node_id.files#}}- 応答がファイルの場合にダウンロードされたファイル(型: array[file])
ツールノード:
{{#node_id.text#}}- ツールの出力テキスト(型: string){{#node_id.files#}}- ツールの出力ファイル(型: array[file]){{#node_id.json#}}- ツールの出力 JSON(型: array[object])
ナレッジ検索ノード:
{{#node_id.result#}}- 検索されたナレッジセグメント(型: array[object])
テンプレート変換ノード:
{{#node_id.output#}}- 変換後の出力(型: string)
質問分類ノード:
{{#node_id.class_name#}}- 分類結果(型: string){{#node_id.usage#}}- トークン使用量情報(型: object)
パラメーター抽出ノード:
{{#node_id.__is_success#}}- 抽出成功を示す値(型: number){{#node_id.__reason#}}- 抽出に失敗した理由(型: string){{#node_id.__usage#}}- トークン使用量情報(型: object)- ノード設定で定義されたカスタム抽出パラメーターも含まれます
変数集約ノード:
{{#node_id.output#}}- 結合されたブランチからの集約出力
ファイルオブジェクトの構造(ファイル型を使用する場合):
name- ファイル名(型: string)size- ファイルサイズ(バイト単位)(型: number)type- ファイルタイプのカテゴリ(型: string)extension- ファイル拡張子(型: string)mime_type- MIME タイプ(型: string)transfer_method- 使用された転送方法(型: string)url- ファイル URL(型: string)related_id- 関連リソース ID(型: string)
ナレッジ検索結果の構造:
{
"content": "",
"title": "",
"url": "",
"icon": "",
"metadata": {
"dataset_id": "",
"dataset_name": "",
"document_id": [],
"document_name": "",
"document_data_source_type": "",
"segment_id": "",
"segment_position": "",
"segment_word_count": "",
"segment_hit_count": "",
"segment_index_node_hash": "",
"score": ""
}
}
環境変数と会話変数
環境変数(アプリレベルで定義):
- 特別なノード ID
envを使用してアクセスします - 例:
{{#env.API_KEY#}}
会話変数(セッション状態):
- 特別なノード ID
conversationを使用してアクセスします - 例:
{{#conversation.user_context#}}
変数の使用例
# In LLM prompt template
prompt_template:
- role: system
text: "You are a helpful assistant."
- role: user
text: "Process this input: {{#1732007415808.user_input#}}"
# In code node
variables:
- ["1732007415808", "user_input"]
- ["1732007420123", "processed_data"]
# Accessing nested object fields
text: "File name: {{#upload_node.files.name#}}"
text: "API response status: {{#http_node.status_code#}}"
ノードの配置
視覚的にわかりやすくなるよう、キャンバス上にノードを配置します。
レイアウト定数(Dify のフロントエンドに基づく):
NODE_WIDTH:240 ピクセルX_OFFSET:60 ピクセル(水平間隔)NODE_WIDTH_X_OFFSET:300 ピクセル(ノード幅+間隔)Y_OFFSET:39 ピクセルSTART_INITIAL_POSITION:{ x: 80, y: 282 }NODE_LAYOUT_HORIZONTAL_PADDING:60 ピクセルNODE_LAYOUT_VERTICAL_PADDING:60 ピクセルNODE_LAYOUT_MIN_DISTANCE:100 ピクセル
コンテナノードのパディング:
- Iteration/Loop コンテナ:
- 上:65、右:16、下:20、左:16
- Iteration/Loop の Z インデックス:1(コンテナ)、1002(子ノード)
水平間隔:接続されたノード間は300~400ピクセル 垂直間隔:
- 同じ階層:同じ y 座標
- 分岐:150~200ピクセルずらします
配置例:
Start: x=80, y=282 # Initial position
LLM: x=380, y=282 # Start + NODE_WIDTH_X_OFFSET
Code: x=680, y=282
End: x=980, y=282
分岐の場合:
If-else: x=380, y=300
True branch: x=680, y=200
False branch: x=680, y=450
Aggregator: x=980, y=300
コンテナノード(Iteration/Loop):
- コンテナ内の開始ノード:{ x: 24, y: 68 }(コンテナからの相対位置)
- 子ノードの
parentIdにはコンテナ ID を設定します - 子ノードはコンテナ(1)よりも高い Z インデックス(1002)を持ちます
詳細なレイアウトパターンと数式については、references/node_positioning.md を参照してください。
ビジュアルエディターとの連携
作成した DSL は、React Flow で構築された Dify のビジュアルワークフローエディターでレンダリングされます。
DSL と UI の対応
ノード → キャンバス上のビジュアルブロック。以下の要素を含みます。
- アイコンとタイトル(
typeフィールドとtitleフィールドから取得) - 接続ハンドル(ノードの種類と error_strategy に基づく)
- 設定パネル(右サイドバーに表示されるノード固有のフォーム)
- ステータスインジケーター(実行中、成功、失敗)
エッジ → ノードを接続するベジェ曲線。以下の要素を含みます。
- 状態(ホバー、選択、実行中)に基づくビジュアルスタイル
- 分岐パスのラベル(true/false、分類ラベル)
- 成功/失敗の分岐を色で表示
ビューポート → キャンバスの表示設定:
viewport:
x: 0 # Pan offset X
y: 0 # Pan offset Y
zoom: 1.0 # Zoom level (0.1 to 2.0)
フロントエンドコンポーネントのアーキテクチャ
DSL がエディターに読み込まれると、次の処理が行われます。
- WorkflowContextProvider がノード/エッジを含む Zustand ストアを初期化します
- ReactFlow がカスタムノードコンポーネントでキャンバスをレンダリングします
- BaseNode が各ノードを共通 UI(ハンドル、ヘッダー)でラップします
- Panel System がノードの選択時に設定フォームを表示します
- Hook System がドラフトの自動保存と実行を管理します
DSL に含まれない UI 機能
以下の UI 専用プロパティはフロントエンドで管理されます(DSL には含めないでください)。
_hovering、_connectedNodeIsHovering:マウス操作の状態_connectedSourceHandleIds、_connectedTargetHandleIds:エッジから算出_runningStatus、_singleRunningStatus:実行時の状態_isCandidate:接続をドラッグしている間の一時的な仮ノードselected:ノードの選択状態
重要:DSL には永続的なプロパティ(id、type、title、position、configuration)のみを含めてください。実行時の UI 状態はエディターによって算出されます。
エラー処理戦略
エラー処理戦略
Dify は、ノード設定で定義される複数のエラー処理戦略をサポートしています。
1. fail-branch(コードノード/HTTP ノードに推奨):
- エラー発生時に代替の実行パスを作成します
error_messageとerror_typeの変数を提供します- エッジ設定で
sourceHandle: "fail-branch"を使用します - 成功パスでは
sourceHandle: "success-branch"を使用します - 終了ノードに進む前に、成功パスとマージするための variable-aggregator が必要です
- エラーからのスムーズな復旧と、カスタムエラー処理ロジックが可能です
2. default-value:
- エラー発生時に、事前定義されたデフォルト値を返します
- 分岐せずにメインの実行パスを続行します
- fail-branch よりシンプルですが、堅牢性は低くなります
- フォールバック値を許容できる、重要度の低い処理に適しています
3. abort(デフォルト):
- 失敗時にワークフロー全体の実行を停止します
- 追加の設定は不要です
- 復旧不能なエラーが発生した場合に使用します
4. retry:
- 最大再試行回数と間隔を設定できる再試行ロジックです
- ノードの
retry_configセクションで定義します - 一時的な障害(ネットワークの問題、レート制限)に役立ちます
- サポート対象:LLM、ツール、HTTP リクエスト、コードノードのみ
再試行設定の構造:
retry_config:
max_retries: 3 # Maximum retry attempts (default: 3)
retry_interval: 100 # Interval between retries in ms (default: 100)
fail-branch エラー処理の実装
ノード設定:
error_strategy: fail-branch
edges 配列:
# Success path
- id: code_node-success-branch-next_node-target
source: code_node_id
target: aggregator_id
sourceHandle: success-branch
targetHandle: target
# Failure path
- id: code_node-fail-branch-error_handler-target
source: code_node_id
target: error_handler_id
sourceHandle: fail-branch
targetHandle: target
fail-branch で使用可能なエラー変数:
{{#node_id.error_message#}}- 人間が読める形式のエラー説明{{#node_id.error_type#}}- エラー種別の分類
検証チェックリスト
ワークフローを確定する前に、以下を確認します。
構造の検証
- すべてのノード ID が一意で、適切な形式(数値文字列または有効な識別子)になっている
- ワークフローのルートノードが1つだけである(開始ノード、データソースノード、またはトリガーノード)
- ワークフローに少なくとも1つの終了ノードがある
- すべてのエッジが、nodes 配列内に存在する有効なソースノード ID とターゲットノード ID を参照している
- 意図的なループノードを除き、無限ループを引き起こす循環依存がない
- ルートノードが正しく特定され、アクセス可能である
エッジと接続の検証
- すべてのエッジ ID が一意である
- エッジの
sourceHandle値がノード種別と一致している:- 標準ノード:「source」(デフォルト)
- If-else/Question-classifier:「true」、「false」、または分類ラベル
- エラー処理を設定したコード/HTTP ノード:「success-branch」または「fail-branch」
- ループノード:続行用の「loop」
- 多くのノードで、エッジの
targetHandleは通常「target」である - エッジの
data.sourceTypeが実際のソースノード種別と一致している - エッジの
data.targetTypeが実際のターゲットノード種別と一致している - 分岐パス(if-else、question-classifier からのパス)に、考えられるすべての結果に対応するエッジがある
-
error_strategy: fail-branchを使用する場合、fail-branch のエッジが存在する
変数とデータフローの検証
- 変数参照で正しい構文
{{#node_id.field#}}を使用している - 参照するすべての変数が上流ノード(現在のノードより前に実行されるノード)に存在する
- 変数セレクターが、参照先ノードの実際の出力フィールドと一致している
- システム変数で正しい
sysプレフィックス{{#sys.query#}}を使用している - 必要な場合、環境変数で
envプレフィックスを使用している - 実行時エラーの原因となる未定義の変数参照がない
エラー処理の検証
-
error_strategy: fail-branchを設定したノードに、成功エッジと失敗エッジの両方がある - 終了ノードに到達する前に、分岐パスが variable-aggregator でマージされている
- variable-aggregator が、すべての分岐パスから入力を受け取っている
-
error_strategy: default-valueを使用する場合、デフォルト値が指定されている - retry 戦略を使用する場合、再試行設定(最大再試行回数、間隔)が有効である
ノード設定の検証
- 各ノードタイプで必須フィールドが設定されていること(node_types.md を参照)
- 視覚的なレイアウトのため、ノードの位置(x、y 座標)が設定されていること
- LLM ノードに有効なモデル設定(プロバイダー、名前、モード)があること
- コードノードで有効な言語(python3 または javascript)が指定されていること
- HTTP リクエストノードに有効な URL とメソッドが設定されていること
- ループノードに有効な
loop_countと終了条件が設定されていること - if-else ノードの条件が適切に構成され、有効な演算子が使用されていること
ワークフロー実行の検証
- 到達不能なノードがないこと(すべてのノードがルートノードから到達可能であること)
- すべての実行経路が最終的に終了ノードまたは回答ノードに到達すること
- コンテナノード(反復、ループ)に適切な開始/終了ノードのペアが設定されていること
- 人間による入力を受け付けるノードが適切に使用されていること(ワークフローは入力待ちで一時停止します)
- トリガーノード(webhook、schedule)が標準の開始ノードと混在していないこと
ノードの実行タイプ
Dify では、ノードを実行時の動作に基づいて分類します。これらのタイプを理解すると、適切なワークフローを設計できます。
EXECUTABLE(標準ロジックノード)
ロジックを実行して出力を生成します。最も一般的なノードタイプです。
- 例: llm、code、http-request、knowledge-retrieval、template-transform
- 動作: すべての入力依存関係が満たされると実行されます
- ソースハンドル:
"source"(またはエラー処理を使用する場合は"success-branch"/"fail-branch") - 出力: ノードタイプによって定義されます(変数リファレンスのセクションを参照)
BRANCH(条件分岐ノード)
条件に基づいて複数の経路から選択し、制御フローを管理します。
- 例: if-else、question-classifier
- 動作: 条件を評価し、1 つ以上の出力エッジを有効にします
- ソースハンドル:
- If-else:
"true"、"false" - Question-classifier: 分類ラベル(カスタム)
- If-else:
- 重要: 選択されなかった経路は「スキップ」としてマークされ、後続の処理は実行されません
CONTAINER(サブグラフ管理)
反復またはループを使って、ネストされた実行コンテキストを管理します。
- 例: iteration、loop
- 動作: 内部のサブグラフを複数回実行します
- 構成要素:
- 親コンテナノード
- 内部開始ノード(iteration-start、loop-start)
- 内部終了ノード(iteration-end、loop-end)
- ソースハンドル: 反復/ループを継続する場合は
"loop" - 状態管理: ループ変数と反復回数を保持します
RESPONSE(出力ストリーミング)
出力をリアルタイムでユーザーにストリーミングします。
- 例: answer、end
- 動作: 結果を出力し、ワークフローを終了する場合があります
- 用途: 回答ノードはワークフローの途中に配置できます。終了ノードは実行を終了します
ROOT(エントリーポイント)
ワークフローのエントリーポイントとして機能します。
- 例: start、datasource、trigger-webhook、trigger-schedule、trigger-plugin
- 動作: 最初に実行されるノードで、入力エッジはありません
- 重要: ワークフローごとにルートノードは 1 つのみです
- 制約: 標準の開始ノードとトリガーノードは共存できません
出力変数をサポートするノード
次のノードタイプは、ほかのノードから参照できる出力変数を生成できます。
- Start、TriggerWebhook、TriggerPlugin
- LLM、Agent
- KnowledgeRetrieval
- Code
- TemplateTransform
- HttpRequest
- Tool
- VariableAssigner、VariableAggregator
- QuestionClassifier
- ParameterExtractor
- Iteration、Loop
- DocumentExtractor(DocExtractor)
- ListFilter(list-operator)
- DataSource
注: この一覧にないノード(if-else、end、answer など)は、通常、再利用可能な出力変数を生成しません。ただし、一部のノードには限定的な内部状態がある場合があります。
ワークフロー実行モデル
実行フロー
- 初期化:GraphEngine がルートノードを ReadyQueue に登録します
- ワーカーの実行:ワーカースレッドが ReadyQueue からノードを取得して実行します
- イベントの発行:ワーカーがイベント(started、succeeded、failed)を event_queue に送信します
- エッジの処理:ディスパッチャーがイベントを処理し、後続ノードを特定します
- 依存関係の解決:依存関係が満たされると、後続ノードが ReadyQueue に追加されます
- 並列実行:複数のワーカーが独立したノードを同時に実行します
- 完了:End ノードが実行されるか、実行が失敗するとワークフローが終了します
エッジの状態
実行中、エッジは次の 3 つの状態になります:
- UNKNOWN:初期状態。まだ評価されていません
- TAKEN:エッジがたどられます(条件が満たされたか、経路が選択された場合)
- SKIPPED:エッジがたどられません(条件が満たされなかったか、別の経路が選択された場合)
ワークフローの実行ステータス
ワークフローは次の状態に移行します:
- SCHEDULED:キューに登録されていますが、まだ開始されていません
- RUNNING:実行中です
- SUCCEEDED:エラーなしで完了しました
- FAILED:未処理のエラーにより終了しました
- PARTIAL_SUCCEEDED:処理済みのエラー(fail-branch または default-value による)を含めて完了しました
- STOPPED:手動で停止または中断されました
- PAUSED:人間からの入力を待っています(human-input ノード)
ノードの実行ステータス
個々のノードは、次のステータスで実行状態を追跡します:
- NOT_START:ノードの実行はまだ開始されていません
- WAITING:ノードはキューに登録され、実行を待っています
- LISTENING:ノードはイベントを待ち受けています(トリガーノード)
- RUNNING:ノードは現在実行中です
- SUCCEEDED:ノードは正常に完了しました
- FAILED:ノードは未処理のエラーにより失敗しました
- EXCEPTION:ノードは失敗しましたが、エラーは処理されました
- RETRY:ノードは失敗後に再試行しています
- STOPPED:ノードの実行は停止されました
重要な UI 状態プロパティ(実行時のみ。DSL には含まれません):
_runningStatus:現在の実行ステータス_singleRunningStatus:単一ノード実行時のステータス_waitingRun:ノードは実行キューに登録されています_retryIndex:現在の再試行回数_isSingleRun:ノードは単一実行のデバッグモードです
実行に関するベストプラクティス
- 並列実行と順次実行:独立したノードは自動的に並列実行されます。順序を指定する必要がある場合は、エッジを使用してください。
- エラーバウンダリー:重要なノードで fail-branch を使用し、ワークフローが中断されないようにしてください
- マージポイント:分岐を収束させる前に、必ず variable-aggregator を使用してマージしてください
- ループの安全性:妥当な
loop_countの上限と、明確な中断条件を設定してください - 人間からの入力:human-input ノードを使用する場合は、一時停止状態を想定して計画してください
リソース
scripts/
generate_id.py- ワークフロー用の一意なノード ID を生成しますvalidate_workflow.py- ワークフロー DSL の構文を検証します(PyYAML が必要です)
references/
node_types.md- Dify のすべてのノードタイプの詳細なリファレンスと例workflow_structure.md- DSL の構造と形式に関する詳細な仕様
assets/
simple_llm_workflow.yml- 基本的な開始→LLM→終了のテンプレートerror_handling_workflow.yml- fail-branch によるエラー処理を含むテンプレートconditional_workflow.yml- if-else 分岐を含むテンプレート
成功のためのヒント
- シンプルに始める:基本的なフローから始め、段階的に複雑さを加えてください
- テンプレートを使用する:ゼロから作成するのではなく、既存のテンプレートを調整してください
- 早めに検証する:多数のノードを追加する前に、構造を確認してください
- エラー処理を計画する:何が失敗する可能性があるか、どのように処理するかを検討してください
- 明確な名前を付ける:保守しやすいように、説明的なノードタイトルを使用してください
- ドキュメントを参照する:フィールドの要件については node_types.md を確認してください
- 段階的にテストする:ワークフローを一段階ずつ構築してテストしてください