
この記事はNovasell Advent Calendar 2025の15日目の記事です。
目次
- 目次
- はじめに
- 本記事の対象読者
- Level 1:ワークフローをツールとして公開し、Agentから利用する
- Level 2:HTTPノードで外部API呼び出し
- Level 3:Console APIで「無双」する
- まとめ
- 参考リンク
はじめに
Novasellで主にAIプロダクトの設計・開発を行っている浅田です。今回は、私たちのチームでも積極的に活用しているDifyの応用テクニックについてお話しします。
Difyは、LLMアプリケーションをノーコード/ローコードで構築できるプラットフォームです。 RAGチャットボットやAIエージェントをGUIで手軽に作れるため、非常に人気があります(自分も最初はそのあまりの簡単さに感嘆した覚えがあります)。 dify.ai
しかし、実際の業務で活用しようとすると、さまざまな課題にぶつかることがあります。
例えば:
- 調査用Agentを作る際、メインのLLMはClaude Opus 4.5を使いつつ、X上のユーザーの声も収集したい。しかし、grokはあくまで1つのモデルなので、デフォルトではツールとして呼び出せない。
- 複数のアプリで同じような処理を重複して管理しており、メンテナンスがつらい。
- アプリケーションごとのLLMコストを把握したいが、Difyではアプリ別にAPIキーを設定できないため、各アプリのコストを目視でチェックする必要がある。
本記事では、こうしたDifyの「痒いところ」を解決するテクニックを紹介します。 以下では3つのLevelに分けて解説していきます。 この3つのテクニックを使いこなせば、Difyの無限の可能性を引き出せるはずです。
なお、ここで紹介するテクニックはすべてDify上で完結します。したがって、エンジニアに限らず誰でも実践できます。
本記事の対象読者
- Difyで基本的なチャットボットやワークフローを構築した経験がある方
- 「動くものは作れたけど、もっと複雑なことがしたい」と感じている方
- Difyを本番運用する上での管理・監視に課題を感じている方
Level 1:ワークフローをツールとして公開し、Agentから利用する
こんなときに使う
「調査用Agentを作っている。メインのモデルはClaude Opus 4を使いたいけど、ツールとしてgrokを呼び出したい」
「画像生成Agentを作っている。メインのモデルはClaude Opus 4を使いたいけど、ツールとしてNano Banana Proを呼び出したい」
「カスタムツールをすばやく公開して、Agentから利用できるようにしたい」
grokやNano Banana Proは1つのモデルであり、デフォルトではツールとして利用できません。こうした特定のモデルを別のAgentからツールとして呼び出したい、あるいはカスタムツールを公開してAgentに利用させたい、というニーズがあります。
こうしたケースで威力を発揮するのが、ワークフローのツール化機能です。
何ができるのか
Difyでは、作成したワークフローを「ツール」として公開し、別のAgentから呼び出すことができます。これにより、以下のような構成が可能になります。
[Agent (Claude Opus 4)]
├── ツール: 画像生成ワークフロー(内部でNano Banana Pro使用)
├── ツール: X Researchワークフロー(内部でgrok使用)
└── ツール: ...
設定手順
Step 1: ワークフローを作成・公開する
まず、ツール化したいワークフローを通常通り作成します。開始ノードで入力変数を定義し、終了ノードで出力を返す構成にしておきます。
完成したら、右上の「公開する」ボタンからワークフローを公開します(以下はgrokのツール化の例です)。

Step 2: 「Workflow as Tool」を設定する
公開メニュー内の「ワークフローをツールとして公開する」オプションを選択し、

以下を設定します。
| 設定項目 | 説明 |
|---|---|
| ツールコールの名前 | Agentがツールを識別するための名前。機能を端的に表す命名を |
| ツールの説明 | LLMがツールの使用タイミングを判断するための重要な情報 |
| ツール入力 | ワークフローに渡す入力パラメータの説明 |

ポイント: ツールの説明やツール入力の説明は、Agentが「いつ、どのようにこのツールを使うべきか」を判断する材料になります。ここをしっかり書くことで、Agentが適切なタイミングでツールを実行できるようになります。可能な限り詳細かつ明確に記載しましょう。
Step 3: Agentから呼び出す
新規Agentを作成し、Toolsセクションで「Workflow」タブから公開済みのワークフローを追加します。

実践Tips
💡 ワークフローの粒度を意識する
ツール化するワークフローは、「単一責務」になるよう設計しましょう。複数の責務を持たせると、Agentが適切なタイミングで呼び出せなくなります。
💡 Chatflowはツール化できない
ツールとして公開できるのは「Workflow」タイプのみです。「Chatflow」はツール化できないので、注意してください。
Level 2:HTTPノードで外部API呼び出し
こんなときに使う
例1: 共通処理の重複管理問題
A・B・Cという3つのワークフローがあり、それぞれに「ドキュメントを解析 → RAG検索 → 結果を要約」という一連の処理が含まれているとします。
[Workflow A] ─ ドキュメント解析 → RAG検索 → 要約生成 ─ ... [Workflow B] ─ ドキュメント解析 → RAG検索 → 要約生成 ─ ... [Workflow C] ─ ドキュメント解析 → RAG検索 → 要約生成 ─ ...
この状態で「要約生成のロジックを変更したい」となった場合、A・B・Cすべてを修正しなければなりません。修正漏れのリスクもあります。
例2: Agentノードの制約回避
ワークフロー内でAgent的な処理をしたい場合、Difyには「Agentノード」がありますが、いくつかの制約があります。例えば、画像を入力として渡せないといった制限です。このように、Agentアプリではできるのに、Agentノードだとできないことがあります。
まとめ: どちらのケースも、HTTPノードで別のDifyアプリをAPI経由で呼び出すことで解決できます。共通処理はワークフローとして、Agent的な処理はAgentアプリとして切り出し、必要な箇所からHTTPで呼び出すパターンです。
設定手順
※以下はAgentを切り出すパターンです。
Step 1: 呼び出される側のAgentを作成・公開する
まず、呼び出したい処理をAgentアプリとして作成し、公開します。 そのうえで、APIアクセス用のAPIキーを発行しておきます。

Step 2: HTTPノードを設定する
呼び出す側のワークフローにHTTPノードを追加し、以下のように設定します。
| 設定項目 | 値 |
|---|---|
| Method | POST |
| URL | https://api.dify.ai/v1/chat-messages(またはセルフホスト環境のURL) |
| Headers | Authorization: Bearer {api_key}, Content-Type: application/json |
| Body | JSON形式でクエリや入力変数を指定 |
重要: Agentを呼び出す場合、response_modeには必ずstreamingを指定してください。blockingではAgentモードが動作しません。

Step 3: レスポンスを処理する
streamingモードのレスポンスは、Server-Sent Events(SSE)形式で返ってきます。そのままでは使いづらいため、Codeノードでパースする処理を入れます。
ストリーミングレスポンスはdata: {...}という形式のチャンクが連続して送られてくるため、これを結合して最終的な回答を抽出するロジックが必要です。
import json def main(output: str) -> dict: # Split the body into lines lines = output.strip().split("\n") last_thought = None # Look for all agent_thought events for line in lines: if line.startswith("data: "): data_str = line[6:] # Remove "data: " prefix try: event_data = json.loads(data_str) if event_data.get("event") == "agent_thought" and event_data.get("thought"): last_thought = event_data.get("thought") except json.JSONDecodeError: continue return { "result": last_thought }
実践Tips
💡 タイムアウト設定に注意
HTTPノードのデフォルトタイムアウトは60秒です。複雑なAgent処理を呼び出す場合、これでは足りないことがあります。セルフホスト環境では、環境変数で調整可能です。
💡 画像を送りたい場合
画像データを送る場合、Base64エンコードして直接送るよりも、File Upload APIでいったんアップロードしてからファイルIDを参照する方式の方が安定します。
自分は以下のような手順でリクエストボディを構築しています。参考までに。
- ファイルアップロード
- ID抽出
- リクエスト構築

⚠️ エラーハンドリングを忘れずに
HTTPノードの後には、ステータスコードをチェックする条件分岐を入れておくことをお勧めします。
Level 3:Console APIで「無双」する
こんなときに使う
Difyを本格的に運用し始めると、UI上の操作だけでは限界を感じる場面が出てきます。
- Dify上のアプリケーションログを有効活用したい
- アプリごとのコストを1つのワークフローで集計したい
- ワークフローから動的にナレッジファイルを追加したい
こうした「運用・管理系」のニーズに応えるのが、Console APIです。
Service API と Console API の違い
Difyには2種類のAPIがあります。
| Service API | Console API | |
|---|---|---|
| 用途 | アプリの実行・利用 | アプリの管理・運用 |
| 認証 | アプリごとのAPIキー | ユーザーログイン(email/password) |
| 主な操作 | チャット送信、ワークフロー実行 | アプリ作成、ログ取得、コスト取得 |
| ドキュメント | 公式ドキュメントあり | 公式ドキュメントなし(ソースコード参照) |
認証の仕組み
Console APIは、まずログインしてアクセストークンを取得し、そのトークンを使って各種操作を行う方式です。
1. POST /console/api/login でログイン
→ access_tokenを取得
2. 各APIリクエストのヘッダーに
Authorization: Bearer {access_token} を付与
具体例:チャット履歴を取得する
実際のコード例を見てみましょう。以下は、Console APIを使って特定アプリのチャット履歴を取得し、Markdown形式に変換するスクリプトです。

import requests from typing import List, Dict, Any def main(conversation_data: str, dify_password: str, dify_email: str, target_app_id) -> str: base_url = "https://your-dify-instance.com/console/api" email = dify_email password = dify_password app_id = target_app_id limit = 100 conversation_id = conversation_data.get("id") base_url = base_url.rstrip('/') session = requests.Session() # ログイン login_url = f"{base_url}/login" response = session.post(login_url, json={ "email": email, "password": password }) response.raise_for_status() access_token = response.json()['data']['access_token'] # チャットメッセージ取得 messages_url = f"{base_url}/apps/{app_id}/chat-messages" headers = {'Authorization': f'Bearer {access_token}'} params = {'conversation_id': conversation_id, 'limit': limit} response = session.get(messages_url, headers=headers, params=params) response.raise_for_status() messages = response.json().get('data', []) # Markdown形式に変換 markdown = _convert_to_markdown(messages) return {"conversation": markdown} def _convert_to_markdown(messages: List[Dict[str, Any]]) -> str: lines = [] for msg in messages: query = msg.get('query', '').strip() answer = msg.get('answer', '').strip() if query: lines.append(f"Q: {query}\n") if answer: lines.append(f"A: {answer}\n") return '\n'.join(lines)
このコードのポイント:
- ログイン処理:
POST /console/api/loginでemail/passwordを送信し、access_tokenを取得 - 認証ヘッダー: 取得したトークンを
Authorization: Bearer {token}として付与 - データ取得:
GET /console/api/apps/{app_id}/chat-messagesでチャット履歴を取得
このスクリプトをDifyのCodeノードに配置すれば、ワークフロー内から別アプリの利用状況を集計する、といった処理が可能になります。
Console APIを活用することで、ログ取得以外にも、コストの取得、ナレッジの追加、設定ファイルのダウンロードなどが可能になります。用途に合わせて上記のコードを応用してみてください。
注意点
⚠️ 公式サポートではない
Console APIは公式ドキュメントに記載されておらず、バージョンアップで仕様が変わる可能性があります。本番運用で使う場合は、この点を理解したうえで利用してください。
⚠️ Cloud版での利用
Dify Cloud(SaaS版)でもConsole APIは存在しますが、一部機能が制限されている可能性があります。セルフホスト環境の方がフル機能を利用できます。
💡 エンドポイントの探し方
Console APIのエンドポイントは、GitHubリポジトリのapi/controllers/console/配下を見ると把握できます。また、ブラウザの開発者ツールでDifyのUIを操作しながらネットワークタブを確認すると、実際に呼ばれているAPIがわかります。
参考: https://github.com/langgenius/dify/tree/main/api/controllers/console
まとめ
本記事では、Difyの応用的な使い方を3つのレベルに分けて紹介しました。
| Level | テクニック | 解決できる課題 |
|---|---|---|
| 1 | ワークフローのツール化 | 複数モデルの使い分け、処理のモジュール化 |
| 2 | HTTPノードでのAPI呼び出し | Agentノードの制約回避、共通処理の切り出し |
| 3 | Console APIの活用 | 運用自動化、コスト管理、CI/CD |
RAGチャットボットを作れるようになったら、ぜひこれらのテクニックを使って、より実践的なAIアプリケーションに挑戦してみてください。