首页 › ai-agents › 设闸仍空转:自主体终止判断四栈实测

概述

自主智能体(Autonomous Agent)几乎都内建了循环终止旋钮——CrewAI 的 max_iter、LangGraph 的 recursion_limit、OpenAI Agents SDK 的 max_turns、OpenHands 的 stuck_detector。直觉上,设了上限就安全了。但 2026 年 7 月华中科技大学发表在 arXiv 的论文《When Agents Do Not Stop》给出反直觉结论:即使框架已经提供循环控制机制,无限智能体环(Infinite Agentic Loops, IALs)仍是真实工程风险——其工具 IAL-Scan 在真实自主体项目中确认了 68 个无限环失败、横跨 47 个项目、精度 91%。本期实测四款主流终止闸门,归纳出四种失效式:计数即放行、封顶即抢救、硬断即崩、觉醒即漏网。核心发现是——计数闸门计量的是步数而非进展,语义闸门抓的是死循环而非漂移环,设了闸,空转依旧。

四栈终止闸门对比

闸门机制 所属框架 计量单位 触发行为 默认值 语义感知 典型失效式
max_iter CrewAI 迭代次数 软封顶("尽力给出好答案") 25 否 计数即放行 / 封顶即抢救
recursion_limit LangGraph 超步数(super-step) 硬熔断(抛 RecursionError) 25 否 硬断即崩
max_turns OpenAI Agents SDK 对话轮次 抛 MaxTurnsExceeded,可 None 关闭 默认开启 否 计数即放行
stuck_detector OpenHands 语义动作-观察对 自动暂停 + is_stuck() 默认开启 是(语义相等) 觉醒即漏网

深度分析一:CrewAI max_iter —— 软封顶的"尽力而为"陷阱

架构原理:CrewAI 的每个 Agent 持有一个迭代计数器,每完成一轮"思考→工具调用→观察"自增。当计数逼近 max_iter 时,框架并不会硬杀,而是把"你已接近上限"作为提示注入上下文,诱导 LLM 收尾。官方文档原文:"Once the agent approaches this number, it will try its best to give a good answer."(达到该数后,它会尽力给出一个好答案。)

from crewai import Agent
researcher = Agent(
    role="市场研究员",
    goal="完成某赛道竞品调研",
    max_iter=25,              # 默认 25:达到后触发"尽力收尾"
    max_retry_limit=2,
    allow_delegation=False,   # 默认 False:关闭跨 Agent 委托旁路
)

优缺点:优点是简单、零成本、对正常任务足够;缺点致命——计数器只数步数,无法判断"这一步有没有进展"。一个反复调用失败工具、原地打转的 Agent 会老实把 25 次额度烧满才停(计数即放行);而临近上限时"尽力给出好答案"的软诱导,反而会触发 LLM 编造一个看起来完整、实则未验证的伪结论(封顶即抢救)。allow_delegation=False 默认关闭委托,正是为了避免委托链路绕过主计数器形成旁路环。

变现/训练营评估:极高。这是训练营"自主体稳定性"模块最易演示的翻车现场——同一个任务,把 max_iter 从 25 调到 5,伪完成率肉眼可见飙升,可设计成对比实验课。

深度分析二:LangGraph recursion_limit —— 硬熔断的"丢现场"

架构原理:LangGraph 把图执行切成一个个 super-step,recursion_limit 限制总步数(默认 25)。与前者的软诱导截然相反,LangGraph 是硬熔断:一旦超限,直接抛出 Python 原生 RecursionError,整个图执行中断,没有任何"优雅收尾"的过渡。

graph.invoke(
    inputs,
    config={"recursion_limit": 25}   # 默认 25;超过抛 RecursionError,整图崩溃
)
# 生产中常需提到 50/100,但提高上限 = 放大单次运行的烧钱上限

优缺点:优点是"绝对会停",是最后一道安全网,绝不让环无限跑下去;缺点是停得太丑——硬抛异常意味着中间状态可能写到一半、checkpoint 处于不一致状态、上层调用方拿到的是栈跟踪而非部分结果。更隐蔽的问题:提升 recursion_limit 几乎是开发者面对长任务的本能反应,但这等同于把单次烧钱上限从 25 倍放大到 100 倍,把"安全网"撑成了"账单网"。

变现/训练营评估:中高。可结合成本监控做"recursion_limit 与单次成本上限"的耦合实验,讲清"安全网不等于省钱网"。

深度分析三:OpenAI Agents SDK max_turns —— 可关闭的双刃

架构原理:OpenAI Agents SDK 用 max_turns 限制 Runner 的执行轮次,超限抛 MaxTurnsExceeded 异常。它同时提供一个 on_max_turns 回调钩子,允许在撞线时自定义收尾逻辑(保存部分输出、返回降级结果),比 LangGraph 的硬抛异常更可控。但官方同时允许 max_turns=None 彻底关闭限制。

from agents import Runner
result = await Runner.run(
    agent,
    input="...",
    max_turns=10,          # 超过抛 MaxTurnsExceeded
    # max_turns=None       # ← 一行代码即可彻底关闭终止闸
)
# on_max_turns 钩子:撞线时优雅保存,而非崩溃

优缺点:优点是有钩子可优雅退出,工程友好;缺点同样是纯计数(计数即放行),且"可关闭"本身是巨大隐患——开发者为了"别让它中途停"随手设 None,等于亲手拆掉安全网。on_max_turns 钩子若不实现,行为就退化为硬熔断。

变现/训练营评估:高。可设计"三档配置"实验:默认 vs 提高 vs None,量化三者的完成率与成本,是企业落地最关心的 ROI 问题。

深度分析四:OpenHands stuck_detector —— 唯一的语义觉醒

架构原理:OpenHands 是四栈中唯一具备语义感知的闸门。它的 stuck_detector(默认开启)实时监控"最近一次用户消息之后"的事件历史,对相邻的 action-observation 对做语义比较(而非对象身份比较),一旦识别出重复模式就自动暂停执行。官方示例:Agent 连续执行 5 次 ls,检测器在抓到 4 个语义相同的动作-观察对后判定卡死,调用 is_stuck() 返回真,框架自动 halt。

from openhands.sdk import Conversation
conv = Conversation(config, stuck_detection=True)   # 默认 True
# 监控用户消息后的事件历史,连续 4 个语义相同的动作对 → 判定卡死
if conv.stuck_detector.is_stuck():
    conv.halt()    # 早停,而非烧满 max_iterations

优缺点:优点是真正"懂"死循环——能在烧满预算之前就识别"你在原地打转"并早停,是四栈里唯一能省钱的闸门;缺点是它只抓语义相等的重复,抓不到"漂移环"——Agent 每次换个略微不同的查询、或以微小变体重试同一个失败动作,每个动作对都不完全相同,语义比较判不出重复(觉醒即漏网)。语义相等 ≠ 进度相等。

变现/训练营评估:最高。语义觉醒 vs 计数闸门的对比,是"自主体能不能自己知道该停"这一终极问题的最佳教学素材。

深度分析五:IAL 理论框架 —— 为什么"有闸仍空转"

前四栈都在"怎么停",arXiv 2607.01641 回答的是更根本的"为什么停不住"。论文把问题命名为 Infinite Agentic Loops(IALs),并给出一个框架无关的有界性判定模型:一个自主体环由四类元素构成——

核心判定:当一条反馈路径同时包含高代价或状态增长的动作,且没有有效边界覆盖它时,该环就会退化为 IAL——反复触发模型调用、工具调用、状态更新或 Agent 跳转,后果是"成本耗尽、模型拒绝服务、上下文膨胀、重复的副作用"。论文的 IAL-Scan 工具把源码抽象成框架无关的 Agent IR,构建 Agentic Loop Dependence Graph(ALDG),既恢复显式循环,也恢复框架隐式反馈路径(工作流跳转、工具分发、重试、Agent 再入)。实证结果:报告 74 个潜在发现,人工复核确认 68 个 IAL 失败、横跨 47 个项目、精度 91%。

这篇论文最关键的洞察不是"发现了多少 bug",而是点破了闸门失效的结构性根因:主流框架都暴露了终止边界(max_iter、recursion_limit 等),但——

  1. 这些边界大多是计数型,只覆盖"主循环步数",覆盖不到委托、重试、工具再入等反馈旁路;
  2. 旁路环在主计数器看不见的地方空转,最终仍触发高代价调用与状态膨胀。

这正好解释了前四栈实测中"设了闸仍空转"的现象:闸门存在 ≠ 闸门覆盖了真实的反馈路径。

深度分析六:终止判断四式 —— 实测归纳

把前四栈的失效模式抽出来,自主体终止判断恰好有四种典型翻车式:

式一 · 计数即放行:CrewAI / LangGraph / OpenAI SDK 三家的纯计数闸门共享同一缺陷——计量步数而非进展。一个反复调用失败工具、原地打转的 Agent,会被闸门"放行"直到烧满全部额度才停。计数器回答的是"跑了多少步",不是"这步有没有用"。

式二 · 封顶即抢救:CrewAI 的软诱导在临近上限时触发 LLM 编造伪完成——一个本应继续的任务,在撞线前被包装成"已完成"。这是最危险的一式,因为输出看起来正常,会骗过缺乏验证的上层流程。

式三 · 硬断即崩:LangGraph 抛 RecursionError,OpenAI SDK 默认抛 MaxTurnsExceeded(若无 on_max_turns 钩子)。绝对会停,但停得丑——中间状态不一致、checkpoint 半写、上层拿到栈跟踪。安全网保住了钱包,却丢了现场。

式四 · 觉醒即漏网:OpenHands 的语义觉醒是四栈里最先进的,但它建立在"语义相等 = 卡死"的假设上。漂移环(每步动作微变、却同样无进展)绕过了语义比较。语义相等 ≠ 进度相等,觉醒仍会漏网。

四式叠加的结论:没有任何单一闸门能独立保证"该停时停、该跑时跑"。生产级自主体必须组合使用。

深度分析七:生产级终止架构 —— 三闸门 + 有界性审计

基于四栈实测与 IAL 理论,推荐生产级自主体采用纵深防御的终止架构,而非依赖单一旋钮:

第一层 · 硬预算闸(绝对熔断):以成本/Token 上限作为不可逾越的最后一道网,对应 LangGraph 的硬熔断语义,但必须配套 checkpoint 持久化与降级输出,避免"硬断即崩"。

第二层 · 计数闸(上限而非策略):max_iter / max_turns 作为"最多跑多少步"的天花板,定位是兜底,不能当作唯一的进展判断。同时审计反馈旁路——委托链、重试逻辑、工具再入是否各自有独立计数,防止旁路在主计数器盲区空转(这正是 IAL 的结构性根因)。

第三层 · 语义 + 进度闸(早停):引入 OpenHands stuck_detector 式的语义重复检测做死循环早停;再叠加一层"进度检测"——每 N 步用一个小模型或规则判断"目标完成度是否提升",补上语义比较抓不到漂移环的漏洞。

关键工程动作:所有硬熔断必须挂 on_max_turns 钩子优雅退出(保存 checkpoint、返回部分结果),把"硬断即崩"转成"硬断即降级"。并把 IAL-Scan 式的有界性审计纳入 CI——每次新增工具或委托路径,自动检查其反馈路径是否被某道闸门覆盖。

终止边界架构图

flowchart TD
    U[用户目标] --> L[Agent 主循环<br/>感知 → 推理 → 行动 → 观察]
    L --> A{本轮行动}
    A -->|工具调用 / 委托 / 重试| T[外部工具与环境]
    T --> O[观察结果]
    O --> L

    L --> G1[第一道闸 · 计数器<br/>max_iter / max_turns / recursion_limit]
    G1 -->|未达上限 且 无进展| F1[计数即放行<br/>烧满额度才停]
    G1 -->|软封顶临近| F2[封顶即抢救<br/>LLM 编造伪完成]
    G1 -->|硬上限超限| F3[硬断即崩<br/>RecursionError 丢现场]
    G1 -->|未触发| L

    L --> G2[第二道闸 · 语义觉醒<br/>stuck_detector]
    G2 -->|连续 N 个语义相同动作对| F4[抓到死循环 · 早停]
    G2 -->|动作微变 · 漂移环| F5[觉醒即漏网]
    G2 -->|正常| L

    L -.委托 / 重试 / 工具再入.-> B[反馈旁路<br/>绕过主循环计数]
    B --> IAL[IAL 无限环<br/>成本耗尽 · 上下文膨胀 · 重复副作用]

    IAL -.需有界性审计覆盖.-> G3[第三道闸 · 硬预算<br/>成本/Token 绝对熔断]

场景化推荐

轻量任务 / Demo 级:CrewAI max_iter=25 足够,但务必开启结果校验环节,挡住"封顶即抢救"的伪完成。

长链路 / 工作流编排:LangGraph recursion_limit 必须配套 checkpoint 与降级钩子,把"硬断即崩"转成优雅退出;切勿为跑长任务而无脑调高上限——那是在放大单次烧钱额度。

对成本敏感的生产自主体:必须上 OpenHands 式语义觉醒闸 + 进度检测双保险,实现"烧满之前就停",并叠加独立的硬预算闸作为绝对兜底。

多 Agent / 含委托的系统:优先做 IAL-Scan 式的有界性审计——重点不是设多少 max_iter,而是确认每条委托、重试、工具再入旁路都被某道闸门覆盖。闸门存在不等于闸门覆盖,这是"设闸仍空转"的根因,也是本期最该带走的一句话。

参考来源

  1. When Agents Do Not Stop: Uncovering Infinite Agentic Loops in LLM Agents (arXiv 2607.01641) — 华中科技大学 2026 年 7 月论文,提出 IAL 概念、IAL-Scan 工具与有界性判定框架(68 个确认失败 / 47 项目 / 精度 91%)。
  2. CrewAI · Customize Agents(max_iter) — 官方文档,确认 max_iter 默认 25 及"尽力给出好答案"的软封顶语义。
  3. OpenHands · Stuck Detector — 官方文档,语义动作-观察对重复检测、默认开启、is_stuck() API。
  4. OpenAI Agents SDK · Running Agents(max_turns) — max_turns / MaxTurnsExceeded / on_max_turns 钩子与 max_turns=None 关闭选项。
  5. crewAIInc/crewAI Issue #6414 — 社区呼吁引入原生确定性 guardrail 防止无限环,反映计数型闸门在生产中的实际痛点。

——「51学通信」AI 智能体实战系列 · 站长爱卫生(微信 gprshome201101)

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入