转载--AI Agent 架构设计:工具调用失败了怎么办——重试、换方案、还是报告(OpenClaw、Claude Code、Hermes Agent 对比)

原文连接:https://mp.weixin.qq.com/s/egIfy43mYjs6ghsTq7Ctlw

工具失败不是例外,是常态

在一个复杂任务的执行循环里,工具调用失败是高频事件。

API 超时。文件权限拒绝。数据库连接断开。命令行工具找不到依赖。外部服务返回 5xx。速率限制触发 429。

普通软件处理这些问题有清晰的模式:try-catch、重试逻辑、断路器、错误码。这些是确定性的------程序按照预先写好的逻辑处理,行为可预测。

Agent 的问题在于:工具失败后,下一步是什么,最终是由语言模型决定的。

模型可能重试,可能换方案,可能向用户报告,也可能------这是最危险的情况------静默地用一个相似但不同的操作替代失败的操作,然后汇报"任务已完成"。

一个核心问题,三种答案

工具失败后,系统面临一个最根本的问题:

谁来决定接下来怎么办?

是框架的程序逻辑?还是语言模型自己判断?还是两者的某种组合?

三个框架对这个问题给出了截然不同的答案:

  • Claude Code:程序先分类,再决定怎么处理。可以重试的自动重试,不能重试的强制上报,超过阈值的熔断停止。模型的自主空间被限制在明确的边界里。

  • OpenClaw:错误注入上下文,交给模型自己判断。没有程序级分类,没有强制的重试上限,行为完全取决于模型的决策。

  • Hermes Agent:框架层有固定 3 次的重试,超过之后交还给模型判断。听起来有程序约束,但实际上有一个已知的严重 Bug,导致任务未完成时 Agent 会静默"汇报完成"。

Claude Code:程序分类 + 数据驱动的熔断器

错误分类是设计核心

Claude Code 的工具失败处理集中在 QueryEngine.ts,核心是对失败进行分类:

复制代码
可恢复失败(框架自动处理):├── 网络超时      → 退避后重试├── 速率限制 429  → 读取 retry-after 头,等待后重试└── 临时 503      → 退避后重试不可恢复失败(注入上下文,交给模型判断):├── 权限拒绝 403  → 不重试,告诉模型├── 格式错误 400  → 不重试,告诉模型└── 工具不存在    → 不重试,告诉模型

这个分类的价值在于:临时性的失败(网络抖动)不打扰用户,框架自动处理;确定性的失败(权限错误)不做无意义重试,直接让模型判断下一步。

把所有 LLM API 调用逻辑集中在一个模块里,是这个设计最重要的架构决策------不同工具的重试行为一致,调试有明确的入口。

熔断器:来自真实生产数据

最值得关注的是 Compaction 失败的熔断器:

复制代码
MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES=3

这个数字不是拍脑袋的。Anthropic 工程师用 BigQuery 分析生产数据发现:1,279 个会话出现 50 次以上连续 Compaction 失败,单个会话最多重试 3,272 次,每天浪费约 25 万次 API 调用。

连续失败超过 3 次,停止重试,强制上报用户。这是从真实生产事故里推导出来的阈值,不是预先猜测的。

源码里还有一个容易被忽视的机制:连续 3 次工具调用产出少于 500 Token,系统判断"继续没有意义",主动终止循环。

OpenClaw:模型自主判断,两个已知的生产问题

工具调用失败时,错误信息作为 tool_result 注入上下文,模型决定下一步:重试、换方案还是报告。

没有错误分类,没有内置重试次数限制,没有强制通知机制。

理想情况下,这个设计工作良好。在多重失败叠加时,有两个已记录的生产问题:

问题一:静默挂起 600 秒

当工具调用卡住(RPC 死锁、Provider 超时),Agent 会静默挂起最长 600 秒------这是源码里 DEFAULT_AGENT_TIMEOUT_SECONDS 的默认值。

600 秒期间:飞书消息排队但不处理,界面无任何活动,用户完全不知道发生了什么。

Issue #8288 记录了真实案例:一天内发生三次,累计超过 8 小时宕机。唯一的恢复方式是删除 sessions.json 重启 Gateway------代价是 Agent 的全部会话历史。

问题二:级联 Fallback 失败

Issue #49732 记录了另一个生产事故:配置了三个 Fallback 模型(Opus → GPT-4o → Sonnet)。Opus 触发限流后,OpenClaw 把整个 Anthropic provider 标记为冷却状态,导致 Sonnet 也无法使用------尽管 Sonnet 本身没有任何问题。

结果:三个 Fallback 同时失效,Agent 向用户输出了一大段原始错误日志,而不是一个友好的"暂时不可用"提示。

根本问题:一个模型的失败传染了整个 Provider 的可用性。

Hermes Agent:重试三次,然后可能悄悄告诉你"完成了"

Hermes 处理工具失败的方式很简单:失败了,重试,最多试三次。

复制代码
第一次失败 → 重试(attempt 1/3)第二次失败 → 重试(attempt 2/3)第三次失败 → 放弃,告诉用户连接失败

这是你实际用下来感受到"不断重试"的原因------它就是在重试,而且不管什么类型的失败,一律重试三次,不分青红皂白。

三次之后放弃,接下来怎么办?交给模型自己判断。这一点和 OpenClaw 一样。

但 Hermes 有一个更危险的问题,藏在重试逻辑里。

当工具执行成功了,但模型的回复是空的(这种情况会发生),Hermes 的处理逻辑是这样的:

回复是空的?→ 去找上一轮有没有留下什么旧文字 → 有的话,把旧文字当作最终答案发出去,然后结束任务

问题在于:旧文字是上一轮说的话,当前任务还没做完。但 Hermes 拿着旧文字发出去,然后退出了------任务未完成,但它告诉你"好的,完成了"。

你看到的是一个正常的回复,不知道任务实际上停在半路。没有任何提示,没有任何警告。

这个 Bug 在 GitHub 上有详细记录(Issue #9400),目前还没有修复。

那么,自己的 Agent 应该怎么设计?

三个框架走过的弯路,已经给出了答案。

**第一:失败必须分类,不能一律重试。**网络抖动重试有意义,权限错误重试没有意义。Hermes 对所有失败一律重试三次,Claude Code 先判断类型再决定怎么处理------后者对资源的浪费更少,行为更可预测。自己设计时,至少区分两类:临时性失败(可以重试)和确定性失败(直接上报)。

**第二:重试必须有上限,上限必须来自数据。**OpenClaw 没有内置上限,生产中出现了单个会话重试 3,272 次的情况。Claude Code 的熔断器上限是 3,来自真实生产数据。不要猜这个数字,用你自己的任务数据来定。

第三:失败必须告诉用户,不能让 Agent 自己消化。 三个框架里最危险的设计,都是让 Agent 在失败后自己绕路、自己汇报完成。Hermes 的 Bug 让工具成功但回复空了的情况变成了"假完成"。你的 Agent 应该有一条原则:不可恢复的失败,必须停下来告诉用户,不能继续往下跑。

**第四:失败之后能接着跑,比从头再来重要得多。**OpenClaw 恢复靠删会话文件,代价是全部历史。Claude Code 和 Hermes 用持久化存储保住了任务状态。设计你的 Agent 时,任务状态和对话历史要分开存------对话可以丢,任务进度不能丢。

相关推荐
Deepoch2 小时前
面向工业现场自主运维:Deepoc 具身模型开发板的端侧智能升级路径
运维·人工智能·科技·巡检机器人·deepoc
科技牛牛2 小时前
AI爬虫引爆代理IP产业:一场正在发生的数据粮草争夺战
人工智能·爬虫·tcp/ip·数据安全·ip地址查询
涤生大数据2 小时前
AI时代,SQL该何去何从?
数据库·人工智能·sql
冬奇Lab2 小时前
RAG 系列(十一):Rerank——让检索结果按重要性排队
人工智能·llm·源码
冬奇Lab2 小时前
一天一个开源项目(第96篇):OpenHarness - 轻量级 AI 代理基础设施框架
人工智能·开源·资讯
lulu12165440783 小时前
JetBrains IDE 终极AI编程方案:CC GUI插件让Claude Code和Codex丝滑运行
java·ide·人工智能·python·ai编程
TENSORTEC腾视科技3 小时前
腾视科技重磅推出AI NAS,重塑数据管理方式,开启智能高效新时代
人工智能·ai·七牛云存储·nas·企业存储·ainas·家庭存储
tanis_20773 小时前
MinerU2.5-Pro 中文 PDF 识别准确率全解:OmniDocBench v1.6 权威基准数据
人工智能·python·pdf
我是发哥哈3 小时前
跨AI模型生成视频的五大维度对比:选型避坑指南
大数据·人工智能·学习·机器学习·chatgpt·音视频