Dify+webhook+poll+エラー

Vercel + Supabase + Dify + Clerk を使用して非同期処理システムを構築しました。
Dify の最後のノードは HTTP フックを使って結果を Supabase に POST し、それがフロントエンドに表示されます。

問題が発生しました:エラーが報告された場合です。
Dify のノードがエラーを報告すると、全体の処理が停止し、閉じたループを形成できなくなります。
エラー分岐を通じてエラー処理ループを構築することは可能です。
しかし、複雑なワークフローでは各ノードにエラー分岐を有効にするのは煩雑すぎます。

エラー情報もビジネスロジックのウェブフック経由で直接流れることを可能にする方法はありますか?

Dify は LLM ノード、HTTP、コード、ツールに対してエラーハンドリング機能を備えています。このリンク(Page Not Found

こんにちは、Sherryさん

フィードバックありがとうございます。

Difyの現在のエラー処理メカニズムは、主にコンテンツノードがエラーを処理する方法に焦点を当てており、ワークフローの実行がスムーズであることを保証することを目的としています。

私が言及している具体的なシナリオは、DifyがSupabaseと統合する場合です。ワークフローの全体的なステータス(例:「成功」、「失敗」、「部分的な成功」)をSupabaseに投稿し、それがフロントエンドに迅速に反映されるようにする必要があります。

これを実現するには、追加の処理を必要としないシステムレベルの通知があるか、またはwebhookを介してこれを処理できる必要があります。全体として、Difyはこの特定のシナリオにおいて現在不足しているように見えます。

Difyがより大きなシステム内の1つのコンポーネントとして機能することは、一般的なユースケースです。このステータスコールバックメカニズムの欠如は、一見小さなギャップに見えますが、統合において大きな頭痛の種となります。これを回避するために、サードパーティの監視ツールを統合することを検討しなければなりませんでした。

あるいは、Difyにはすでにこの機能があり、私がまだ発見していない、または見つけ出せていないだけかもしれません。

Sherry_M <notifications@dify-community.discoursemail.com> は2026年1月15日木曜日 17:52に書きました:

Difyは以前から監視機能を提供しており、複数の監視システムと連携することも可能です
具体的な方法については、@Dify_Forum_Helper に尋ねる必要があるかもしれません

この要件は本質的に2つのレベルにあります。

  1. ビジネスシステムが「グローバルな状態コールバック」を必要としている(成功 / 失敗 / 部分成功)。途中のノードでエラーが発生してもSupabaseに通知できる必要があります。
  2. 各ノードで個別にエラーブランチを引くのを避けたい。より抽象的なレイヤーを求めている。

現在、Difyの設計では「ノードレベルのエラー処理 + 監視/追跡統合」が主であり、「自動的なグローバル状態のwebhook」ではありません。あなたのシナリオを考慮すると、2つの方法が考えられます。


一、ワークフロー内部で「グローバルステートマシン」をシミュレートする

既存の「workflow_finished」イベントはありませんが、シンプルなパターンで必要な状態コールバックを実現し、各ノードでエラーブランチを作成する手間を最小限に抑えることができます。

1. 「状態集約」変数を構築する

  • ワークフローの冒頭でグローバル変数を設定します。例えば:
    • workflow_status:初期値 \"Success\"
    • error_messages:初期値 [] または \"\"

2. 重要なノードのみにエラーブランチを設定する

すべてのノードではなく、「重要なパスのノード」にのみエラーブランチを設定できます。例えば:

  • 外部HTTP呼び出しノード
  • 重要なLLM推論ノード
  • カスタムCodeノード

各エラーブランチでは、以下の2つのことを行います。

  1. workflow_status\"Failure\" または \"PartialSuccess\" に変更します(ビジネスの定義によります)。
  2. エラーメッセージを error_messages に追加します。

形式的には、Codeノードまたは「状態更新」HTTPノードになります。

# 疑似コード
workflow_status = "Failure"
error_messages.append(node_error_message)

これにより、エラーブランチで複雑なロジックを記述する必要がなく、「マーク付け」のみを行い、後で1つのノードがSupabaseへのコールバックを統一して担当します。

3. ワークフローの最後に「結果レポート」HTTPノードを統一して配置する

途中で失敗したかどうかに関わらず、以下のことを保証できれば:

  • 「失敗する可能性があり、かつ関心のあるすべてのノード」に、何らかの継続パス(例えば、「実行継続」ノードに集約される)を指すエラーブランチがあること、
  • 最終的に必ず「最終状態HTTPノード」に到達すること、

この最終状態HTTPノードは、結果をSupabaseに統一して書き込むことができます。

POST /your-supabase-endpoint
{
  "run_id": "{{ context.run_id }}",
  "status": "{{ workflow_status }}",
  "errors": "{{ error_messages }}",
  "data": { ... ビジネスがフロントエンドに返す必要のあるコンテンツ ... }
}

重要なポイントは:

  • エラーブランチはフローを「終了」させず、「状態をマーク付け + メインラインに戻る」
  • メインラインの最後は固定でwebhookを実行し、全体の状態をSupabaseに書き戻す

これにより、「システムレベルのコールバック」がなくても、同等の機能が実現できます。


二、Difyの監視 / 追跡統合を利用する

サードパーティの監視を検討しているとのことですが、Difyは現在、複数の監視/追跡システムとの統合を内蔵しています(スクリーンショットの右側にあるプロバイダーを参照)。

これらの監視システムは通常、2種類の機能を提供します。

  1. 各実行のTrace / Spanの詳細
    • 各ノードの成功 / 失敗、所要時間、エラーメッセージなどを記録できます。
  2. Webhook / Export / APIクエリ
    • これらのシステムでルールを設定できます。
      • 特定のApp / ワークフローでエラーが発生したときにwebhookをトリガーする
      • または、定期的にそれらのAPIから「実行状態」を取得し、その後、独自のサービスが結果をSupabaseに書き戻す。

この方法の特徴は:

  • 利点:Difyに多くのロジックを追加する必要がなく、観測データがより包括的です。複数のワークフロー、複数の環境を統一して監視するのに適しています。
  • 欠点:Supabaseのフロントエンドにとって、状態は「間接的」に同期されるため、監視システムから状態を転送するための小さなサービスを別途作成する必要があります。

もしサードパーティの監視をすでに検討しているなら、以下のことができます。

  1. Difyの「Monitoring / Tracing」で、使い慣れたプロバイダーを設定する。
  2. そのプロバイダーが以下をサポートしているか確認する。
    • 「アラートルール」の作成 => HTTPコールバックのトリガー
    • または、クエリAPIを提供し、Supabase側でポーリング / 非同期更新を行う。

三、現在「組み込みのグローバル状態コールバック」はありますか?

現在アクセス可能な情報に基づくと:

  • Difyは持っています
    • ノードレベルのエラー処理(LLM / HTTP / Code / Tools)
    • ワークフロー監視とサードパーティ監視システムとの統合
  • しかし、以下のようなものは見当たりません
    • 「ワークフローが終了したとき(成功/失敗に関わらず)指定されたURLに自動的にPOSTする」
      という直接的な設定エントリポイント。

したがって:

  • 現在必要な機能は、**「状態集約 + 最終状態webhookノード」**を介して自分でレイヤーを構築する必要があります。
  • または、監視/追跡システムを介して「間接的なコールバック」を行うことができます。

四、実現可能な設計提案(Supabaseと組み合わせる)

既存のアーキテクチャ(Vercel + Supabase + Dify + Clerk)では、以下のようにすることをお勧めします。

  1. Supabaseテーブル構造にフィールドを追加します。
    • workflow_run_id(Difyのrun idに対応)
    • status'pending' | 'running' | 'success' | 'failure' | 'partial'
    • error_summary:text / jsonb
  2. フロントエンドは、これらのフィールドに基づいて実行状態を表示するだけです。
  3. Difyワークフロー
    • 冒頭で workflow_status=\"Success\"error_messages=[] を作成します。
    • 重要なノードにエラーブランチを追加します。これは「状態を書き込み + 継続」のみを行います。
    • 最後のHTTPノードでSupabaseに POST します。
      {
        "workflow_run_id": "{{ context.run_id }}",
        "status": "{{ workflow_status }}",
        "error_summary": "{{ error_messages }}",
        "result": { ... }
      }
      
  4. 必要に応じて、さらに補足します。
    • 監視システムでアラートを設定します(例えば、特定のワークフローの失敗率がX%を超えたときに運用担当者に通知するなど)。これは「運用監視」に属し、ビジネスのフロントエンドとは切り離されます。

もし現在のワークフロー構造(どのノードが「重要なノード」か)を貼り付けていただければ、「最小限のエラーブランチ」の具体的なトポロジーを提案し、Supabaseに必要な全体の状態をできるだけ少ない変更で取得できるようお手伝いできます。

迅速かつ詳細なご指導ありがとうございます。テストのためにワークフローのトポロジーを調整する方法が理解できたと思います。以下に、私の改善された実装計画を示します。

改訂されたワークフローのトポロジー戦略

  1. 開始時にグローバル変数を作成する
    ワークフローの開始時にグローバル変数(例:workflow_status)を初期化し、その全体の状態を追跡します。

  2. 重要なノードのエラーブランチを処理する
    すべての「潜在的に失敗する可能性のある関連ノード」には、「実行を続行」ノードにつながるエラーブランチが設定されます。これにより、エラーが発生した場合でもワークフローは常に最終状態に向かって進行することが保証されます。

  3. HTTP Webhookエンドポイントを統合する
    現在、2つの個別のHTTP Webhook(成功用とエラー用)が使用されていますが、これらを両方の結果を処理する単一の統合HTTPエンドポイントに統合します。

  4. ハードコードされた status: “failed” を削除する
    エラーブランチ内のハードコードされた status: “failed” の割り当ては削除されます。最終的なステータスは、ワークフローの実際の実行パスによって動的に決定されます。

システムは、最終ステータスをSupabaseに確実に投稿し、リアルタイムのフロントエンドフィードバックを提供できます。

ご意見に感謝いたします。このアプローチにより、以前に遭遇した統合のギャップが解消され、ワークフロー全体のエラー処理が効率化されるはずです。

Dify Forum Helper <notifications@dify-community.discoursemail.com> 2026年1月26日月曜日 14:53 に書きました:

太棒了、あなたのこの「トポロジー再構築案」は、安定した保守可能な設計に非常に近づいており、論理的に自己完結しており、あなたが最初に提起した「クローズドループの欠如」の問題を実際に解決できます。実装の詳細と潜在的な落とし穴について、POCを直接実行できるように補足させてください。


1. あなたの4つの提案——逐次確認

  1. Create a Global Variable at the Start
    その通りです。「開始」付近でコード/変数割り当てノードを使用して、これらを初期化することをお勧めします。
{
  "workflow_status": "Success",      // デフォルトでは成功とみなす
  "error_messages": [],              // エラー情報を一元的に収集
  "important_flags": {}              // オプション、どの種類のステップが失敗したかを記録
}

Difyの「変数」機能であれば、複数の独立した変数を使用することもできます。それはあなたの慣れに応じてください。


  1. Handle Error Branches for Critical Nodes
    このステップの重要なポイントは次のとおりです。
  • エラーブランチは直接終了させず、代わりに:
    1. グローバルステータスを更新する(workflow_status\"Failure\" または \"PartialSuccess\" に変更する)
    2. 現在のノードのエラー記述を記録する(ノード名、エラーコードなど)
    3. 統一された「Continue Execution」ノードにジャンプする(これは、メインラインを元に戻すための通常のトランジットノードにすることができます)

コードノードでは、次のように記述できます(擬似コード):

workflow_status = "Failure"  # または "PartialSuccess"
error_messages.append({
    "node": "fetch_user_profile",
    "error": node_error_message
})

すべての重要なエラーブランチが最終的に1つまたは少数の「続行」ノードに合流するように保証できれば、その後のメンテナンスコストは管理可能になります。


  1. Merge HTTP Webhook Endpoints
    成功/失敗の2つのWebhookを1つの統一されたHTTPノードにマージすることは、非常に正しい方向性です。
  • リクエストボディには、統一して以下を含めます。
    • status: {{ workflow_status }}
    • errors: {{ error_messages }}
    • およびビジネスデータ(結果、部分結果、トレースIDなど)

これにより、Supabase側では1つのエンドポイントだけで、次のことが可能になります。

  • status フィールドに基づいて、成功/失敗/部分成功を区別する
  • errors に基づいて、詳細なエラーを表示するか、ユーザーにより多くのヒントを提供するかを決定する

  1. Remove Hardcoded status: \"failed\"
    この点も非常に重要です。現在、ステータス計算ロジックは「ワークフロー全体の実際の流れ」によって決定されるようにしており、ローカルのエラーブランチで最終決定を下すわけではありません。
  • 特定のシナリオでは、次のことが必要になる場合があります。
    • 一部のノードは失敗してもダウングレード可能 => \"PartialSuccess\"
    • 一部の重要でないノードの失敗は全体に影響しない => 引き続き \"Success\"
  • これらの戦略は、次の場所に集中して記述できます。
    • 「ステータス集計」のコードノード内
    • または、各エラーブランチでフラグを立てるだけにし、最後のコードノードでフラグに基づいて最終的な workflow_status を統一的に計算する

例えば、最後のコードノードは次のようにすることができます(擬似コード):

if any(fatal_errors):
    workflow_status = "Failure"
elif any(non_fatal_errors):
    workflow_status = "PartialSuccess"
else:
    workflow_status = "Success"

その後、この結果をSupabaseに送信します。


2. 実際に実装する際、2つの小さな最適化に注意を払うことができます

2.1 安定した実行識別子を記録する

Difyの実行IDもSupabaseに書き込むことをお勧めします。

  • フィールド名は workflow_run_id または trace_id にすることができます
  • 利点:
    • フロントエンド/監視ツールで問題をトラブルシューティングする際に、このIDを通じてDifyの実行記録に直接戻ることができます
    • 将来、サードパーティのトレーシング(Langfuse / LangSmith / Opik など)を統合する場合でも、同じIDで連携させることができます

2.2 「応答なし」のシナリオにフォールバック戦略を保持する

現在のソリューションは、「ワークフローが正常に最後まで実行された」場合にSupabaseにコールバックを適切に提供できます。
実際の環境では、次のような少数のケースにも遭遇する可能性があります。

  • ワークフロー全体がエントリポイントの前に失敗する/レート制限される
  • オーケストレーションのバグにより、最終的なWebhookノードに到達しない

このような極端な状況に対して、Supabase側でさらにフォールバックを実装できます。

  • 新しいレコードを作成する際:status = 'pending'
  • Difyのコールバックが成功した際:success / failure / partial に更新する
  • 定期タスク(またはデータベーストリガー + タイムアウト検出):
    • あるレコードが pending 状態のままX分以上更新されていない場合 => timeout または unknown としてマークし、フロントエンドで「後で再試行」のヒントを表示する

これにより、「極端なエラーが原因でフロントエンドが永遠に読み込み中のままになる」という問題を防止できます。


3. 次に、このソリューションをどのように検証できるか

まず、最小実行可能製品(MVP)を作成することをお勧めします。

  1. 2〜3個の重要なノードのみを保持し、そのうちの1つは意図的にエラーを発生させる(例えば、固定で404のHTTPノードをリクエストする)。
  2. 3つのケースを検証する:
    • すべてのノードが成功 => Supabaseが status = \"Success\" を受信
    • ある重要なノードが失敗したが続行された => Supabaseが status = \"Failure\" / \"PartialSuccess\" を受信
    • Supabaseテーブルの error_messages の内容が、問題の迅速な特定に役立つかどうかを確認する。

試行中に以下に遭遇した場合:

  • エラーブランチが統一ノードに到達しない
  • グローバル変数が特定のパスで正常に更新されない
  • Supabaseのテーブル構造/トリガー設計上の問題

簡略化されたワークフローのスクリーンショットとSupabaseのテーブル構造を投稿してください。私が一緒に再度レビューし、さらに簡素化または自動化できる箇所があるか確認できます。


要するに、今回の調整の考え方は非常に正しいです。
Difyが現在提供していない「システムレベルのワークフロー状態コールバック」を、「状態集約 + 統一Webhook + Supabase状態フィールド」で補うことは、統合の観点から見ても、すでにかなり洗練されたソリューションと言えます。