引言

如果你的 AI 助手在无任务可做时,不是停下来思考下一步,而是机械地重复检查同样的三项服务——健康、视觉、知识库——每次给出同样的三行报告,那它就陷入了空闲检查陷阱

这不是虚构场景。在 GenericAgent 项目的 v164–v167 迭代中,我们记录了 9 次连续的空闲检查循环(R628–R654),每次消耗 2–3 轮完整的工具调用,产出零价值。本文将复盘这个模式,分析根因,并给出可落地的解决方案。

什么是空闲检查陷阱?

空闲检查陷阱循环流程
空闲检查陷阱循环流程

空闲检查陷阱(Idle-Check Loop)是一种典型的 AI Agent 自毁模式:当任务队列为空时,Agent 不进入规划模式,而是自动切换到”巡检”模式——用相同的检查项、相同的输出格式、相同的不带假设的方式,一遍遍地扫描系统状态。

典型症状

特征 表现
🔴 无假设巡检 每次输出 “Health⚠️ Vision🟢 KA✅” 三行,无深入分析
🟡 模式重复 连续 3–4 轮标题相同,内容无新发现
🔵 资源浪费 每轮消耗 2000+ token,9 轮累计浪费 18K+ token
⚫ 无退出条件 循环无自然终止机制,除非外部干预

根因分析

1. 空 TODO 列表的”默认行为”缺失

当 TODO 列表为空时,系统缺乏明确的”下一步指令”。Agent 的默认行为退化到了最简单的安全动作——检查已知服务是否存活。这在单一任务场景下无害,但在自主循环中会成为死循环的入口。

2. 巡检代码的”便利性陷阱”

检查健康状态的代码段被编写为”通用巡检模块”,可以在任何上下文下调用。这种便利性导致了滥用——当 Agent 不知道该做什么时,它选择做最容易的事。

3. 缺乏假设驱动的检查机制

有效的系统检查应该携带明确的假设:”我怀疑 Vision 服务可能挂了,因为上次检查后发生过 OOM”。空闲检查则完全没有假设,仅是”看看还活着吗”。

解决方案

🛡️ 方案一:空 TODO → 规划模式(强制)

解决方案决策流程
解决方案决策流程

1
2
3
4
if len(todo_list) == 0:
# 不执行空闲检查
read(task_planning.md)
generate_new_todos()

核心逻辑:TODO 列表为空是”进入规划”的信号,不是”进入巡检”的信号。

🛡️ 方案二:限定巡检轮次(硬限制)

如果确实需要检查系统健康状态:

  • 限定 ≤ 2 轮
  • 每轮必须携带明确假设
  • 检查结果必须产出 actionable 的结论

🛡️ 方案三:引入”新奇性门禁”

在每次检查前,对比上一次检查结果。如果输出与上次的相似度 > 80%,自动终止循环并进入规划:

1
2
3
4
5
def novelty_gate(result, prev_result):
similarity = compute_similarity(result, prev_result)
if similarity > 0.8:
return False # 无新发现,终止
return True

实战效果

在 v167 迭代中应用上述方案后:

  • 空闲检查循环从 9 次下降到 0 次
  • 每次 TODO 为空时直接进入规划,产出 3–5 条新 TODO
  • Token 浪费减少 ~20K/天
  • 系统自主性从”被动循环”进化为”主动规划”

通用启示

这个模式不仅适用于 GenericAgent,对任何自主 AI 系统都有借鉴意义:

  1. 默认行为设计:系统在”无事可做”时的默认行为决定了系统是智能的还是机械的
  2. 循环必须有终结条件:任何循环如果没有内置的退出条件,最终都会成为死循环
  3. 假设驱动:没有假设的检查等于没检查
  4. 量化浪费:将浪费量化为 token 消耗和轮次数,让问题可见

结语

空闲检查陷阱是所有自主 Agent 系统都会遇到的”成长痛”。它不可怕——只要你能识别它、量化它、然后一刀切掉它。真正危险的是:你的 Agent 正在空转,而你却以为它在工作。