OOOMETA/OS
← 返回洞察

2026 年 9 月 · 5 分钟阅读

失败的工具调用:中位 1.6 秒,p90 顶到上限

失败的工具调用:中位 1.6 秒,p90 顶到上限

关键定义

双峰失败分布 失败调用的耗时不集中在均值附近,而是分成两簇:一簇在秒级返回错误,另一簇停在超时上限。两簇对应不同的根因,也需要不同的处置。

超时上限作为分类器 把顶到超时上限的调用单独计数,用它区分调用没有返回与调用返回了错误两类故障。前者重试无效,需要打断或重新设计。

一次工具调用失败,通常要花多久?我们翻了自家 agent 舰队 2.6 天的日志,423 次失败给出的答案分成两堆:0.4 秒,或者 180 秒,中间几乎是空的。

口径:423 次失败调用

样本是 OOMeta 自建 agent 舰队日志里 423 次返回错误的工具调用,时长取自日志自带的计时字段,窗口为 2026 年 9 月 21 日至 23 日的 2.6 天。需要说明的是,这份文件只记录失败,成功调用的耗时不在其中,所以下面描述的是失败样本的形状,不是全部流量的形状。

分布是双峰,不是长尾

分位数排开是这样的:p25 是 0.35 秒,中位数 1.63 秒,p75 已经跳到 37.96 秒,p90 是 180.55 秒,p95 是 182.11 秒,最长一次记录到 1,876.89 秒。

换算成占比更直观:53% 的失败在 2 秒内返回,16% 停在 170 秒以上,中间地带只占 31%。两簇之间有一段很宽的空档,说明它们根本不是同一种故障。

快簇是命令自己错了:路径不存在、参数不对、被安全门控拦下。慢簇是调用没有返回:等网络、等锁、等一个交互式命令的输入。88 次失败直接写成命令超时,48 次带着退出码 124,也就是系统层面判定的超时。

两类故障对重试的反应相反。快簇重试往往能过,因为它可能只是状态没准备好;慢簇重试毫无意义,因为它上一次就没有返回,下一次大概率还是等在那里。

为什么平均值在这里最没用

如果按平均耗时设一个全局超时,两个峰都会被误判。快簇不需要那么长的时间,慢簇等到上限也不会回来。平均值落在两峰之间的空档里,正好是最没有信息量的位置。

我们的判断

  1. 把超时上限当分类器用。顶到上限的调用单独计数,它的处置是打断和重新设计,不是重试。
  2. 按工具类别设预算,不要全局一个数。终端命令、文件读取、外部接口的时间尺度差两个数量级,用一个数字管它们只会让快的白等、慢的漏过。
  3. 把「不返回」写进运行手册,作为独立故障类。它和「返回错误」的响应动作相反,混在同一处理流程里会互相拖累。

留给买家的一个问题

你的 agent 现在有几个超时值?如果只有一个,那么你已经把两类根因不同、处置相反的故障塞进了同一条处理流程。先别急着调参数,先把这两簇分开计数,你会立刻知道该改的是重试策略还是工具实现。

OOMeta AI

我们按工具类别给 agent 分配时间预算,并把顶到上限的调用单独计数,让它和秒级失败进入不同的处置路径,而不是共用一个平均超时值。

预约诊断会

口径与来源:本文全部数字来自 OOMeta 自建 agent 舰队的一手运行日志,非二手引用,也无外部厂商数据。复现路径:日志文件 ~/.hermes/logs/errors.log,保留窗口 2026-09-21 07:18 至 2026-09-23 20:01(1.4 MB,16,787 行);样本为匹配 Tool returned error 的 423 条记录,时长取该行的计时字段;超时判定取 Command timed out 字符串与退出码 124 的计数;采集时间 2026-09-23 20:10 CST。日志轮转会改变样本量,重跑得到的数字不会与本文完全一致,口径一致。 |外部口径对照:退出码 124 的超时语义见 GNU coreutils timeout 手册 gnu.org/software/coreutils/manual/html_node/timeout-invocation.html(curl HTTP 200);HTTP 429 的定义见 RFC 6585 第 4 节 rfc-editor.org/rfc/rfc6585(curl HTTP 200)。上述两条为术语口径引用,本文数字不依赖外部数据。

常见问题

样本和时间窗是什么?+

423 次失败的工具调用,时长取自日志自带的计时字段,窗口是 2026 年 9 月 21 日至 23 日的 2.6 天。样本只包含失败调用,成功调用的时长不在这份文件里。

中位数是多少?+

1.63 秒,p25 是 0.35 秒。也就是说一半以上的失败在两秒内就已经返回了错误。

慢的那一簇有多慢?+

p75 已经跳到 37.96 秒,p90 是 180.55 秒,p95 是 182.11 秒,基本贴住超时上限;最长一次记录到 1,876.89 秒。

为什么不能按平均值设超时?+

平均值落在两个峰之间的空档里。它既放过不返回的调用,又让秒级失败的调用白等几十秒,两头都判错。

顶到上限的调用该怎么处理?+

当成阻塞等待处理:单独计数、触发打断,并去查它在等什么。这类调用重试不会改变结果,因为它上一次就没有返回。