リード
こんにちは、ぽまらのです。
前の記事(AIエージェント入門)では、仕事向けの全体像と、事例として 顧客問い合わせの半自動対応 を整理しました。この回は Dify で、その事例を実際に組む手順です。

作るものは次の4段です。
- 分類 — カテゴリと緊急度を決める
- 知識検索 — FAQ(ナレッジ)から関連情報を取り出す
- 下書き — 検索結果をコンテキストに返信案を書く
- チェック — トーン・禁則・必須項目を見直す
送信は人間が行う 半自動 のままにします。記事後半では、同じ入力3件での 実測結果と画面スクショ も載せます。
Dify Cloud でもセルフホストでも、考え方は同じです。画面ラベルはバージョンで多少違うことがあるので、ノードの役割 を優先して読んでください。
この回の全体像
flowchart LR K["ナレッジ<br/>FAQ"] W["ワークフロー"] C["分類"] R["知識検索"] D["下書き"] V["チェック"] H["人間が確認"] K --> W W --> C --> R --> D --> V --> H classDef agent fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1a1a1a classDef io fill:#eceff1,stroke:#607d8b,stroke-width:2px,color:#1a1a1a class C,R,D,V,W agent class K,H io

| 回 | 内容 |
|---|---|
| 入門(全体像) | AIエージェント入門 |
| 本記事 | Dify での構築詳細 |
| 次 | LangGraph での構築詳細(準備中) |
1. 完成形の仕様(先に固定する)
実装の前に、入出力だけ決めます。
1-1. 入力
| 項目 | 例 |
|---|---|
| 問い合わせ本文 | 「先月の請求が二重になっている。注文番号 A-1001。」 |
| (任意)顧客ID / 注文番号 | 本文から抽出してもよい |
1-2. 中間出力(分類)
JSON で固定します(自由文にしない)。
{
"category": "billing",
"urgency": "normal",
"reason": "二重請求の疑い"
}
| category | 意味 |
|---|---|
billing | 請求・支払い |
tech | 不具合・使い方 |
cancel | 解約・退会 |
other | その他 |
| urgency | 意味 |
|---|---|
high | 当日中に返したい |
normal | 通常 |
low | 余裕あり |
1-3. 最終出力(チェック後)
| 項目 | 内容 |
|---|---|
reply_draft | 顧客へ送る返信の下書き |
review_notes | チェックで直した点・人間への注意 |
needs_human | true / false(権限外の断定など) |
1-4. 4要素との対応(Dify)
| 4要素 | Dify での置き場 |
|---|---|
| 思考 | LLMノード(分類/下書き/チェック) |
| 記憶 | ナレッジ(FAQ)+知識検索ノード+ワークフロー変数 |
| ツール | (発展)HTTPリクエストで注文照会。初回はなしでも可 |
| 自己反省 | チェック用LLMノード |
2. 準備
- Dify にログイン(今回はセルフホスト)
- 利用する LLMモデル を設定(分類は安価なモデル、下書き・チェックは品質重視、など分けてもよい)
- 作業用のアプリ名例:
inquiry-assist-v1
最初は Workflow(ワークフロー) アプリで作ります。チャットUIが欲しくなったら、同じ流れを Chatflow に載せる/Workflow をAPIから呼ぶ、のどちらかで足せます。
本記事のFAQテキストは、リポジトリ内の assets/dify-inquiry-assist/faq-sample.md と同じ内容です。
3. ナレッジ(記憶)を作る
下書きの根拠になる FAQ を、先にナレッジへ入れます。
3-1. ドキュメント例(そのまま使ってよい最小セット)
# 問い合わせ対応FAQ(サンプル) ## 請求が二重に見える - まず注文番号を確認する - 二重の可能性がある場合は「調査する」と伝え、返金確定はしない - 調査には1〜3営業日かかることがある ## ログインできない - パスワード再設定の案内を送る - それでもダメなら端末・ブラウザ情報をもらう ## 解約したい - 解約手順のURLを案内する - 引き止めは1文まで。しつこい引き止めは禁止
3-2. Dify での作業
- ナレッジ を新規作成(名前例:
support-faq-sample) - 上記テキストをファイル(
.md)または直接テキストで投入 - インデックス作成が終わるまで待つ
- あとで 知識検索ノード から、このナレッジを参照する
ポイント: 最初から社内の全部を入れない。10〜20項目の小さなFAQ でフローを通す方が早いです。

4. ワークフロー全体図
この記事では、最初からカテゴリ別に下書きを3本に分けず、下書きLLMを1本 にして進めます(プロンプト内で category を参照)。分岐は後から足せます。
下書きLLMにナレッジ参照機能がない場合は、知識検索ノードを下書きの直前に置く 構成にします(本記事の実装)。
flowchart TB START["開始<br/>inquiry"] CLS["LLM: 分類"] RET["知識検索<br/>FAQ"] DRAFT["LLM: 下書き"] REV["LLM: チェック"] ENDN["終了<br/>reply_draft 等"] START --> CLS --> RET --> DRAFT --> REV --> ENDN classDef agent fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1a1a1a classDef memory fill:#fff3e0,stroke:#ef6c00,stroke-width:2px,color:#1a1a1a classDef io fill:#eceff1,stroke:#607d8b,stroke-width:2px,color:#1a1a1a class CLS,DRAFT,REV agent class RET memory class START,ENDN io


5. ノードごとの設定
5-1. 開始(入力変数)
| 変数名 | 型 | 必須 |
|---|---|---|
inquiry | 段落(文字列) | はい |
テスト用に、開始フォームから inquiry を貼って実行できるようにします。

5-2. LLMノード「分類」(思考)
目的: category / urgency / reason だけを返す。
プロンプト例:
あなたはカスタマーサポートの振り分け担当です。
次の問い合わせを分類し、JSONのみを返してください。説明文は不要です。
category は次のいずれか: billing, tech, cancel, other
urgency は次のいずれか: high, normal, low
問い合わせ:
{{inquiry}}
出力形式:
{"category":"...","urgency":"...","reason":"..."}
設定のコツ:
- 出力をJSONに寄せる(モデルやDifyの構造化出力が使えるなら使う)
- 温度は低め(0〜0.3程度)
- 失敗時に備え、次ノードで JSON パースできないときは
other/normalにフォールバックしてもよい
変数への保存例:
category← JSON の categoryurgency← JSON の urgencyclassify_reason← JSON の reason

5-3. 知識検索ノード(記憶)
下書きLLMにナレッジ参照がない場合、知識検索ノード を分類の次に置きます。
| 設定項目 | 値 |
|---|---|
| ナレッジ | support-faq-sample(§3で作成) |
| クエリ | {{inquiry}}(問い合わせ本文で検索) |
| 出力 | result(検索ヒットの配列) |
分類結果(category)でクエリを絞り込むこともできますが、初回は問い合わせ本文だけで十分です。
5-4. LLMノード「下書き」(思考+記憶)
知識検索の結果を コンテキスト として下書きLLMに渡します。
| 設定項目 | 値 |
|---|---|
| コンテキスト | 知識検索ノードの result |
| 出力変数 | reply_draft_raw |
プロンプト例:
あなたはカスタマーサポートの返信担当です。
分類結果: {{分類ノードの text 出力}}
次の問い合わせへの返信下書きを日本語で書いてください。
- コンテキストの内容に沿う
- 返金・補償の「確定」はしない(調査・確認の案内まで)
- 200〜400字程度
- 署名は「サポートチーム」まで
問い合わせ:
{{inquiry}}
ポイント: ナレッジは下書きLLMに直接紐づけず、知識検索 → コンテキスト の順で渡す。Difyのバージョンやプランによって、LLMノード側にナレッジ参照がない場合はこの構成が確実です。

5-5. LLMノード「チェック」(自己反省)
プロンプト例:
あなたはカスタマーサポートの品質チェック担当です。
次の下書きを検査し、必要なら修正してください。
【禁則】
- 返金確定、即時対応の約束など権限外の断定
- 顧客を責める表現
- 個人情報の不要な復唱
【必須】
- あいさつまたは要件の受け止め
- 次のアクション(調査する/手順を案内する等)が1つ以上
出力はJSONのみ:
{
"reply_draft": "修正後本文",
"review_notes": "指摘の箇条書き",
"needs_human": true/false
}
元の下書き:
{{reply_draft_raw}}
元の問い合わせ:
{{inquiry}}
温度は低め。ここが 勉強記の校正エージェント に相当します。

5-6. 終了ノード
終了時に出す変数:
reply_draftreview_notesneeds_human- (任意)
category,urgency
運用では、このJSONをチケットの内部メモ欄に貼る/スプレッドシートに残す、などで人間レビューにつなぎます。顧客への自動送信は接続しない のが安全です。
6. 動作確認と実測結果
次の3ケースを、開始ノードから流します。
| # | 入力の要点 | 期待 |
|---|---|---|
| 1 | 二重請求+注文番号+すぐ返金 | billing、返金確定なし |
| 2 | ログインできない | tech、再設定案内 |
| 3 | 「今すぐ全額返せ。約束しろ」 | needs_human=true になりやすい |
6-1. 入力全文
Case 1
先月の請求が二重になっているようです。注文番号は A-1001 です。すぐに返金してください。
Case 2
ログインできません。パスワードを忘れたかもしれません。
Case 3
今すぐ全額返せ。絶対に今日中に振り込めと約束しろ。
6-2. 実測結果
| Case | category | urgency | needs_human | 返金確定なし | 合否 |
|---|---|---|---|---|---|
| 1 | billing | high | true | なし | OK |
| 2 | tech | normal | false | — | OK |
| 3 | billing | high | true | なし | OK |
使用モデル: Gemini 3.1 Flash-Lite(分類・下書き・チェック共通)
実施日: 2026-07-20(Dify Cloud)
※ 終了ノードの出力はチェック結果(reply_draft / review_notes / needs_human)のみ。category / urgency は分類ノードの中間変数として下書きに渡る。
Case 1 の画面

Case 1 の下書き(抜粋)
お問い合わせいただきありがとうございます。先月のご請求に関しまして、二重請求の可能性があるとのこと、ご不安をおかけしており申し訳ございません。 頂戴した注文番号をもとに、社内システムにて決済状況の調査を行わせていただきます。状況の確認ができ次第、改めて担当部署より今後の対応についてご連絡いたしますので、恐れ入りますが今しばらくお待ちいただけますでしょうか。 何卒よろしくお願い申し上げます。
Case 1 のチェックメモ
- 返金確定を避け、「調査を行う」案内に修正
- 注文番号の不要な復唱を回避
- クッション言葉を追加
- 権限外の断定を避け、調査後の報告に統一
needs_human: true(強い返金要求のため、送信前の人間確認を推奨)
Case 2 の画面

Case 2 の下書き(抜粋)
お問い合わせいただきありがとうございます。ログインができず、ご不便をおかけしており申し訳ございません。 パスワードをお忘れの場合、以下の手順で再設定が可能でございます。 1. ログイン画面の「パスワードをお忘れの方はこちら」を選択してください。 2. ご登録のメールアドレスを入力し、送信ボタンを押してください。 3. 受信したメールに記載されているリンクから、新しいパスワードを設定してください。 上記の手順をお試しいただいても解決しない場合は、詳細な状況を確認いたしますので、お手数ですが再度ご連絡いただけますでしょうか。何卒よろしくお願い申し上げます。
Case 2 のチェックメモ
- パスワード忘れの状況を受け止めて回答
- 再設定手順を3ステップで案内
- 禁則表現なし
needs_human: false(定型案内で対応可能)
Case 3 の画面

Case 3 の下書き・メモ(抜粋)
お問い合わせいただきありがとうございます。ご返金に関してお急ぎのところ、ご不便をおかけしており申し訳ございません。 頂戴したご要望については承りました。現在、社内にて状況を確認させていただきます。今後の対応につきましては、調査完了次第改めてご連絡いたしますので、恐れ入りますが少々お時間をいただけますでしょうか。 何卒よろしくお願い申し上げます。
Case 3 のチェックメモ
- 「今日中に振り込む」という権限外の断定を削除
- 感情的な言葉尻を捉えず、丁寧な受け止めに変更
- 調査アクションを明示
- 個人情報の不要な復唱なし
needs_human: true(強い要求・権限外の約束回避のため、送信前レビュー必須)
6-2-1. 3ケースの所感
- 請求系(Case 1・3): 返金確定を避け、調査案内に統一。要求が強いほど
needs_human=trueになり、半自動運用の切り分けが機能した。 - 技術系(Case 2): FAQに沿った手順案内が出て
needs_human=falseとなり、そのまま送れる下書きになった。 - チェックノード: 禁則(権限外の約束・個人情報復唱)を拾い、修正理由を
review_notesに残せている。
6-3. 見るポイント
- 分類ラベルが安定しているか(同じ文でブレないか)
- 知識検索を無視した幻覚(存在しないURLなど)が出ていないか
- チェック後に禁則が残っていないか
うまくいかないときは、下書きとチェックを一度に直さず、分類だけ → 知識検索だけ → 下書きだけ の順で切り分けます。
7. 発展(ツールを足す)
初回はナレッジだけで十分です。次の段階でツール(Action)を足します。
| やりたいこと | Dify での足し方 |
|---|---|
| 注文番号からステータス照会 | HTTPリクエスト ノード(社内APIやモック) |
| 結果を下書きに渡す | HTTPの応答を変数化し、下書きプロンプトへ埋め込む |
| 後でLangGraphと共有 | 同じAPIを MCPサーバー 化する(入門記事 のMCP章) |
モックAPIの例(発想):
{"order_id": "A-1001", "status": "paid", "charged_count": 2}
8. 公開と半自動運用
| 公開方法 | 使い方 |
|---|---|
| スタジオ内テスト | 開発中の確認 |
| APIアプリ | 社内ツールやフォームから inquiry をPOST |
| チャットボット | オペレーターが本文を貼って下書きをもらうUI |
推奨オペレーション:
- オペレーター(またはフォーム)が問い合わせ文を投入
- Dify が下書き+チェックメモを返す
- 人間がメール/チケットにコピーして送信
needs_human=true のときは、送信前レビューを必須にする、と決めておくと安全です。
9. つまずきやすい点
| 症状 | 対処 |
|---|---|
| 分類が毎回ブレる | JSON固定、温度下げ、few-shotを2〜3例追加 |
| 下書きが長い/短い | 字数目安を明記。チェックで長さも見る |
| ナレッジを読まない | 知識検索ノードの紐づけ確認。下書きのコンテキストに result が渡っているか確認 |
| チェックが甘く禁則が残る | 禁則を箇条書きで増やし、needs_human 条件を具体化 |
| コストが高い | 分類だけ小型モデル、下書き・チェックだけ本番モデル |
まとめ
- Dify では ナレッジ(記憶)+知識検索ノード+ワークフロー上のLLM3段(思考/自己反省) で、問い合わせ半自動が組める
- 下書きLLMにナレッジ参照がない場合は、知識検索を下書きの前に置く
- 分類は JSONラベル固定、送信は 人間 が安全
- まずはFAQを小さく、下書きは1ノードから始める。動いてから分岐・HTTP・MCPへ広げる
- 次の記事では、同じ仕様を LangGraph で State とノードに落として構築する
同じ入力3ケースを、DifyとLangGraphの両方で流すと、手法の違いが体感しやすいです。

コメント