Agent 为何会陷入 Tool 调用死循环?
> 结论先行:Tool 调用死循环通常不是单点 bug,而是 Agent 控制闭环失稳。定位时不要只看最后一次输出,要看每一轮的状态、动作、观察、记忆和终止判断是否在推动任务前进。
## 1. 先把 Agent 看成一个闭环系统
Agent 不是普通的 `input -> output` 函数。它更接近一个带反馈的控制系统:
```mermaid
flowchart LR
G[Goal<br/>任务目标] --> S[State<br/>当前状态]
S --> P[Planner<br/>下一步决策]
P --> A[Action<br/>选择工具和参数]
A --> T[Tool<br/>执行外部操作]
T --> O[Observation<br/>工具返回]
O --> M[Memory / State Update<br/>写入事实和进度]
M --> E{Stop?}
E -- no --> S
E -- yes --> R[Final Answer / Done]
```
一次正常推进的 Agent run,有三个必要条件:
| 条件 | 含义 | 反例 |
|---|---|---|
| 状态在变化 | 每轮获得了新事实、新约束或新结论 | 同一个 search 结果反复出现 |
| 决策在收敛 | 动作越来越接近完成目标 | 一直换 query,但语义目标不变 |
| 终止可判定 | 系统知道什么叫完成、失败、卡住 | 只有“继续试试”,没有退出分支 |
所以,死循环的更准确表达是:
```text
Agent loop = 缺少有效进展判断 缺少退出/换策略机制
```
不是所有死循环都来自“信息不变”。有些场景里信息在变,但没有改变任务状态;也有些场景里工具持续失败,但控制器只会盲目重试。
## 2. 两种常见 Agent 模式里的循环点
视频里重点讲了两类构建模式:ReAct 和 Plan-And-Execute。它们都会调用工具,但循环风险不一样。
### ReAct:边想边做,容易局部打转
```mermaid
sequenceDiagram
participant U as User
participant L as LLM
participant T as Tool
U->>L: 目标
loop until done
L->>L: Thought
L->>T: Action(tool, args)
T-->>L: Observation
L->>L: 根据 Observation 决定下一步
end
L-->>U: Answer
```
ReAct 的优点是灵活,缺点是每一步都由当前上下文驱动。如果 Observation 模糊、历史过长或没有进展判定,它很容易进入:
```text
Thought: 我还需要更多信息
Action: search(...)
Observation: 一些相似结果
Thought: 我还需要更多信息
Action: search(...)
```
所以 ReAct Agent 的测试重点是:每轮 action 是否带来新的事实、是否减少不确定性、是否有明确停止条件。
### Plan-And-Execute:先计划再执行,容易计划失真
```mermaid
flowchart TD
U[User Goal] --> P[Planner<br/>生成步骤列表]
P --> E[Executor<br/>逐步执行]
E --> T[Tool]
T --> O[Observation]
O --> C{计划是否仍然有效?}
C -- yes --> E
C -- no --> R[Replan]
R --> E
```
Plan-And-Execute 的优点是结构清晰,缺点是计划可能和真实环境脱节。循环经常发生在两处:
| 位置 | 循环原因 | 例子 |
|---|---|---|
| Execute | 某一步无法完成,但 Executor 不会换策略 | 一直调用同一个失败工具 |
| Replan | 每次重新计划都生成同一套不可行步骤 | 计划 A 失败,再生成计划 A |
所以 Plan-And-Execute 的测试重点是:计划是否可验证、失败后是否真正改变策略、replan 是否产生了语义差异。
## 3. 死循环的三种典型形态
```mermaid
flowchart TB
L[Tool 调用死循环] --> A[重复同一动作]
L --> B[语义重复动作]
L --> C[失败后盲目重试]
A --> A1[same tool same args<br/>如 search('pricing') x 10]
B --> B1[same intent different wording<br/>如 pricing / price / cost 反复搜索]
C --> C1[same error no diagnosis<br/>如参数错误后继续原样调用]
```
最容易漏掉的是第二种:表面上每次 query 都不同,但语义上没有新方向。例如:
```text
search("A 公司 2024 revenue")
search("A company 2024 annual revenue")
search("A 公司 去年收入")
search("A company financial result")
```
这些不一定是错误。如果每次搜索带来新的可靠证据,它就是探索;如果 extracted facts 没变,它就是语义重复。
## 4. 六个故障层级
原文里把“死循环 = Planner 在信息不变时反复做相同决策”作为一句话总结,这个说法有用,但不完整。工程上建议按六层定位:
```mermaid
flowchart TD
G[Goal 层<br/>目标和完成条件] --> P[Planner 层<br/>计划和下一步选择]
P --> A[Action 层<br/>工具和参数]
A --> T[Tool 层<br/>契约和返回语义]
T --> M[Memory 层<br/>事实、历史、进度]
M --> C[Controller 层<br/>终止、重试、回退]
C --> G
```
| 层级 | 常见问题 | 可观测信号 | 修复方向 |
|---|---|---|---|
| Goal | 没定义完成条件 | Agent 不知道何时回答 | 把目标拆成可验收条件 |
| Planner | 没有进展感 | 一直选择同类动作 | 注入 state diff、已尝试动作、剩余缺口 |
| Action | 参数语义错误 | schema 合法但业务错误 | 参数预校验、语义校验、高风险确认 |
| Tool | 返回不可判定 | `pending`、空字符串、模糊成功 | 设计明确状态码和 next_action |
| Memory | 忘记已知事实 | 重复发现 A/B | 外部状态表、facts ledger、action history |
| Controller | 只会 retry | 同错同参重复失败 | retry budget、stuck detector、fallback |
这张表比“怀疑 Tool”或“怀疑 Prompt”更可靠,因为它把 Agent 拆成可观测组件。
## 5. 最常见的根因:进展无法被度量
Agent 不是必须每一步都成功,但必须能判断“这一步有没有让任务更接近完成”。
一个实用的进展模型:
```text
Progress =
new_facts
reduced_uncertainty
completed_subgoals
- repeated_actions
- unresolved_errors
```
这不是为了追求数学精确,而是为了让系统有判断依据。
```mermaid
flowchart LR
O[Observation] --> F[Extract facts]
F --> D[Compare with known facts]
D -->|new facts| U[Update state]
D -->|no new facts| N[No information gain]
N --> K{Repeated?}
K -->|yes| X[Stop / fallback / ask human]
K -->|no| Q[Try different strategy]
```
判断是否卡住,不能只看文本是否重复。更好的方式是看语义状态是否变化:
```json
{
"step": 5,
"goal": "找到 A 公司 2024 年收入并给出来源",
"action": {
"tool": "search",
"args": {"query": "A company 2024 annual revenue"}
},
"observation_hash": "9b1c...",
"extracted_facts": [
{"key": "revenue_2024", "value": "12.8B USD", "source": "annual_report"}
],
"new_facts_count": 0,
"repeated_action_score": 0.82,
"open_questions": [],
"answerable": true,
"decision": "stop_and_answer"
}
```
关键字段是 `new_facts_count`、`open_questions`、`answerable` 和 `repeated_action_score`。有了这些字段,循环检测才不是拍脑袋。
## 6. Tool 返回值必须是可判定契约
很多死循环来自工具返回设计太弱:
```python
# 不推荐:Agent 无法判断下一步
return "请求已提交,请稍后查看"
# 推荐:返回可执行语义
return {
"status": "PENDING",
"retry_after_seconds": 30,
"max_poll_attempts": 3,
"operation_id": "op_123",
"next_action": "poll_status"
}
```
工具返回至少应该回答四个问题:
| 问题 | 示例字段 |
|---|---|
| 成功、失败、还是等待? | `status: SUCCESS / FAILURE / PENDING / AMBIGUOUS` |
| 如果失败,失败类型是什么? | `error_code`, `recoverable` |
| 如果要重试,什么时候重试? | `retry_after_seconds`, `retry_budget` |
| 下一步建议是什么? | `next_action` |
否则 Agent 只能猜。猜错几轮后,就变成了循环。
## 7. Hard Stop 不是修复,只是保险丝
`max_steps` 必须有,但它不是根治方案。
```python
for step in range(MAX_STEPS):
result = agent.step()
if result.done:
return result.answer
if stuck_detector.is_stuck(history):
return fallback_or_fail(result)
```
`max_steps` 只能防止系统无限烧钱,不能解释为什么卡住。真正的修复要加三类机制:
| 机制 | 作用 |
|---|---|
| Stuck Detector | 判断是否重复、无信息增益、同错重试 |
| Strategy Switch | 从搜索切到读文档、从自动处理切到询问用户 |
| Failure Report | 输出失败原因、已尝试动作、缺失条件 |
失败也应该是一个明确状态,而不是沉默地继续运行。
## 8. 一个可落地的诊断流程
```mermaid
flowchart TD
S[发现 Tool 重复调用] --> Q1{工具参数完全相同?}
Q1 -- yes --> A[检查 retry budget / controller]
Q1 -- no --> Q2{语义目标是否相同?}
Q2 -- yes --> B[检查 information gain]
Q2 -- no --> Q3{是否仍在缩小问题空间?}
Q3 -- yes --> C[可能是正常探索]
Q3 -- no --> D[Planner 缺少策略切换]
A --> Q4{错误是否相同?}
Q4 -- yes --> E[加错误分类和参数修正]
Q4 -- no --> F[检查 Tool 稳定性]
B --> Q5{已有答案是否可生成?}
Q5 -- yes --> G[Stop condition 缺失]
Q5 -- no --> H[补充缺口定义和下一步策略]
```
这套流程的核心不是“第几次就停”,而是问:
```text
这一轮相对上一轮,任务状态发生了什么可验证变化?
```
如果答不上来,就不能继续盲目调用工具。
## 9. 最小可用的 Agent 日志
没有日志,Agent 死循环只能靠猜。最小日志建议如下:
```json
{
"run_id": "run_001",
"step": 7,
"goal": "完成用户订单退款",
"state_summary": "已确认订单存在,退款接口连续返回 PENDING",
"action": {
"tool": "refund_status",
"args": {"operation_id": "op_123"}
},
"observation": {
"status": "PENDING",
"retry_after_seconds": 30
},
"state_diff": {
"new_facts": [],
"completed_subgoals": [],
"open_questions": ["退款最终状态未知"]
},
"diagnostics": {
"same_action_count": 3,
"same_error_count": 0,
"information_gain": 0,
"answerable": false,
"stuck": true
},
"controller_decision": "fallback_to_human_or_schedule_poll"
}
```
只要这个日志稳定存在,循环问题就能归类到 Planner、Tool、Memory 或 Controller,而不是靠感觉排查。
## 10. 最后的判断标准
一个可靠的 Agent 系统至少要满足:
| 能力 | 检查问题 |
|---|---|
| 目标清晰 | 完成条件能否被机器判断? |
| 状态可见 | 每轮 state diff 是否可记录? |
| 工具可判定 | Tool 返回是否包含状态、错误、下一步? |
| 记忆可靠 | 已知事实是否脱离上下文窗口持久化? |
| 重试受控 | 是否有 retry budget 和 backoff? |
| 失败可解释 | 卡住时能否输出原因和已尝试路径? |
一句话总结:
```text
Agent 死循环的本质,是系统无法区分“继续探索”和“原地重复”。
```
解决它,不是只改 prompt,也不是只加 `max_steps`。要把 Agent 当成一个工程控制系统:记录状态变化,约束工具契约,检测无进展,必要时切换策略或明确失败。
-
07.23
斗破苍穹联动角色技能何如
-
07.23
班后钓鱼好玩吗 班后钓鱼玩法说明
-
07.23
我开了个翡翠厅何时出 公测上线时间预告
-
07.23
心动小镇最新21个食谱制作方法
-
07.23
《龙之信条2》支线任务阴沉的蔷薇园如何完成
-
07.23
程序员失业送外卖官网下载地址 最新官方安装指引
-
-
- 改机位(平视 → 俯视 / 仰视 / 鱼眼)
- 07.23
-
- Agent 为何会陷入 Tool 调用死循环?
- 07.23
-
-
-
-
-
下载
- |
-
-
下载
- 《行尸走肉第一章》免安装中文汉化硬盘版下载
- 单机|436 MB
- 一款以动作冒险为主题的游戏
-
-
下载
- 《街头霸王X铁拳》免安装中文汉化硬盘版下载
- 单机|111MB
- 一款非常好玩的格斗游戏
-
-
下载
- |
-
-
下载
- 《暗黑破坏神3》免安装繁体中文正式版下载
- 单机|7630 MB
- 一款以角色扮演为主题的游戏
-
-
下载
- 《马克思佩恩3》免安装硬盘版下载
- 单机|27033 MB
- 一款以第三人称射击为主题的游戏