恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
真题拆解 01:Agent 死循环了,异常处理写在哪
首页
资讯中心
/
真题拆解 01:Agent 死循环了,异常处理写在哪
真题拆解 01:Agent 死循环了,异常处理写在哪
发布时间:2026/8/25 23:30:42
真题拆解 01Agent 死循环了异常处理写在哪这是「真题拆解」系列的第一篇。这个系列一题一篇把真实发生的提问原样摆出来拆出背后的知识点给到能直接讲的深度答案再串起整个 Agent 知识网。选题全部来自真实生产与真实追问——这篇的问题是 2026 年大厂校招里被反复追问的一道题。问题还原你的 Agent 项目 Demo 跑得挺好但有人看完后追问了一句“你的 Agent 调了三个工具就死循环了异常处理写在哪”大多数第一反应是答设置最大循环次数。但这道题真正在问的不是轮数而是你知道 Agent 为什么会失控以及失控之后用什么机制把它拉回来吗它不是一个概念题是一个系统设计题——“Agent 失控了怎么拉回来”是 2026 年生产 Agent 最重要的工程能力之一。为什么设置最大循环次数不够先看清浅答案和深答案的差距浅答案设最大轮数深答案三层防御防什么只挡轮数超了挡失控的各种形态烧 token没到上限前一直在烧系统层 token 上限烧到线就停工具反复失败不管一直重试熔断器连败即断绕圈子不管直到轮数耗尽无进展检测状态不推进即熔断终止后裸停用户一脸懵告知进度 记日志 人工介入轮数上限只是最后一道闸不是第一道防线。只答这一个追问立刻会来“那没到上限之前它一直在烧 token 怎么办”——这就是系统层预算要回答的问题。知识点拆解这题背后是 4 个知识点死循环的根因——模型为什么会被困住不解决根因防御只是硬扛工具层容错——异常怎么让模型看懂推理层熔断——循环怎么检测、怎么断系统层预算——钱和时间怎么兜底收尾策略——终止不是裸崩逐个拆开。深度答案三层防御第零层先懂根因——死循环是怎么发生的防御之前先理解敌人。Agent 死循环有三个典型根因根因一模型对失败工具盲目重试。工具抛了一坨堆栈给模型模型不知道错在哪唯一的策略就是再试一次。再试失败再试……这不是模型傻是反馈没给够——它拿到的是不可理解的错误而不是发生了什么、还能不能重试。根因二ReAct 没有全局规划容易局部最优绕圈子。每步只根据当前观察做决策没有全局目标意识容易在同一个局部反复折腾。这是 ReAct 的天生弱点对比 Plan-and-Execute 的全局规划。根因三没有终止信号的无限循环。循环的退出条件是模型说完成了但如果模型每次都说再查一次任务永远处于进行中循环就没有尽头。三个根因对应三层防御一层治一个。第一层工具层——让模型看懂错误原则工具异常不抛给调用方而是转成结构化错误返回给模型。importtimedefsafe_call_tool(tool,**kwargs):工具调用统一包一层异常转结构化错误try:resulttool(**kwargs)return{status:success,data:result}exceptTimeoutError:return{status:failed,error_type:Timeout,retry_after:5}exceptRateLimitError:return{status:failed,error_type:RateLimit,retry_after:30}exceptExceptionase:return{status:failed,error_type:type(e).__name__,detail:str(e)[:200]}为什么这么做模型拿到{status: failed, error_type: Timeout, retry_after: 5}能明确知道超时了、5 秒后可重试拿到一坨堆栈只会懵然后盲目重试——死循环根因一的解法就在这。结构化错误里带retry_after是点睛之笔它告诉模型能不能重试、等多久让模型做正确决策而不是撞运气。第二层推理层——熔断与循环检测工具层防模型看不懂错误推理层防模型行为失控。三件套① 最大轮数兜底保护max_iterations生产环境常见 15-20 轮。② 重复动作检测记录最近 N 轮 Action发现同一个工具 同一组参数连续出现判定卡死。③ 无进展检测连续 N 步状态没有推进结果集没有变化、没有靠近目标判定绕圈。后两者用熔断器统一实现classCircuitBreaker:熔断器连续失败/重复动作达到阈值即熔断冷却期后半开恢复def__init__(self,threshold:int3,cooldown:int30):self.thresholdthreshold# 连续触发几次就熔断self.cooldowncooldown# 熔断冷却期秒self.calls{}# tool_name - [最近调用的参数快照]self.failures{}# tool_name - 连续失败次数self.opened_at{}# tool_name - 熔断开始时间deftrack(self,tool_name:str,args:dict,ok:bool)-bool:每次调用后上报结果返回 False 表示该工具已熔断禁止再调nowtime.time()# 重复动作检测同一参数连续出现self.calls.setdefault(tool_name,[]).append(args)ifself.calls[tool_name][-self.threshold:][args]*self.threshold:self.open(tool_name)returnFalse# 连续失败检测ifok:self.failures[tool_name]0else:self.failures[tool_name]self.failures.get(tool_name,0)1ifself.failures[tool_name]self.threshold:self.open(tool_name)returnFalsereturnTruedefopen(self,tool_name:str):self.opened_at[tool_name]time.time()# 熔断进入冷却期defallow(self,tool_name:str)-bool:熔断期间放行一次探活半开状态冷却期过则关闭熔断openedself.opened_at.get(tool_name)ifopenedisNone:returnTrueiftime.time()-openedself.cooldown:self.opened_at.pop(tool_name)# 冷却结束允许再试self.failures[tool_name]0returnTruereturnFalse# 还在冷却期禁止调用熔断器是三层里最容易被低估的一个连续失败 N 次就断和断完之后还能恢复是一体的。上面的allow()实现了经典的熔断-冷却-半开探活熔断期间不调用冷却期后放行一次试活成功就恢复失败继续断。没有恢复机制的熔断等于永久禁用一个工具。第三层系统层——钱和时间兜底前两层管行为这一层管成本。轮数上限挡的是行为token 上限挡的是钱——两者是两回事。模型可能每轮都很短命每次都很快完成但调了几百次token 早烧穿了。classBudgetGuard:单次任务的资源预算超时、token、调用次数谁超都停def__init__(self,max_tokens:int100_000,max_time:int120,max_calls:int20):self.max_tokensmax_tokens self.max_timemax_time self.max_callsmax_callsdefcheck(self,state:dict)-str|None:返回 None 表示正常返回字符串表示超限类型ifstate[tokens_used]self.max_tokens:returntoken_budget_exceededifstate[elapsed]self.max_time:returntimeoutifstate[tool_calls]self.max_calls:returncall_limit_exceededreturnNone收尾终止不是裸崩检测到死循环、预算耗尽之后正确收尾四步终止当前推理链——停止循环不再调工具告知用户当前进度——“已排查了 X、Y未定位到根因”——不让用户面对黑屏记录完整日志——这一步的输入输出全部落库这就是第 10 篇可观测的用武之地请求人工介入或重新规划——给用户两个选项人工接手或换一条策略重新来裸崩是最差结局用户不知道发生了什么、系统没留下任何痕迹、也无法恢复。知识联动这道题串起了整个系列死循环问题工具层 结构化错误推理层 熔断检测系统层 预算兜底收尾 终止策略第3篇 Function Calling 与工具设计第2篇 手写 ReAct 循环第9篇 护栏 harness 层第10篇 可观测 trace第8篇 编排与重新规划防御层串起的系列篇目关联知识点工具层第 3 篇 Function Calling工具不是裸函数错误码设计是工具设计的一部分推理层第 2 篇 手写 ReAct循环是死循环的载体终止条件循环的出口系统层第 9 篇 护栏 harness预算是护栏四件事之一和重试/检查点并列收尾第 10 篇 可观测 第 8 篇 编排记录 trace 才能复盘重新规划是编排的兜底手段这道题几乎能把能力篇 约束篇 可见篇整个打通——因为它问的就是系统的鲁棒性而鲁棒性恰恰是所有生产 Agent 的命门。追问链更进一步的提问追问 1“没到上限之前它一直在烧 token 怎么办”→ 系统层 token 预算上限兜底第三层。轮数挡行为、token 挡钱预算独立于轮数检查谁先超谁停。追问 2“熔断之后这个工具还能用吗”→ 能熔断不是永久禁用。熔断器有冷却期冷却后半开探活放行一次试活成功就恢复失败继续断。没有恢复机制的熔断是设计缺陷。追问 3“怎么区分正常重试和死循环”→ 三个判定指标重复同一工具同一参数连续 N 次、无进展结果集连续 N 步无变化、耗预算token/时间异常增长。正常重试是参数有变化、有进展、成本可控的。追问 4“死循环和慢循环怎么区分”→ 死循环靠重复动作/无进展检测识别慢循环靠全局超时兜底。前者判卡住了后者判太久没完成。两个机制独立存在一个管质量、一个管时间。总结一句话记住它三层防御防死循环工具层把异常转成结构化错误让模型看懂治盲目重试推理层用最大轮数 重复动作/无进展检测 熔断器切断失控治绕圈子系统层用 token/超时/调用次数预算兜住成本治烧钱。只设最大轮数是不够的——那是最后一道闸不是第一道防线。终止必须收尾四步停循环、报进度、记日志、给人/重新规划。小结这题考的是失控了怎么拉回来系统级工程能力不是概念根因三连看不懂错误盲目重试 / ReAct 局部最优绕圈 / 没有终止信号三层防御工具层结构化错误 → 推理层熔断检测 → 系统层预算兜底熔断器要能恢复熔断-冷却-半开探活没有恢复机制是设计缺陷收尾四步停循环、报进度、记日志、人工介入或重新规划知识联动串起工具设计、ReAct、护栏、可观测、编排五篇下一题预告ReAct 的消息格式——tool_response 到底该用 user 角色还是 assistant 角色同一个循环消息角色放错模型行为完全不同——这是字节追问过细节的点。本系列路线入门系列正片 11 番外 3 深度 7→真题拆解系列死循环异常处理 → ReAct 消息格式 → 多 Agent 互相推诿 → 多工具顺序/超时/熔断 → Prompt Injection 防御 → Subagents vs Agent Teams → 任务成功率指标 → token 成本定位 → ReAct vs Plan-and-Execute → 工具幂等/重试 → 更多