Agent工具调用陷入死循环:明确工具定义、最大迭代次数、后备设计
简介
Dify 的 Agent 一遍又一遍地调用同一个工具,或者陷入“信息未找到→再次搜索→再次未找到”的循环——这个问题不仅浪费代币成本,而且严重降低了用户体验。
乍一看,Agent的无限循环似乎是由于模型不智能造成的,但实际上,这主要是系统设计问题。 Dify的官方文档明确指出,Maximum Iterations设置存在于Agent节点上,并且可以通过环境变量MAX_ITERATIONS_NUM来设置平台级别的上限。也就是说,通过适当设计以下三个要素可以显着缓解这个问题:平台上限设置+工具定义质量+提示退出条件。
症状
| 症状 | 里面发生了什么 |
|---|---|
| 同一工具连续调用 5 次或以上 | 工具返回值无法正确解释 |
| 特工一直说“我会再调查一下” | 提示 |
| 使用不同的参数重复使用相同的工具 | 使用该工具的条件不明确,您尝试通过更改参数来解决它们 |
| 需要几分钟才能得到回复 | 迭代次数没有上限,一直运行到达到成本限制 |
| 答案止于“验证工具结果…” | 该工具返回错误,但代理无法理解该错误 |
原因分析
了解代理决策循环
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
当“你能回答吗?”时会发生无限循环。步骤始终返回“否”。
原因 1:工具定义(描述)不明确
工具描述是模型确定何时使用该工具以及期望什么的最重要输入。
坏例子:
tool:
name: search_database
description: "データベースを検索します"
该定义不清楚:
- 它是什么样的数据库?
- 它支持什么类型的查询?
- 如果没有找到结果怎么办?
- 结果将以什么格式返回?
好例子:
tool:
name: search_employee_database
description: |
社員情報データベースを検索します。
入力: 社員名(姓名)または社員番号
出力: 社員名、部署、内線番号、メールアドレスを含むJSON
制約:
- 部分一致検索に対応
- 結果が見つからない場合は空の配列 [] を返す
- 一度に最大10件まで返す
注意: 退職者の情報は含まれません
原因 2:工具的错误处理不足
当工具返回错误或结果为空时,代理通常会将其解释为“重试可能会更改结果”。
ループの例:
1. Agent: search_database("田中太郎") → 結果なし
2. Agent: "もう少し調べてみます"
3. Agent: search_database("田中 太郎") → 結果なし
4. Agent: "別の方法で検索します"
5. Agent: search_database("タナカタロウ") → 結果なし
6. Agent: "さらに調べます..." → 以後繰り返し
原因 3:未设置最大迭代次数
Dify的Agent节点有一个Maximum Iterations参数,但是如果默认值限制不够,就会导致成本膨胀然后停止。
| 设置 | 价值 | 描述 |
|---|---|---|
| 代理节点的最大迭代次数 | 默认值 | 每节点迭代限制 |
MAX_ITERATIONS_NUM 环境变量 | 平台层面 | 适用于所有代理的全局上限 |
###原因4:提示没有退出条件
很多系统提示只提供“回答用户问题”的正面指示,而没有明确何时放弃。
典型问题提示:
あなたは社内ヘルプデスクアシスタントです。
ユーザーの質問に対して、利用可能なツールを活用して
正確な回答を提供してください。
仅凭这条指令,代理就会优先考虑“提供准确的答案”,并继续尝试,即使找不到答案也不会放弃。
###原因5:工具之间的角色划分不明确
当多个工具具有相似的功能时,代理可能无法决定使用哪一个,并进入交替调用它们的循环。
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:适当设置最大迭代次数
代理节点级别:
在 Dify 的 Workflow 编辑器中选择 Agent 节点并设置 Maximum Iterations。
| 使用案例 | 建议的迭代次数 | 原因 |
|---|---|---|
| 简单的信息搜索(常见问题解答) | 3-5 | 3-5 1-2 次搜索就足够了 |
| 复杂的任务(调查/分析) | 5 至 8 | 需要多种工具的组合 |
| 多步骤加工 | 8 至 12 | 假设逐步处理 |
| 最多也不过如此 | 15 | 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:设计后备路径
如果代理陷入困境,请设计一个渐进的后备方案。
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[人間への引き継ぎメッセージ]
工作流程中的实现: 在Agent节点后面放置一个IF/ELSE节点,如果Agent输出包含“Not Found”,则分支到知识库直接搜索节点,如果仍然没有结果,则分支到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日志。
检查要点:
| 检查项目 | 评判标准 |
|---|---|
| 重复调用的工具 | 工具定义需要改进 |
| 每次的参数都一样吗? | 如果它们相同,则模型不会解释结果 |
| 思想内容 | “我会进一步调查”→退出条件不充分 |
| 当达到最大迭代次数时是否会停止? | 如果没有达到,有可能是没有设置上限 |
从 Dify 控制台的“日志和注释”选项卡中,选择有问题的对话,并循环浏览每次迭代的想法/操作/观察,以确定循环的起点。
注意事项
1. 代理设计清单
构建新代理时请确保以下事项:
- 是否设置了最大迭代次数(建议:5-10)?
- 每个工具的描述是否指定了没有结果时的行为?
- 系统提示符是否包含退出条件?
- 多种工具的角色界限是否清晰?
- 是否设计了后备路径(移交至人工等)?
- 该工具的错误响应是否采用代理可以理解的格式?
2. 测试场景
上线前,请务必测试以下“故障场景”:
| 测试案例 | 预期行为 |
|---|---|
| 搜索不存在的员工姓名 | 2次内回答“未找到” |
| 知识库中没有的问题 | 3次内回退消息 |
| 如果该工具返回错误 | 提供带有错误消息的替代方案 |
| 超出范围的问题 | 指导范围外无需调用工具 |
| 模棱两可的问题 | 一次搜索后要求用户确认 |
3.成本监控
代理的无限循环直接体现在代币成本上。
# 環境変数でコスト関連の上限を設定
MAX_ITERATIONS_NUM=15 # イテレーション上限
WORKFLOW_MAX_EXECUTION_TIME=300 # 5分でタイムアウト
监控指标:
| 指标 | 警告阈值 | 回应 |
|---|---|---|
| 每个对话的平均迭代次数 | 超过 5 | 工具定义/及时审查 |
| 每次对话的令牌消耗 | 超过 10,000 | 代理设计评审 |
| 连续调用同一工具的次数 | 超过3次 | 加强退出条件 |
| 最大迭代达成率 | 超过 10% | 审查上限及退出条件 |
4. 代理逐渐复杂化
与其从一开始就拥有所有工具,不如分阶段添加工具:阶段1(仅知识库搜索)→阶段2(+员工搜索)→阶段3(+系统状态确认)→阶段4(+预订/申请系统),并验证每个阶段的退出条件和路由。
总结
Agent死循环的根本原因不是模型效率低下,而是系统不知道什么时候停止。通过同时设计以下三个要素可以实现有效的对策:
- 平台上限:用
Maximum Iterations和MAX_ITERATIONS_NUM设置物理停止条件 - 工具定义的澄清:在每个工具的描述中指定目的、输入/输出、限制以及结果为空时的行为。
- 提示退出条件:在系统提示中包含明确的规则,例如“多次尝试无结果则停止”和“不要使用相同的参数再次调用相同的工具”。
如果缺少这三个要素中的任何一个,就会存在无限循环的风险。 Agent 的设计不仅要考虑“它能做什么”,还要考虑“何时放弃”。
参考资料
-エージェント | Dify Docs(日本語) -Agent | Dify Legacy Docs -Environment Variables - Dify Docs -ReAct エージェントの基本構造と「思考・行動・観察」ループ | note.com