Deep Research 的一次回答,可能依赖多次搜索、页面访问和计算。
链路一旦足够长,工具失败就会成为系统必须面对的正常状态,无法继续按偶发例外处理。
Search 可能超时或限流,Visit 可能遇到页面不存在、访问受限或正文抽取为空,Scholar 可能只返回不完整元数据,Python 可能因为输入、资源或沙箱规则失败。
报错至少是可见的;更危险的是系统“为了继续”掩盖错误。Agent 可能把搜索摘要当正文,换一个不相关页面凑证据,重复调用同一工具,甚至在没有资料时生成一段听起来完整的结论。
所以面试官问工具容错时,真正想听的是:
怎样区分可重试与不可重试错误,重试、换参数、换来源、换工具、降级和停止分别在什么条件下发生,如何保护已经获得的证据,又怎样验证系统没有在失败后悄悄降低事实标准?
工具失败首先要被“看懂”
如果所有异常都被包装成 tool failed,Agent 无法选择正确动作。
参数错误意味着请求本身不合法。继续发送同一参数不会恢复,应根据字段错误做最小修复。
临时网络错误意味着工具服务可能稍后可用。对只读、幂等调用,可以在有限预算内退避重试。
限流意味着当前调用速度超过服务边界。每个 Agent 自己快速重试只会放大问题,应由网关排队、降低并发或切换经过授权的备用服务。
权限错误意味着当前身份无权访问。系统应换公开来源、请求用户提供授权材料,或明确无法核验,不能尝试绕过。
资源不存在可能是 URL 过期、页面迁移或实体写错。应该回到 Search 找官方迁移位置,而不是无限 Visit。
内容为空可能来自动态页面、抽取器失败或页面确实没有相关信息。需要区分“页面没内容”和“抽取没成功”。
安全拒绝表示工具调用触碰协议、文件、代码或隐私边界。它不是普通技术失败,不能通过换一种参数逃避规则。

错误类型决定下一步,原样重试只是少数情况的正确答案。
错误对象应该包含哪些字段?
一个可执行的错误对象至少包含工具名、调用 ID、错误类别、是否建议重试、可读说明、已消耗时间、预算影响和建议动作。
参数问题还要包含字段路径、当前值和期望约束。模型才能只修错的字段,不重新生成全部参数。
权限和安全问题要明确不可重试,但不能把内部鉴权细节、密钥或敏感路径返回给模型。
内容错误可以说明“页面可访问,但没有抽取到与目标相关的段落”,让 Agent 决定换目标、换来源或调整当前缺口。
工具服务的内部堆栈保留在日志,不直接进入模型上下文。模型需要的是能改变下一步的结构化信息,工程团队需要的是完整诊断信息,两者不必相同。
错误对象还要带工具和 Schema 版本。一次参数失败可能来自新旧契约不一致,没有版本就难以回放。
一条完整的恢复决策链
第一步,网关判断请求是否已经执行,以及工具是否有副作用。
第二步,根据错误类型决定是否允许重试。只读调用更容易重试,写操作必须依赖幂等键和明确状态。
第三步,检查当前重试次数、剩余预算和全局服务健康。即使错误可重试,也不能无限尝试。
第四步,选择最小恢复动作:修正字段、延迟重试、换授权备用服务、回到 Search、换来源、换工具或缩小目标。
第五步,把恢复结果写回研究状态。成功后标明证据来源和是否来自降级路径;失败后记录已经尝试的策略,防止循环。
第六步,重新评估当前任务还能否满足用户契约。关键缺口无法关闭时进入部分完成或失败,不把低标准结果伪装成正常完成。

每次恢复都受错误类型、幂等性、预算和用户契约共同约束。
重试为什么必须有限且分层?
一次临时网络抖动可能很快恢复,有限重试有价值。
但参数错误、权限错误和不存在资源不会因为重复发送而变化。原样重试只会浪费预算并制造噪声。
重试还要分工具调用和研究策略两层。
工具层重试处理同一请求的短暂失败,例如一次超时。
策略层重试处理路径失败,例如某个来源不可用后换另一个官方来源。这已经不是同一次调用,需要新的动作 ID 和证据判断。
所有 Agent 共享的服务应在网关集中控制。若十个研究单元各自认为“再试一次”,总请求会突然放大。网关需要全局并发、速率和熔断状态。
退避时间、次数和并发不能照搬固定教学值。它们取决于工具服务承诺、任务时限、幂等性和用户体验,必须通过故障演练调校。
熔断器怎样避免故障被整个系统放大?
当一个外部搜索服务持续失败时,继续把每个新请求都发过去,只会增加排队和超时。
网关可以按工具和错误类型维护健康状态。短时间内持续出现可归因于服务的失败时,进入熔断状态,新的调用不再等待真实超时,而是立即返回“服务暂不可用”和允许的替代路径。
熔断不是永久下线。经过观察窗口后,可以用少量探测请求进入半开状态。探测稳定成功,再逐步恢复流量;仍失败则继续熔断。
参数错误和权限错误不能计入服务熔断,否则一个调用方的坏请求会误伤所有用户。相反,真实服务超时也不能让每个 Agent 各自统计,否则全局已经故障,单个 Agent 还以为只是偶发问题。
熔断状态应进入路由输入。Agent 知道某工具当前不可用,才能选择公开备用来源、延后该子任务或给出部分完成,而不是不断生成同一个调用。
恢复后也不要瞬间放开全部并发。逐步恢复能避免服务刚好转就再次被积压请求压垮。
工具只返回一半结果,算成功还是失败?
不少工具不是非黑即白。
Search 可能返回部分候选后超时,Visit 可能提取到正文却丢了表格,Scholar 可能有论文元数据却没有摘要,Python 可能完成部分文件处理后遇到坏行。
如果统一标成成功,Agent 会高估证据完整性;统一标成失败,又会丢掉已经取得的有效信息。
结果对象应分别记录执行状态、已完成范围、缺失范围、证据片段和是否允许继续使用。已返回内容可以进入候选证据,但与完整结果分级管理。
后续动作针对缺失部分补偿。例如 Visit 缺表格时,可以换支持该格式的解析器,不必重新访问已经抽取的正文。若缺失部分正是用户问题核心,则不能用现有片段直接结束。
部分返回还要有稳定调用 ID。重试补齐后,新结果与旧结果合并,而不是当作两个独立来源。
Search 失败后可以怎样降级?
先判断是服务失败,还是查询本身没有结果。
服务超时或限流时,可以排队、降低并发、使用经过授权的备用搜索源,或者暂时返回已有证据。
查询无结果时,应该检查实体、时间和语言,尝试合理改写或拆分,而不是把无结果误判成服务故障。
如果已有明确官方站点,可以在允许范围内直接访问已知页面;但不能因为 Search 不可用就随便猜 URL。
备用搜索源返回的字段和排序可能不同,结果进入统一 Schema 前要归一化。切换来源后还要在 Trace 标明,方便评估降级路径是否降低证据质量。
若任务要求最新、多源或完整检索,而当前只有一条旧缓存,系统应明确能力不足。不能为了保持“回答率”而悄悄降低来源要求。
Visit 失败要先分清“页面问题”和“抽取问题”
页面不存在时,查看是否有官方迁移、重定向或新版本入口。
访问受限时,不能绕过登录、付费、机器人规则或内容授权。可以寻找公开原始出处,或者请用户提供有权使用的材料。
页面可打开但正文为空,可能是动态渲染、反爬页面、文件格式不支持或抽取器失败。工具应返回页面状态和抽取状态两个字段,不能把它们混成空字符串。
正文存在但没有目标信息,也不是技术错误。它是一次有效核验,说明该页面不能支持当前主张。研究状态应记录“已检查但未支持”,避免再次访问。
切换到转载或聚合页面时,证据等级会变化。最终报告要说明它不是原始来源,关键结论仍可标记待核验。
Scholar 和 Python 失败有哪些特殊边界?
Scholar 可能只返回标题、摘要和出版信息,拿不到正文。这时可以确认论文存在,却不能声称已经核验方法和实验限制。
元数据冲突时,应按标识、作者、版本和发布日期归一,避免把预印本和正式版本计成两个独立来源。
Python 的参数和数据来源比运行成功更重要。
语法错误可以修复,资源超限需要缩小任务或调整沙箱预算,安全拒绝不能绕过。若输入数据口径未对齐,程序即使运行成功,结果也不应进入确定结论。
计算失败后不应改用语言模型心算一个“差不多”的值。可以返回公式、已确认输入和未完成原因,或者请求补充数据。
派生结果还要保存输入 Evidence ID、操作摘要和环境版本,恢复后才能重放。
有副作用的工具为什么要单独设计?
当前研究工具大多只读,但真实 Agent 以后可能接入保存文件、发送消息、创建任务或修改配置。
这类调用不能套用 Search 的自动重试。请求超时不代表服务端没有执行,再发一次可能产生重复写入。
执行前需要明确用户授权、目标对象、预览和幂等键。执行后保存服务端确认 ID,用它查询结果,而不是只靠客户端是否收到响应判断成功。
发生不确定状态时,先查询已有动作是否完成,再决定重试。无法确认时应暂停并请求人工处理,不能让模型猜测。
补偿操作也不是万能回滚。删除一条已经发送的消息,未必能消除外部影响。因此研究循环中的自动探索只能直接使用低风险只读工具,高风险写操作放在明确工作流和人工确认边界内。
即使当前项目暂时没有写工具,注册表也应标注副作用等级,防止未来新增能力后沿用错误重试策略。
已有证据怎样在故障中被保护?
工具失败只影响当前动作,不应删除之前已经核验的主张。
研究状态需要把已确认证据、候选证据、失败动作和未完成缺口分开。新工具失败时,只更新相关缺口和预算。
状态提交也要有版本。多个并行工具返回时,失败结果不能基于旧版本覆盖已经成功合并的新证据。
部分完成报告应使用已有可靠证据,但必须标出缺失范围。例如三个对象中两个已核验,第三个访问受限,就说明第三项无法确认,不能复制前两项结构生成猜测。
恢复服务后,可以从未完成缺口继续,而不是从头搜索。幂等动作 ID 和已访问集合用于避免重复。
进程重启和用户取消怎样恢复?
工具还在运行时,Agent 进程可能重启,用户也可能主动取消任务。
每个关键动作开始前要持久化调用 ID、工具、参数摘要、任务版本和当前状态。进程恢复后先查询调用是否已经完成,再决定取回结果、重试或标记不确定,不能直接重新发送。
用户取消时先停止产生新动作,再尝试取消可安全中断的工具。已经返回的证据可以保存,但任务状态必须标为用户取消,不能因为后台稍后完成就自动发布报告。
若工具不支持取消,系统应忽略迟到结果或把它保存为未合并证据,不能让旧任务结果覆盖用户后来修改的要求。
恢复还要检查工具和 Schema 版本。任务创建后接口已升级,旧参数可能不能直接重放,需要兼容层或明确终止。
这类恢复应进入故障演练。只测试单次 HTTP 超时,无法证明长任务真的能跨进程、跨版本继续。
降级不是“换个差一点的答案”
降级应该改变能力或交付,并让这个变化可见。
Search 主服务不可用,切备用服务是一种工具层降级。
无法完成多源交叉验证,只返回单一原始来源并标明限制,是证据层降级。
关键页面无法访问,输出已确认内容和信息缺口,是交付层降级。
高风险结论缺证据,直接拒绝给确定答案,是安全层降级。
每种降级都要预先定义最低可接受标准。若用户契约要求必须完整比较,部分结果可能不能作为正常交付,只能保存进度并说明阻塞。
“接口返回 200”不能代表没有降级。响应状态、报告正文和 Trace 都要表明系统最终走了哪条能力路径。
一个教学故障场景
下面是教学设计,不代表真实线上事故。
任务要求核对某开源项目当前版本的配置边界。
Search 成功找到官方文档,Visit 第一次超时。网关有限重试后仍失败,返回临时网络错误。
Agent 随后访问一个社区转载,页面可读,但没有版本时间。它只能作为候选线索,不能替代官方当前文档。
系统回到 Search,找到官方发布说明的另一个入口。Visit 成功,确认了版本和配置边界。
如果备用入口也失败,合格输出应保留社区线索,但明确“当前版本未从原始来源核验”。错误做法是把转载写成官方结论,或者一直重试第一个 URL 直到预算耗尽。
这个场景说明恢复成功不只看工具最终有没有返回,还看证据标准是否保持。
故障注入集应该覆盖什么?
参数层加入缺字段、错类型、越界值和互斥参数。
网络层加入超时、连接中断、偶发错误和持续错误。
服务层加入限流、排队、部分返回和备用服务不可用。
资源层加入页面不存在、重定向循环、动态空正文和内容版本变化。
权限层加入登录、租户隔离、受限内容和危险协议。
策略层加入重复查询、同源转载、错误工具和预算耗尽。
状态层加入并发返回、任务取消、进程重启和旧版本覆盖。
每个样本都要定义期望动作:是否重试、是否换工具、是否降级、是否停止,以及最终状态应该是完成、部分完成还是失败。

故障测试要覆盖调用、服务、证据和状态,而不是只模拟一次超时。
工具容错应该看哪些指标?
工具成功率只说明接口层状态。
还要看首次调用成功、重试后成功、换来源成功、降级完成和最终无法完成分别占什么类型。不同错误混成一个平均值没有诊断价值。
重复调用率和无效重试率用于发现循环。
恢复后证据等级检查系统是否因为故障使用了更弱来源。
部分完成可用性检查已有结论、缺口和恢复点是否清楚。
尾延迟和预算消耗反映恢复是否拖垮长任务。
最终报告还要检查关键主张是否被真实来源支持,失败信息是否被隐藏。一个系统可能通过积极降级提高接口成功率,同时降低答案可信度,必须联合观察。
指标不能被写成固定生产效果。应该按工具、错误、任务风险和恢复路径分组,在自己的 Trace 上建立基线。
怎样排查“恢复后答案反而错了”?
先定位错误主张第一次出现在哪个恢复步骤。
检查原工具失败前是否已经存在可靠证据,恢复状态有没有把它覆盖。
检查备用来源的证据等级、版本和对象是否与原目标一致。
检查参数修复是否只改错误字段,还是连查询对象也改变。
检查重试返回是否被重复计成多个来源。
检查降级状态是否传到最终生成,还是被回答层当成正常完成。
最后固定原始工具结果做轨迹重放。修复应该在相同故障条件下产生预期恢复,而不是依赖下一次网络刚好成功。
面试官继续追问,怎么接?
追问一:所有超时都应该重试吗?
不应该。要看工具是否幂等、错误是否临时、剩余预算和全局服务状态。写操作或持续故障不能原样重试。
追问二:备用来源返回了答案,为什么还要标记降级?
备用来源的原始性、时效和口径可能不同。恢复了可用性,不代表恢复了相同证据强度。
追问三:页面 403 时能不能换爬取方式?
不能以绕过权限为目标。应尊重访问和内容授权,寻找公开原始来源、请求用户提供材料或明确无法核验。
追问四:工具失败后怎样避免 Agent 循环?
保存规范化动作、错误类型和已尝试策略,限制工具与全局预算。重复同一路径时提示换维度或停止。
追问五:怎样证明容错没有降低答案标准?
故障注入后检查来源等级、主张支持、缺口表达和完成状态,并与无故障基线比较,而不是只看最终有没有文本返回。
工具失败后,完整恢复链怎样说
Deep Research 的工具失败要先结构化分类。参数、临时网络、限流、权限、资源不存在、内容为空、安全拒绝和内部错误,对应的恢复动作不同。只有临时且幂等的错误适合有限退避重试;参数错做最小修复;页面失效回到 Search 找官方迁移;权限问题不能绕过;工具能力不匹配要换工具。
我会让统一网关管理超时、并发、重试、熔断、缓存和日志,错误返回包含调用 ID、类别、是否可重试、预算影响和建议动作。研究状态把已确认证据、失败动作和未完成缺口分开,恢复失败时输出部分完成或明确阻塞,不能用弱来源或猜测伪装正常完成。并行与重试使用版本和幂等 ID,避免旧失败覆盖新证据或重复计数。
验收会注入参数、网络、限流、权限、页面、抽取、重复和状态故障,检查系统是重试、换来源、换工具、降级还是停止,并观察无效重试、尾延迟、证据等级、部分完成可用性和最终主张支持。接口无法保证永远成功,验收目标是在失败时仍保持证据标准和清楚边界。

容错方案要通过的四项核验
拿一次故障注入的 Trace 说明错误怎样分类、状态怎样保护、恢复动作怎样选择,以及最终证据有没有降级。
- 错误是否有结构化类别、可重试标记和预算影响?
- 重试、换来源、换工具、降级和停止是否有明确条件?
- 工具失败时已有证据和状态版本能否被保护并恢复?
- 故障注入是否检查最终证据标准,而不只检查接口成功?