mcpField
D
dify-workflow-skills

dify-workflow-skills

github.com/mango-svipエージェントワークフロー3236 回インストール42 週間前に更新
リポジトリ

dify-workflow-skills について

DifyのワークフローDSLファイルを作成、編集、検証するスキルです。Difyで自動化ワークフローを構築するためのノード、接続、変数、エラー処理パターンを扱います。

主な機能

  1. 01説明からワークフロー YAML を生成
  2. 02ノードと接続の編集
  3. 03DSL 構造の検証
  4. 04分岐、ループ、エラー処理の設計
  5. 05ノードタイプとパターンの参照

活用シーン

  1. 01Difyの自動化ワークフローを新規作成
  2. 02既存ワークフローのノードを追加・削除
  3. 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.yml
error_handling_workflow.yml
conditional_workflow.yml
references/
node_types.md
node_positioning.md
workflow_structure.md
edge_types.md
scripts/
generate_id.py
validate_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、スケジュール、プラグインのトリガーに使用されます

主な機能

  1. 新しいワークフローの作成 - 説明からワークフロー全体の YAML ファイルを生成
  2. 既存のワークフローの編集 - ノードや接続を追加、変更、削除
  3. ワークフローの検証 - DSL の構文と構造を確認
  4. 複雑なフローの設計 - LLM ノード、コード実行、分岐、ループ、エラー処理を含むワークフローを構築
  5. エラー処理戦略 - 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:ノードのフローを設計する

ワークフローの構造を計画します。

  1. Start ノード - 入力変数を定義します
  2. 処理ノード - LLM、code、ツールなど
  3. 制御フロー - 分岐には if-else、反復には loop を使用します
  4. エラー処理 - code ノードで fail-branch を使用します
  5. 出力の集約 - variable-aggregator で分岐を統合します
  6. 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 を定義します
  • ループは反復間で状態を保持します

既存のワークフローの編集

ノードの追加
  1. 既存のワークフローファイルを読み込みます
  2. 新しい一意のノード ID を生成します
  3. ノードを workflow.graph.nodes 配列に追加し、以下を設定します:
    • 一意の ID と位置
    • ノードの種類と設定
    • 適切な sourcePosition/targetPosition
  4. 新しいノードを接続するエッジを workflow.graph.edges に追加します
  5. 依存するノード(例:終了ノードの出力)を更新します
ノードの削除
  1. 削除するノード ID を特定します
  2. ノードを workflow.graph.nodes から削除します
  3. そのノード ID を参照するすべてのエッジを(ソースまたはターゲットとして)削除します
  4. 削除したノードの出力を参照していた下流ノードを更新します
接続の変更
  1. ソースとターゲットのノード ID からエッジを特定します
  2. エッジの source、target、sourceHandle、または targetHandle を更新します
  3. エッジの data.sourceType と data.targetType を、実際のノードの種類に合わせて更新します
  4. エッジの 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 がエディターに読み込まれると、次の処理が行われます。

  1. WorkflowContextProvider がノード/エッジを含む Zustand ストアを初期化します
  2. ReactFlow がカスタムノードコンポーネントでキャンバスをレンダリングします
  3. BaseNode が各ノードを共通 UI(ハンドル、ヘッダー)でラップします
  4. Panel System がノードの選択時に設定フォームを表示します
  5. 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: 分類ラベル(カスタム)
  • 重要: 選択されなかった経路は「スキップ」としてマークされ、後続の処理は実行されません
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 など)は、通常、再利用可能な出力変数を生成しません。ただし、一部のノードには限定的な内部状態がある場合があります。

ワークフロー実行モデル

実行フロー
  1. 初期化:GraphEngine がルートノードを ReadyQueue に登録します
  2. ワーカーの実行:ワーカースレッドが ReadyQueue からノードを取得して実行します
  3. イベントの発行:ワーカーがイベント(started、succeeded、failed)を event_queue に送信します
  4. エッジの処理:ディスパッチャーがイベントを処理し、後続ノードを特定します
  5. 依存関係の解決:依存関係が満たされると、後続ノードが ReadyQueue に追加されます
  6. 並列実行:複数のワーカーが独立したノードを同時に実行します
  7. 完了: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:ノードは単一実行のデバッグモードです
実行に関するベストプラクティス
  1. 並列実行と順次実行:独立したノードは自動的に並列実行されます。順序を指定する必要がある場合は、エッジを使用してください。
  2. エラーバウンダリー:重要なノードで fail-branch を使用し、ワークフローが中断されないようにしてください
  3. マージポイント:分岐を収束させる前に、必ず variable-aggregator を使用してマージしてください
  4. ループの安全性:妥当な loop_count の上限と、明確な中断条件を設定してください
  5. 人間からの入力: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 分岐を含むテンプレート

成功のためのヒント

  1. シンプルに始める:基本的なフローから始め、段階的に複雑さを加えてください
  2. テンプレートを使用する:ゼロから作成するのではなく、既存のテンプレートを調整してください
  3. 早めに検証する:多数のノードを追加する前に、構造を確認してください
  4. エラー処理を計画する:何が失敗する可能性があるか、どのように処理するかを検討してください
  5. 明確な名前を付ける:保守しやすいように、説明的なノードタイトルを使用してください
  6. ドキュメントを参照する:フィールドの要件については node_types.md を確認してください
  7. 段階的にテストする:ワークフローを一段階ずつ構築してテストしてください

コメント