跳到正文

AGENT PROJECT INTERVIEW · Q12 / 25

Agent 工具超时怎么办?重试、换工具、降级和停止怎样设计

从错误分类、三层超时、共享重试预算到备用工具、缓存、熔断、部分结果和安全停止,讲清 Agent 工具故障的工程处理与验收。

作者与复核:吴师兄内容依据:公开 Agent 教程、项目题资料与工程推导查看关联教程 →查看吴师兄公开作品 →

25 道题目Q12
本页内容24 节

30 秒先说结论

工具超时后先区分参数、权限、暂时故障、永久故障和结果不确定。只读或可靠幂等的暂时故障才在单次、步骤和任务预算内有限重试,并使用退避与抖动;写操作超时先核对幂等状态。持续失败后只切换契约兼容的备用,缓存要校验新鲜度和权限,否则交付部分结果、转人工或安全停止。

面试官可能会问:“搜索工具超时了,你让 Agent 自动重试几次?重试还失败怎么办?”

这道题最危险的回答,是背一个固定次数,再补一句指数退避。每次重试都是一项有成本、有副作用、可能放大故障的业务决定,不能在错误发生后默认触发。工具为什么失败、是否可能自行恢复、请求能否幂等重放、剩余时间和预算还有多少,都会改变策略。

一个成熟的 Agent 不应该把所有异常都扔回模型,让模型凭一段错误文字自由选择。执行层先把错误分类,运行时根据工具策略和任务状态决定重试、切换兼容工具、返回缓存、交付部分结果、请求用户补充或安全停止。模型可以在有限候选中调整路径,但不能绕过超时、预算与副作用边界。

先给出 30 秒回答

工具超时后我先区分可重试的暂时故障、不可重试的参数或权限错误,以及结果不确定的写操作。每个工具同时设置单次调用超时、整步截止时间和整任务预算。只读且幂等的暂时故障可以在预算内做有限重试,使用退避与随机抖动,避免并发重试风暴;持续失败时根据契约切换等价备用、返回允许使用的缓存、交付部分结果或转人工。权限、参数和业务拒绝不自动重试;写操作超时先查幂等状态。所有策略由执行层强制,并通过故障注入验证,不照抄固定重试次数。

这段回答强调三件事:先分类,再看预算,最后选择有语义保证的退路。

工具失败后的五种出口

重试只是其中一种出口,很多错误继续重试只会让问题更严重。

第一步不是重试,而是识别错误类型

参数错误

缺少必填字段、枚举不合法、日期范围颠倒、URL 不允许访问。这类错误通常不会随时间自行恢复。正确做法是修正参数或询问用户,原样重试没有意义。

权限错误

当前用户或 Agent 没有访问目标资源的权限。权限错误不能通过换模型、改描述或反复请求解决。系统应停止该动作,提供安全解释或进入授权与人工流程。

资源不存在

工具执行正常,但目标对象没有找到。可能是标识写错、对象已删除、当前数据域不对,也可能是合法空结果。先核对条件,再决定澄清或换数据源,不能默认上游故障。

暂时故障

网络抖动、上游限流、服务暂时不可用、短时超时,可能在稍后恢复。只读和幂等动作可以在预算内重试,但需要退避、抖动和上限。

永久故障或契约不兼容

接口已经下线、版本不兼容、返回结构发生破坏性变化。继续重试不会恢复,应触发熔断、禁用候选并通知负责人。

结果不确定

写请求发出后超时,程序不知道下游是否已经成功。这是最不能直接重试的情况。必须用幂等键或业务查询核对,确认未执行后才考虑再次提交。

错误分类应由工具适配器和网关完成,返回结构化 error_typeretryable 和状态证据。模型看到的是可理解摘要,不是内部堆栈;真正的重试权限仍由策略控制。

超时至少有三层

单次工具超时

限制一个外部调用最多占用多久,防止某个网页、数据库或 API 无限挂起。不同工具的正常耗时不同,不能共用一个随意数字。

当前步骤截止时间

一个计划步骤可能包含多次搜索、访问和验证。即使每次调用都没有超过单次限制,累计时间也可能远超用户预期。步骤需要自己的截止时间。

整个任务预算

Agent 是多步循环。前面消耗过多后,后续可用时间、模型调用和工具调用都要减少。每次准备重试前,系统应查看剩余预算,而不是只看当前工具的重试次数。

还可以有用户侧截止时间与后台任务截止时间。交互请求可能需要快速返回“任务已转后台”,后台仍可继续;但转后台不是取消预算,而是换一套明确的状态与通知机制。

超时信号要能向上传递。工具超时不等于整个任务必须失败,Planner 可以选择替代路径;整任务耗尽则必须停止或交付部分结果,模型不能继续发起新动作。

什么时候允许自动重试

自动重试至少满足四个条件。

第一,错误被明确判断为暂时故障。第二,动作是只读或具有可靠幂等。第三,剩余时间与调用预算足够。第四,重试不会违反上游限流或放大故障。

满足条件后,也不是立刻连续请求。退避让下游有恢复时间,随机抖动让大量任务不要在同一时刻再次冲击服务。上游返回建议等待时间时,应优先遵守协议,而不是自己更激进地请求。

重试次数不能用一个全局常量回答。搜索和写库风险不同,用户交互与离线任务时限不同,故障率和恢复时间也不同。合理阈值来自工具历史分布、服务目标和故障演练。

同一次 Agent 任务中的重试要有共享预算。否则工具 A 重试若干次、工具 B 再重试若干次、Planner 重规划后又从头重试,局部都没超上限,整体却已经失控。

重试放在哪一层

客户端或 SDK 层

适合处理连接重置等非常底层、明确安全的瞬时错误。它看不到完整业务语义,次数要保守,并把实际尝试记录出来。

工具网关层

掌握工具契约、幂等、超时和备用执行器,是多数工具重试的主位置。它能把底层错误转换为统一 Observation。

Agent 规划层

不负责原样重发同一请求,而是在工具层已经判断失败后决定是否换关键词、换工具、拆小任务或请求澄清。这里是策略调整,不应与网络重试混为一谈。

多层都自动重试会产生乘法放大。SDK 重试、网关重试、Agent 又重试,最终一次用户请求可能触发远超预期的下游调用。系统要明确每层职责,并在 Trace 中记录总尝试次数。

从错误分类到任务出口的处理流程

底层重试解决瞬时传输问题,Agent 换路解决任务策略问题。

换工具之前先确认是不是等价替代

“搜索 A 失败就换搜索 B”听起来简单,但不同工具可能覆盖范围、时效、权限、排序和返回格式不同。

只有契约兼容、证据质量满足当前任务时,才能作为自动备用。备用工具的结果要标明来源,最终答案不能把降级数据冒充主数据源。

若备用只能提供摘要而主工具提供正文,系统可以交付部分结果或继续等待,但不能把两者视为完全等价。若用户要求最新信息,过期缓存也不是合格备用。

Tool Registry 可以为工具声明兼容组、能力差异和降级等级。网关根据任务要求选择,模型只在允许集合中调整。任何涉及权限或写操作的替代,都要重新鉴权和审批。

缓存降级有什么边界

缓存能在上游暂时不可用时提供结果,但会引入新鲜度风险。

缓存条目需要来源、生成时间、有效期、数据版本和适用范围。用户问“今天”“最新”或实时状态时,过期缓存不能作为确定答案。可以明确告诉用户结果来自较早快照,并让用户选择是否接受。

权限变化也会让缓存失效。不能因为用户过去看过某条数据,就在当前无权限时直接返回旧缓存。租户、身份和数据范围必须进入缓存隔离与校验。

缓存命中不应跳过业务验收。它只是另一种工具结果,仍需判断是否满足当前子目标。

熔断解决什么问题

当工具持续故障时,继续尝试会占满连接、拖慢所有任务,并可能压垮正在恢复的下游。熔断器在失败达到条件后暂时拒绝新调用,让请求快速走备用或降级。

熔断状态要反映到工具暴露和路由。若 Registry 已经标记不可用,但模型仍看到 Schema,就会反复选择它。新请求可以暂时不展示故障工具,正在运行的任务则收到明确 temporarily_unavailable

恢复不能一次全量放开。可以用少量探测请求确认服务,再逐步恢复。具体触发和恢复阈值必须基于工具历史与服务目标,文章和面试中都不要把示例数字说成通用答案。

怎样返回部分结果

多工具任务中,部分来源可能成功,部分失败。系统应保存已完成证据和未完成项,而不是因为一个工具超时丢掉全部结果。

部分结果适合只读、可解释的任务。最终输出说明已完成什么、缺少什么、缺口会影响哪些结论、用户能否稍后继续。Checkpoint 保存已完成步骤,下次恢复不重复昂贵调用。

有完整性硬要求的任务不能部分交付为“成功”。例如关键审批材料缺失、写操作依赖未满足,应暂停或失败。是否允许部分结果来自任务定义,不由模型临场决定。

什么时候应该停止而不是继续聪明地尝试

达到总时间或调用预算;同一错误连续出现;备用工具也不可用;多轮没有新信息;权限或关键依赖无法满足;高风险写操作状态不确定。出现这些条件时,继续探索的预期收益已经低于风险和成本。

停止不等于丢给用户一句“失败”。系统可以返回失败位置、已完成证据、未完成原因、是否可稍后恢复,以及需要用户或人工做什么。可解释停止比无限重试更像生产系统。

超时以后,旧请求真的停了吗

应用侧返回超时,不代表下游工作已经终止。HTTP 客户端放弃等待后,服务器可能还在计算;模型请求取消后,网关可能仍然收到迟到结果;后台任务可能已经进入队列。

只读请求的迟到结果通常可以丢弃或写入缓存,但要防止它覆盖更新的数据。写请求的迟到结果更危险,用户看到失败后可能再次提交,而第一次请求稍后才完成。

因此工具需要可传播取消信号,并定义不支持取消时怎样处理。运行时给每次调用分配唯一 ID,任务停止后把该调用标记为过期。迟到结果仍进入审计和幂等台账,但不能悄悄推动已经结束的 Agent 状态。

如果下游采用异步任务,超时返回的应是“仍在处理”或任务 ID,而不是失败。Agent 可以暂停等待回调或查询状态。把所有长耗时请求硬塞进同步超时,会制造大量结果不确定。

怎样防止重试风暴

单个任务的重试看起来很轻,但大量任务同时遇到故障时,重试流量可能比正常流量更大。下游刚恢复一点容量,又被同步重试压垮,形成反复故障。

除了退避和抖动,还需要全局重试预算。网关按工具和租户限制同时重试数量,新请求与重试请求可以使用不同队列,避免旧任务占满所有资源。熔断打开后,直接走降级,不再让每个 Agent 各自试探。

恢复探测也要集中管理。由少量探针验证服务,不让所有等待任务同时成为探针。确认健康后分批放量,持续观察错误和延迟,再恢复正常路由。

重试风暴验收不能只跑单任务。要模拟一批任务同时遇到限流或超时,检查下游请求总量、排队、熔断和用户出口。没有并发场景,很多重试策略在测试中看起来都正确。

降级顺序应该提前定义

故障发生时临时让模型想一个替代方案,容易出现能力越界。可以为每类任务预先定义降级阶梯。

例如公开研究任务的阶梯可能是:主搜索服务,契约兼容备用服务,符合新鲜度要求的缓存,已有证据的部分报告,明确停止。每一级都写清证据质量和用户提示。

内部业务查询的阶梯则可能完全不同:主数据库只读接口,授权只读副本,稍后重试或人工查询。不能因为公开搜索可用,就拿它替代内部订单事实。

写操作通常不做“换一个工具继续写”。同一业务动作有多个执行通道时,需要统一幂等和事务语义。否则备用通道可能重复提交。高风险动作的安全降级往往是只生成建议或 Dry-run,不产生真实副作用。

降级阶梯应进入 Registry 或任务策略,并通过版本管理。备用工具上线、缓存策略变化和权限调整后,都要跑对应故障样本。

重规划和重试有什么区别

重试保持目标、工具和参数基本不变,假设错误是暂时的。重规划则承认原路径可能不可行,根据 Observation 修改查询、拆分步骤或选择另一种能力。

工具超时一次,网关可能先做安全重试;搜索持续为空,Agent 更适合重规划关键词;关键数据源明确不可用,Planner 可以调整输出范围。若只是换一个同名备用执行器,仍属于工具层降级,不必让模型重新生成全局计划。

这个区分能减少无意义模型调用。网络抖动不需要 Planner,任务假设被推翻才需要重规划。Trace 分开记录 retry、fallback 和 replan,才能看出系统究竟在哪里消耗资源。

怎样评估重试与降级策略

不能只统计“最终有没有成功”。还要看无重试首轮结果、重试后恢复、降级后完成、部分交付、人工接管和安全停止。重试掩盖的下游故障需要单独可见。

资源指标包括每任务尝试次数、额外工具调用、等待时间和剩余预算。安全指标包括非幂等重复、越权重试、过期缓存和停止后迟到结果是否改变状态。

任务质量要比较降级前后证据。备用来源是否满足同样要求,缓存是否明确标注时间,部分结果是否暴露缺口。若降级让系统总能输出文本,却降低事实可靠性,不能算成功。

评估集按错误类型分层,并保留不重试基线、有限重试、备用和停止策略的对照。具体阈值和收益都从真实运行记录计算,设计稿里只写判定规则。

不同工具故障对应的退路矩阵

参数、权限、暂时故障和状态不确定分别需要澄清、拒绝、退避或核对。

Trace 要记录哪些信息

每次尝试至少记录工具、版本、调用 ID、请求摘要、错误类别、单次耗时、剩余预算、是否重试、退避原因、备用选择和最终出口。

不要只记录最后一次成功。首次失败和中间尝试决定系统是否稳定,也能揭示重试掩盖了多少下游问题。

Trace 还要区分网络重试和策略换路。前者参数与目标不变,后者可能改写查询或选择不同工具。两者混在一个 retry_count 中,无法诊断问题。

敏感参数只保存脱敏摘要或引用。错误堆栈进入受控日志,模型得到安全、结构化的 Observation。

怎样做故障注入验收

注入超时

分别让工具在连接、读取和执行阶段超时,检查单次、步骤和任务预算是否生效,是否能及时取消无用请求。

注入限流

让上游返回限流信号,检查退避、抖动和服务建议等待是否被遵守,多个并发任务是否形成重试风暴。

注入返回格式变化

验证适配器能否识别契约不兼容并熔断,而不是把错误结构当正常结果交给模型。

注入空结果与权限

确认系统不会把空结果当暂时故障死循环,也不会对权限拒绝换参数探测。

注入写操作结果不确定

模拟下游成功但本地超时,恢复时应先按幂等键核对,而不是直接再次提交。

注入备用故障

主工具和备用都失败时,系统要能交付部分结果或停止,不能在工具之间来回切换。

故障演练要检查 Trace 和用户结果,不只看进程有没有崩。没有真实测试结果时,按验收方案表述,不填写预期恢复率。

超时重试与降级验收清单

可靠性不是永远成功,而是在失败时能限制损失并给出正确出口。

面试官会怎样连续追问

追问一:最大重试次数设多少

没有通用数字。根据错误恢复分布、工具幂等性、单次耗时、任务截止时间和上游限流确定,并用故障演练验证。回答方法比背次数更重要。

追问二:指数退避为什么还要随机抖动

大量任务同时失败时,如果按相同间隔重试,会再次同时冲击下游。抖动分散请求时间,降低同步重试峰值。

追问三:工具超时后为什么不能让模型决定重试

模型可以在允许动作中建议换路,但是否可重试涉及幂等、预算、权限和下游状态,应由执行策略强制。尤其写操作结果不确定时不能自由重放。

追问四:缓存为什么不能总作为降级

缓存可能过期、越权或不满足当前任务的新鲜度。必须校验来源、时间、身份和业务要求,并明确告知降级语义。

追问五:熔断后模型还会不会选这个工具

要让健康状态同步到工具暴露和路由,新请求不展示故障工具;执行网关仍拒绝旧上下文发来的调用,并返回可路由错误。

追问六:怎样避免三层重试叠加

明确 SDK、网关和 Agent 的职责,使用共享总预算和统一 Trace。底层处理瞬时传输,网关按工具策略重试,Agent 只做任务换路。

工具失败以后,怎样讲清重试决策

工具超时后我不会直接背一个重试次数,而是先分类。参数、权限和业务拒绝不自动重试;只读或可靠幂等的暂时故障,才在剩余预算内有限重试,并做退避和随机抖动;写操作超时先按幂等键查询结果,不能直接重放。超时有单次调用、当前步骤和整任务三层,重试共享总时间与调用预算,避免 SDK、网关和 Agent 多层叠加。持续失败后,只在契约等价时切备用;缓存要检查新鲜度和权限;否则返回部分结果、请求澄清、转人工或安全停止。工具健康状态同步到 Registry 和路由,避免模型持续选故障工具。最后通过超时、限流、格式变化、权限、状态不确定和备用故障注入验证完整退路。

重试策略不是口号:项目里要有这些记录

  1. 是否先区分参数、权限、暂时故障、永久故障和结果不确定。
  2. 是否同时设置单次、步骤与整任务预算。
  3. SDK、网关和 Agent 各自的重试责任是否清楚。
  4. 备用和缓存是否真的满足任务能力、新鲜度与权限。
  5. 写操作超时是否先核对幂等状态。
  6. 是否做过故障注入;没做过就只讲设计,不报恢复指标。

重试的目标不是让错误暂时消失,而是在有限预算和安全边界内争取恢复。知道什么时候不重试、什么时候降级和什么时候停止,才是这道题真正的工程深度。

INTERVIEW FOLLOW-UPS

面试官会怎样继续追问?

这些追问会继续检查方案取舍、验证方法和项目事实。
  1. Q01

    最大重试次数为什么不能直接背固定数字?

  2. Q02

    SDK、工具网关与 Agent 规划层的重试职责怎样划分?

  3. Q03

    写操作超时后为什么必须先核对幂等状态?

  4. Q04

    怎样通过故障注入验证熔断、降级和停止策略?

PROJECT CHECK

换成你的项目,这几件事能否说清楚?

  • 先按错误语义和副作用判断能否重试
  • 同时设置单次、步骤与整任务共享预算
  • 为备用、缓存、部分结果和停止定义语义
  • 注入超时、限流、格式变化和主备同时故障
用自己的项目经历练一次