如何设计不会无限循环的智能体
高级13 分钟阅读自动化

如何设计不会无限循环的智能体

生产环境中最常见的智能体故障,是陷入无限或近乎无限的循环:智能体不断重试、转向分支,消耗大量token,却没有取得进展。本文介绍如何通过架构设计避免这类问题,让智能体即使面对困难任务也能正常结束。

您应该能够做到的事情

智能体之所以无限循环,是因为缺少判断何时停止的机制。生产级智能体必须设有明确的预算、进度检查、退出路径,以及能够发现停滞状态的反思机制。每种方法单独看都很简单,但缺少任何一项,都可能让智能体耗尽你的预算。

AI Expert Team发布日期: 2026年5月15日
仅在此浏览器中保存。
本文内容

昂贵的生产AI故障常常是这样的:周二凌晨3点,一个客服智能体陷入无限循环。它调用同一个工具,收到同一个错误;稍微修改参数后重试,仍然收到同一个错误;随后继续重复,每分钟多达数百次。到了早上,团队突然面对一笔四位数甚至五位数的账单,具体金额取决于所用模型和调用频率。

这种情况并不少见。智能体陷入循环,是最常见、后果也最严重的生产故障之一。这类问题很隐蔽,因为智能体往往“看起来仍在工作”:它不断采取行动,调用要么成功,要么按相同方式失败。只有查看运行轨迹时,才会发现同一种模式在反复出现。

要构建不会无限循环的智能体,必须有意识地作出架构选择。智能体的大多数故障都可以预见,防范方法也早已为人所知。能够可靠上线智能体的团队,正是那些严格落实这些方法的团队。

本文将介绍智能体为何陷入循环、哪些架构方法可以避免循环,以及漏网的循环出现时,如何通过运营防护及时发现。

智能体为何陷入循环

智能体循环通常源于以下几种机制。

1. 无法判断是否取得进展

智能体不清楚“我取得进展了吗?”它尝试一种办法、观察结果,然后决定换一种办法。如果没有明确的进度跟踪,“换一种办法”可能只是“用略有不同的方式重复同一件事”。

2. 缺少终止条件

智能体的提示词只说“帮助用户”,却没有说明“当X成立时停止”。没有明确的终止条件,智能体就会一直“帮下去”:再搜索一条信息,再尝试一个工具,再继续优化一点。

3. 病态重试

遇到失败时,智能体会自然地重试。如果没有重试次数限制,同一种失败就可能被无限重试。智能体只意识到“我还没有成功”,却意识不到“我已经试过10次了”。

4. 状态遗忘

智能体的工作记忆只包含最近几轮。如果一个循环已经经历了20次尝试,智能体在上下文中可能只看得到最后5次,因而无法发现外部观察者一眼就能看出的重复模式。

5. 工具结果不一致

工具返回含混或相互矛盾的结果,智能体于是再次尝试。工具仍然给出含混的结果,智能体便推断“也许我上次理解错了”,换种方式重试。结果仍然含混,于是形成循环。

6. 过度乐观

智能体在训练中学会了坚持不懈,即使更合理的策略是停下来求助,它也会继续尝试。这在长周期任务中尤其危险,因为微小的疑惑会不断累积。

7. 目标漂移

智能体逐渐偏离原本要完成的目标。它不断分出子任务,再分出更小的子任务,在与目标略有关联的方向上越走越远,却始终没有回到主任务。

不同智能体出现故障的方式各不相同,但防范措施大多相通。

方法1:硬性步骤预算

最简单也最重要的防线,是设置最大步骤数。例如,智能体最多可以调用工具20次。达到20次后,它必须给出最终答复,或者升级给人工处理。

实现示例:

def agent_loop(query, max_steps=20):
    messages = [{"role": "user", "content": query}]
    for step in range(max_steps):
        response = call_llm(messages, tools=available_tools)
        if response.is_final_answer:
            return response.content
        result = execute_tool(response.tool_call)
        messages.append(response)
        messages.append({"role": "tool", "content": result})
    # 已用尽预算——强制给出最终答复
    return force_final_answer(messages)

预算应根据任务校准。简单任务可以设置5–10步,复杂的多来源任务设置20–30步,开放式研究则可设置50步以上,但无论如何都必须有上限。

达到预算后,智能体应根据已有信息给出尽可能好的答复,或者升级给人工处理。

仅这一项措施,就能避免大多数灾难性的循环。因此必须始终落实。

变体

token预算。 除了限制步骤数,也可以改为或同时限制token总数。这样可以防止智能体虽然步骤不多,每一步却产生50K token的推理轨迹。

成本预算。 将步骤和token预算换算为欧元,让超支风险变得具体可见。

时间预算。 限制实际经过的时间。这对面向用户的流程很有用,例如要求“30秒内答复”。

大多数生产智能体都会以某种形式同时设置这四种预算。触及其中任何一项,都应终止本次运行。

方法2:进度跟踪

预算本身并不能让智能体意识到自己陷入停滞,只能保证它最终会停止。进度跟踪则能帮助智能体识别循环并主动脱离。

一种简单做法是让智能体维护明确的“进度”日志,每一步都记录获得了什么新信息,或者实际发生了什么变化。

第1步:搜索姓“Smith”的客户,找到12个匹配项。
第2步:筛选出活跃账户,还剩4个。
第3步:查看近期活动,发现客户234最近提交过一张价格相关工单。
第4步:读取工单详情,投诉内容与近期调价有关。
第5步:起草回复,已可发送。

每一步都增加了新信息。如果智能体执行第6步后,进度日志没有新增内容,仍是相同的搜索、结果和结论,就说明它正在原地打转。

提示词可以加入:

决定下一步行动之前,总结你在最近几步中了解到的内容。如果最近3步都没有获得新信息,请停止,并选择以下一种方式:
- 根据现有信息给出尽可能好的答复。
- 升级问题:说明你尝试过什么,以及还缺少什么。

这样一来,智能体就能看到自己“没有取得进展”,并采取相应措施。

方法3:重复检测

有时,智能体会原样重复同一个工具调用。这很容易通过程序检测。

def detect_repeat(history):
    recent_calls = [c for c in history[-5:] if c.is_tool_call]
    if len(recent_calls) < 3:
        return False
    call_signatures = [(c.tool, json.dumps(c.args, sort_keys=True)) for c in recent_calls]
    return len(set(call_signatures)) < len(call_signatures) / 2

检测到重复后,可以介入:

  • 注入一条消息:“你最近已经用这些参数调用过该工具,结果没有变化。请换一种方法或终止任务。”
  • 或者直接强制终止。

这种方法可以自动捕获最明显的循环。

方法4:停滞状态检测

除了完全相同的重复,还可以检测更隐蔽的停滞状态:

模式识别。 单独调用一次LLM,让它评估:“查看最近5个步骤,这个智能体是否在取得进展?”如果没有,就中止循环。

def is_stuck(history):
    recent = format_history(history[-5:])
    response = call_llm(
        system="你负责评估一个智能体是否在取得进展。",
        user=f"智能体最近的步骤:\n{recent}\n\n智能体是在取得实质性进展,还是陷入了循环?回答:progressing | stuck"
    )
    return response.content.strip() == "stuck"

每隔几步运行一次检查。如果返回“stuck”,就进行干预。

工具多样性。 如果智能体连续5步以上只调用了1个工具,就值得警惕。应强制它尝试其他方法或停止。

错误模式。 如果同一个工具已经3次以上返回相同错误,就停止使用该工具。继续重试并不能让智能体猜出缺少的输入。

方法5:定期反思

在智能体运行到特定节点时,强制它明确反思。

每完成5个步骤,智能体都必须进行一次反思:

1. 我的原始目标是什么?
2. 到目前为止,我了解到了什么?
3. 我还需要知道什么?
4. 我是在取得进展,还是在重复?
5. 我应该继续还是停止?

反思会迫使智能体暂时跳出只考虑下一步行动的思维,重新审视全局。

这对长周期任务尤其有效。没有强制反思,智能体容易逐渐偏离目标;加入反思后,它们可以自行发现这种偏离。

方法6:目标锚定

智能体运行时间一长,最初的目标就容易被遗忘。上下文窗口逐渐被中间步骤占满,原始问题只占庞大上下文中的一小部分。

可以通过反复强调目标来应对:

  • 在每条系统消息顶部写明原始目标。
  • 让智能体每隔N步重述一次目标。
  • 使用独立的“目标跟踪器”,确认每一步都与目标一致。

提示词可以加入:

原始目标:[verbatim user request]

每次行动前,请确认:
- 这项行动是否有助于实现原始目标?
- 如果有,请继续。
- 如果没有,请直接回到原始目标。

方法7:划定子任务边界

长周期智能体会自然地把工作拆分成子任务。如果缺少结构,子任务可能递归产生更小的子任务,最终让智能体彻底迷失。

应提供明确结构:

  • 智能体明确列出子任务。
  • 每个子任务都有自己的预算。
  • 子任务完成或失败后,智能体回到主任务。
  • 子任务不得无限产生更深层的子任务。

LangGraph等框架试图将这种结构形式化:用状态机表示流程,每个节点都是一个清晰步骤,节点之间有明确的状态转换。

这种结构对复杂智能体至关重要,对简单智能体则可能有些过度。

方法8:退出路径

智能体陷入停滞时,需要有明确的停止方式:

升级处理。 “我无法完成这项任务。以下是我尝试过的方法和仍然缺少的信息。”智能体停止运行,并把问题交给其他人处理。

部分完成。 “我已完成A和B,C因X而受阻。”智能体不必完全成功,也可以交付有用的部分结果。

请求澄清。 “我需要用户补充以下信息:……”智能体暂停并提问。

这些应该是智能体可以优先选择的常规路径,而不是迫不得已的最后手段。提示词应明确列出这些选项,并鼓励智能体在停滞时使用。

可以加入以下提示词:

如果遇到以下任何情况,请停止尝试并作出恰当回应:
- 某个工具持续返回相同错误。
- 你已尝试3种不同方法,但仍没有进展。
- 你需要只有用户才能提供的信息。
- 任务复杂度超出了现有工具的能力。

遇到这些情况时:
- 如果是工具错误:说明问题,并建议用户联系支持人员。
- 如果是没有进展:报告你尝试过的方法,并请求指导。
- 如果是缺少信息:向用户提出一个具体问题。
- 如果是任务过于复杂:提供摘要,并升级给人工协助。

方法9:根据置信度决定行动

智能体应知道自己何时有把握、何时没有把握。在置信度不足时贸然行动,往往是循环的起点。

一种方法是要求智能体在每次采取重大行动前,明确给出置信度。

调用delete_record之前,请用1–5分表示你对这项操作正确性的置信度。如果低于4,不要调用,而应请求人工确认。

这种方法尤其适合破坏性操作或成本高昂的操作。智能体必须确认自己有充分把握,才能执行。

与反思机制结合后,这种做法可以发现智能体只是在“胡乱试办法”,而不是“按计划执行”的情况。

方法10:工具层防护

除了智能体层面的措施,工具本身也可以设置防护:

按会话限流。 一个工具在单次会话中最多只能调用N次。超过N次后返回“rate limit”,迫使智能体采取其他行动。

幂等性。 完全相同的重复调用直接返回缓存结果,不再重新执行,避免循环持续冲击工具。

成本上限。 对昂贵工具,例如高负载数据库查询或按量计费的第三方API,设置每次会话的使用上限。

故障熔断。 某个工具在本次会话中失败3次后即被禁用,智能体无法再调用它。

这些防护与智能体层面的措施互为补充。智能体即使试图重复调用,也会被工具阻止。

方法11:外部监控

无论智能体内部设置了多少防护,仍需要由外部监控捕获漏网的问题。

监控进程观察所有运行中的智能体,并检查:

  • 每个智能体的步骤数。
  • 每个智能体的token用量。
  • 每个智能体的成本。
  • 每个智能体的运行时间。
  • 工具调用模式。

任何智能体超过阈值时,立即将其终止并发出警报。

这是最后一道防线。即使智能体本身已经失常,监控程序也能在它耗尽预算之前将其拦下。

具体实现可以是:

  • 用时序数据库跟踪智能体指标。
  • 通过规则触发终止命令,例如“智能体运行超过5分钟就终止”。
  • 用一个小型服务持续监视并执行这些规则。

对于同时运行大量智能体的系统,这项措施不可或缺。

方法12:人在回路检查点

对于高风险智能体,应设置人工检查点。智能体运行至检查点后暂停,等待人工批准。

典型检查点包括:

  • 执行破坏性操作之前。
  • 作出不可逆决定之后。
  • 长周期任务的重要里程碑。
  • 置信度下降时。

这不是因为不信任智能体,而是为了在修复成本尚低时发现错误。

一种实用工作流是:智能体自主完成准备工作,提交摘要和拟执行的操作,由人工批准后再执行。人工只参与决策,不必介入每一个步骤。

完整示例:长时间运行的研究智能体

以下展示如何把这些方法应用到一个真实智能体中。

任务: 调研一家竞争对手并撰写简报。

预计工作量: 搜索网页10–30次,阅读页面20–50个,综合写成一篇1,000词的简报。

采用的方法:

  1. 步骤预算: 共60步。

  2. token预算: 300K token(上下文和操作)。超出预算后,先总结当前发现再继续。

  3. 成本预算: 每次运行€2。超出后停止,并返回部分简报。

  4. 时间预算: 实际经过时间5分钟。

  5. 进度跟踪: 每一步都向“发现日志”加入新信息。如果连续3步没有新发现,就退出。

  6. 重复检测: 如果同一搜索词运行两次且结果相似,就强制改用其他方法。

  7. 定期反思: 每10步反思一次当前进展和剩余工作。

  8. 目标锚定: 在每条系统消息顶部写明原始简报目标。

  9. 退出路径: “信息已经足够”或“无法找到足够信息”都可以让智能体正常结束。

  10. 外部监控: 由独立监控程序终止超出预算的智能体。

结果: 运行时间中位数为3分钟,成本中位数为€0.40;循环或超时导致的失败率低于1%。生成的简报为700–1,200词,有事实依据,可作为实用的初稿。

如果不采用这些方法,偶尔会出现运行30分钟、花费超过€20,甚至会话彻底卡死的情况。这些方法能显著降低长尾风险。

在生产环境中检测

即使采用了上述方法,偶尔仍会有问题漏过,因此还要进行检测:

对长时间运行的智能体发出警报。 运行时间超过中位数2倍的任何智能体都会触发警报。

对成本激增发出警报。 单个智能体或总体成本超过阈值时发出警报。

对重复模式发出警报。 发现疑似循环的工具调用模式时发出警报。

每天审查长时间运行的轨迹。 人工每天快速查看耗时最长的10条运行轨迹,以发现评估没有覆盖的问题。

汇总指标: 跟踪循环率随时间的变化。当模型更新或提示词变更等因素导致循环频率上升时,就能及时发现。

一个实用的仪表盘应展示智能体运行长度的分布。分布的长尾能反映循环发生率。

常见错误

以下错误经常出现:

错误1:不设步骤预算。 团队常说“需要时再加”,直到智能体凌晨3点陷入循环,才后悔没有提前设置。从第一天起就必须加入步骤预算。

错误2:预算过高。 “100步肯定够了”,但循环照样会把预算用满。预算应按中位数的2–3倍来设,而不是按最坏情况来设。

错误3:没有外部监控。 只相信智能体会自行停止,但它有时不会。生产环境必须有外部监控。

错误4:发现循环后不分析。 监控程序终止循环后,团队就继续做其他工作,结果同样的循环下周再次发生。每次发现循环都要进行事后分析:是什么触发了循环,什么发生了变化,能否从根本上防止这一类故障?

错误5:在简单任务上过于频繁地反思。 对一个总共只有5步的任务强制每5步反思一次,只会增加开销,没有实际收益。反思频率应与任务复杂度相匹配。

错误6:在长上下文中遗失目标。 只在第1步提过一次的目标,到了第50步往往已经淡出上下文。必须定期重新强调目标。

错误7:相信智能体自报的进度。 智能体可能声称自己正在取得进展,实际却并非如此。只要条件允许,就应从外部验证。

错误8:允许智能体递归调用自己。 “把这项任务拆分给多个子智能体”可能导致智能体数量呈指数增长。如果允许这种行为,就必须严格限制预算。

哪些循环可以接受

并非所有循环都有问题。有些任务确实需要多轮迭代:

  • 迭代改进代码:编写、测试、修复,再重复。
  • 带有分支的多步骤研究。
  • 优化任务:尝试不同方案、评估,再改进。

在这些任务中,循环本身就是工作,并非故障。相应方法也需要调整:

  • 提供更充足的步骤预算,例如50–200步。
  • 明确把过程定义为“迭代”,而不是“循环”。
  • 跟踪质量改进,每轮迭代都应提升某项指标。
  • 改进停滞时硬性停止。

关键在于区分“预期内的迭代工作”和“意外循环”,并分别采用适当措施。

生产检查清单

智能体无限循环是可以预见、很常见,也能够避免的问题。相应方法早已明确:步骤预算、进度跟踪、重复检测、定期反思、目标锚定、退出路径、工具防护和外部监控。

这些并非可有可无的锦上添花,而是决定智能体能否上线,还是会带来意外四位数账单的关键措施。

任何生产智能体都应检查以下项目:

  • 最大步骤预算。
  • 最大token预算。
  • 最大成本预算。
  • 最大时间预算。
  • 重复调用检测。
  • 进度跟踪。
  • 定期反思。
  • 目标锚定。
  • 多种退出路径。
  • 具备终止能力的外部监控。

每一项都很容易实现。结合起来,它们决定了一个智能体是“无人看管就很危险”,还是“在生产环境中可靠运行”。

把这些方法落实到系统中,并认真测试。由此消除的长尾风险,远远抵得上投入的工作。

继续阅读

通过下一篇文章继续沿着相同的学习路径进行学习。

深入学习

精选的外部课程,帮助您更深入地了解该主题。

查看所有 自动化 课程