Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Agent のツール呼び出しが無限ループに陥る:ツール定義の明確化・最大イテレーション数・フォールバック設計

はじめに

Dify の Agent が同じツールを何度も繰り返し呼び出す、あるいは「情報が見つからない → 再検索 → また見つからない」のループに入って止まらなくなる――この問題はトークンコストの浪費だけでなく、ユーザー体験を著しく損なう。

Agent の無限ループは一見「モデルが賢くない」ように見えるが、実際にはシステム設計の問題であることが大半だ。Dify の公式ドキュメントでは、Agent ノードに Maximum Iterations 設定が存在すること、環境変数 MAX_ITERATIONS_NUM でプラットフォームレベルの上限を設定できることが明示されている。つまり、この問題は「プラットフォームの上限設定 + ツール定義の品質 + プロンプトの退出条件」の三要素を適切に設計することで、大幅に軽減できる。


症状

症状内部で起きていること
同じツールが5回以上連続で呼び出されるツールの戻り値を正しく解釈できていない
Agent が「もう少し調べます」と言い続ける退出条件がプロンプトに定義されていない
異なるパラメータで同じツールを繰り返すツールの使用条件が曖昧で、パラメータ変更で解決しようとする
レスポンスが返るまで数分かかるイテレーション数の上限が未設定で、コスト制限に到達するまで実行される
回答が「ツールの結果を確認中です…」で止まるツールがエラーを返しているが、Agent がエラーを理解できていない

原因分析

Agent の意思決定ループを理解する

Dify の Agent(ReAct方式)は、以下のループを繰り返すことで問題を解決する。

flowchart TD
    A[ユーザーの質問] --> B[思考 Thought]
    B --> C{ツール呼び出しが必要?}
    C -->|Yes| D[行動 Action: ツール呼び出し]
    D --> E[観察 Observation: ツールの結果]
    E --> F{回答できる?}
    F -->|No| B
    F -->|Yes| G[最終回答 Final Answer]
    C -->|No| G

無限ループは、「回答できる?」のステップで常に「No」と判断される 場合に発生する。

原因1:ツール定義(Description)が曖昧

ツールの description はモデルがツールを「いつ使うか」「何を期待できるか」を判断する最も重要な入力である。

悪い例:

tool:
  name: search_database
  description: "データベースを検索します"

この定義では以下が不明:

  • どんなデータベースか
  • どんなクエリに対応しているか
  • 結果が見つからない場合はどうなるか
  • どんな形式で結果が返るか

良い例:

tool:
  name: search_employee_database
  description: |
    社員情報データベースを検索します。
    入力: 社員名(姓名)または社員番号
    出力: 社員名、部署、内線番号、メールアドレスを含むJSON
    制約: 
    - 部分一致検索に対応
    - 結果が見つからない場合は空の配列 [] を返す
    - 一度に最大10件まで返す
    注意: 退職者の情報は含まれません

原因2:ツールのエラーハンドリングが不十分

ツールがエラーを返した場合や結果が空の場合に、Agent がそれを「もう一度試せば結果が変わるかもしれない」と解釈するケースが多い。

ループの例:
1. Agent: search_database("田中太郎") → 結果なし
2. Agent: "もう少し調べてみます"
3. Agent: search_database("田中 太郎") → 結果なし
4. Agent: "別の方法で検索します"
5. Agent: search_database("タナカタロウ") → 結果なし
6. Agent: "さらに調べます..."  → 以後繰り返し

原因3:Maximum Iterations が未設定

Dify の Agent ノードには Maximum Iterations パラメータがあるが、デフォルト値が十分に制限的でない場合、コストが膨張してから初めて停止する。

設定説明
Agent ノードの Maximum Iterationsデフォルト値ノード単位のイテレーション上限
MAX_ITERATIONS_NUM 環境変数プラットフォームレベル全 Agent に適用されるグローバル上限

原因4:プロンプトに退出条件がない

多くのシステムプロンプトが「ユーザーの質問に答えてください」という前向きな指示だけで、「どういう場合に諦めるか」を明示していない。

典型的な問題のあるプロンプト:

あなたは社内ヘルプデスクアシスタントです。
ユーザーの質問に対して、利用可能なツールを活用して
正確な回答を提供してください。

この指示だけでは、Agent は「正確な回答を提供する」ことを最優先し、見つからない場合でも諦めずに試行を続ける。

原因5:ツール間の役割分担が不明確

複数のツールが似た機能を持つ場合、Agent がどちらを使うべきか判断できず、交互に呼び出すループに入ることがある。

1. Agent: search_knowledge_base("VPN設定方法") → 部分的な結果
2. Agent: search_faq("VPN設定方法") → 別の部分的な結果
3. Agent: "もう少し調べます"
4. Agent: search_knowledge_base("VPN 設定 手順") → 似た結果
5. Agent: search_faq("VPN接続できない") → 別の結果
6. → 繰り返し

解決策

解決策1:Maximum Iterations を適切に設定する

Agent ノードレベル:

Dify の Workflow エディタで Agent ノードを選択し、Maximum Iterations を設定する。

ユースケース推奨イテレーション数理由
単純な情報検索(FAQ応答)3〜51〜2回の検索で十分
複合的なタスク(調査・分析)5〜8複数ツールの組み合わせが必要
マルチステップ処理8〜12段階的な処理が前提
最大でもこれ以上は不要15これ以上はほぼ確実に無限ループ

プラットフォームレベル(セルフホスト環境):

# .env ファイル
MAX_ITERATIONS_NUM=15    # 全Agent共通の最大イテレーション数

解決策2:ツール定義を改善する

各ツールに以下の情報を含める:

tools:
  - name: search_employee
    description: |
      社員情報を検索します。
      
      【用途】社員の連絡先、所属部署を調べるとき
      【入力】社員名(姓または名)、または社員番号(E+数字5桁)
      【出力形式】
        - 見つかった場合: {"found": true, "employees": [...]}
        - 見つからなかった場合: {"found": false, "message": "該当なし"}
      【制限事項】
        - 退職者は検索対象外
        - 一度に10件まで
      【注意】結果が見つからなかった場合、パラメータを変えて
        再度呼び出しても結果は変わりません。
    parameters:
      query:
        type: string
        description: "社員名または社員番号"
        required: true

  - name: search_knowledge_base
    description: |
      社内ナレッジベースを検索します。
      
      【用途】社内規程、手順書、マニュアルの内容を調べるとき
      【入力】自然言語のクエリ(日本語)
      【出力形式】
        - 関連チャンクのリスト(最大5件、relevance_score付き)
        - 関連情報がない場合: 空リスト []
      【このツールで検索できないもの】
        - 社員の個人情報 → search_employee を使用
        - リアルタイムのシステム障害情報 → check_system_status を使用
      【注意】同じクエリで2回以上呼び出しても結果は同じです。
        結果が不十分な場合はクエリの表現を変えてください。

解決策3:システムプロンプトに退出条件を明記する

# System Prompt

あなたは株式会社ABCの社内ヘルプデスクAIアシスタントです。

## 基本ルール
- 利用可能なツールを活用して、ユーザーの質問に正確に回答してください
- 回答の根拠は必ずツールの検索結果に基づくこと

## 退出条件(重要)
以下の条件に該当する場合は、ツール呼び出しを停止し、
適切な回答を返してください:

1. **同じツールを2回呼び出しても有効な結果が得られない場合**
   → 「申し訳ございませんが、現在のナレッジベースにはこの質問に
      該当する情報が見つかりませんでした。IT部門(内線: 1234)に
      お問い合わせください。」

2. **ツールがエラーを返した場合**
   → エラー内容をユーザーに伝え、別の問い合わせ方法を案内してください

3. **ユーザーの質問が対応範囲外の場合**
   → 対応範囲外であることを伝え、適切な問い合わせ先を案内してください

4. **すでに十分な情報が得られている場合**
   → 追加のツール呼び出しは不要です。得られた情報で回答してください

## 禁止事項
- 同じツールを同じパラメータで2回以上呼び出さないこと
- 3回連続でツール呼び出しが空結果だった場合、それ以上の試行を行わないこと
- 「もう少し調べます」「別の方法で検索します」と言って呼び出しを続けないこと

解決策4:フォールバックパスを設計する

Agent が行き詰まった場合の段階的なフォールバックを設計する。

flowchart TD
    A[ユーザー質問] --> B[ツール呼び出し 1回目]
    B --> C{有効な結果?}
    C -->|Yes| D[回答生成]
    C -->|No| E[ツール呼び出し 2回目 クエリ変更]
    E --> F{有効な結果?}
    F -->|Yes| D
    F -->|No| G[フォールバック: ナレッジベース直接検索]
    G --> H{有効な結果?}
    H -->|Yes| I[ナレッジベースの情報で回答]
    H -->|No| J[人間への引き継ぎメッセージ]

Workflow での実装: Agent ノードの後に IF/ELSE ノードを配置し、Agent 出力に「見つかりませんでした」が含まれる場合はナレッジベース直接検索ノードへ、それでも結果がなければ人間引き継ぎ用の LLM ノードへ分岐させる。

解決策5:ツール間の役割境界を明確にする

## ツール使用ガイドライン(System Prompt に含める)

利用可能なツールと使い分け:

| 質問の種類 | 使用するツール | 使わないツール |
|-----------|--------------|--------------|
| 社員の連絡先・部署 | search_employee | search_knowledge_base |
| 社内規程・手順 | search_knowledge_base | search_employee |
| システム障害の状況 | check_system_status | search_knowledge_base |
| 会議室の予約状況 | check_room_availability | search_employee |

重要: 上記の対応表に従ってツールを選択してください。
対応表にないタイプの質問には、ツール呼び出しを行わず
「この種類のお問い合わせには対応しておりません」と回答してください。

解決策6:Agent ログによるデバッグ

無限ループが発生した場合、まず Agent のログを確認する。

確認すべきポイント:

確認項目判断基準
繰り返し呼ばれているツールツール定義の改善が必要
パラメータが毎回同じか同じならモデルが結果を解釈できていない
Thought の内容「もう少し調べます」→ 退出条件不足
Maximum Iterations 到達で停止か到達していなければ上限未設定の可能性

Dify コンソールの「ログと注釈」タブから、問題の会話を選択し、各イテレーションの Thought / Action / Observation を順に確認してループの開始点を特定する。


予防策

1. Agent 設計チェックリスト

新しい Agent を構築する際に以下を確認する:

  • Maximum Iterations が設定されているか(推奨: 5〜10)
  • 各ツールの description に「結果がない場合」の挙動が明記されているか
  • システムプロンプトに退出条件が含まれているか
  • 複数ツールの役割境界が明確か
  • フォールバックパス(人間への引き継ぎ等)が設計されているか
  • ツールのエラーレスポンスが Agent にとって理解可能な形式か

2. テストシナリオ

本番投入前に、以下の「失敗シナリオ」を必ずテストする:

テストケース期待する挙動
存在しない社員名で検索2回以内に「見つかりません」と回答
ナレッジベースにない質問3回以内にフォールバックメッセージ
ツールがエラーを返す場合エラーメッセージとともに代替案を提示
対応範囲外の質問ツール呼び出しなしで範囲外を案内
曖昧な質問1回の検索後、ユーザーに確認を求める

3. コスト監視

Agent の無限ループは直接的にトークンコストに反映される。

# 環境変数でコスト関連の上限を設定
MAX_ITERATIONS_NUM=15              # イテレーション上限
WORKFLOW_MAX_EXECUTION_TIME=300    # 5分でタイムアウト

監視すべき指標:

指標警告閾値対応
1会話あたりの平均イテレーション数5回超ツール定義・プロンプト見直し
1会話あたりのトークン消費量10,000超Agent の設計見直し
同一ツールの連続呼び出し回数3回超退出条件の強化
Maximum Iterations 到達率10%超上限値と退出条件の見直し

4. 段階的な Agent 複雑化

最初からすべてのツールを持たせず、Phase 1(ナレッジベース検索のみ)→ Phase 2(+ 社員検索)→ Phase 3(+ システム状態確認)→ Phase 4(+ 予約・申請系)と段階的にツールを追加し、各段階で退出条件とルーティングを検証する。


まとめ

Agent の無限ループは「モデルの能力不足」ではなく、「いつ停止すべきかをシステムが教えていない」ことが根本原因である。効果的な対策は以下の三要素を同時に設計することで実現できる:

  1. プラットフォーム上限Maximum IterationsMAX_ITERATIONS_NUM で物理的な停止条件を設定する
  2. ツール定義の明確化:各ツールの description に、用途・入出力・制限事項・結果が空の場合の挙動を明記する
  3. プロンプトの退出条件:「何回試しても結果がない場合は停止する」「同じツールを同じパラメータで再呼び出ししない」といった明示的なルールをシステムプロンプトに含める

これら三要素のうち一つでも欠けていると、無限ループのリスクは残り続ける。Agent の設計は「何ができるか」だけでなく、「いつ諦めるか」まで含めて完成となる。


参考資料