供应商 99.9% 的 SLA 对你的 Agent 来说衡量边界错了
一个模型提供商发布了 99.9% 的可用性 SLA。采购团队将其理解为“三个九,每年四个小时的停机时间,对于非 0 级(非核心)工作负载是可以接受的”。六个月后,智能体(Agent)功能上线,值班仪表板显示用户感知的任务成功率约为 98% —— 这个数字没有写进任何合同,在提供商的状态页面上也找不到,而且没有人为此负责。提供商满足了他们的 SLA,而产品却没达到其 SLO。两者同时成立,而这种差距并不是一个 bug —— 这是一个算术问题。
大多数团队都忽略了算术这部分。提供商的 99.9% 是针对同步请求工作负载进行衡量的 —— 一个用户,一个提示词,一个响应,一个计费事件。而智能体并不会产生这种工作负载。一个用户感知的任务会扇出(fan out)为 8 到 20 次推理调用,它会对瞬时错误进行重试,对慢速调用进行对冲(hedge),并聚合部分输出。每一次调用都是对提供商故障分布的一次独立抽样,如果任何关键调用失败,任务就会失败。SLA 覆盖的边界和用户感受到的边界并不是同一个边界。
这篇文章讨论的是背后的数学逻辑、本应存在但实际缺失的合同条款,以及在用户发现之前揭示这种差距的可观测性工作。一个反复出现的主题是:供应商的 SLA 是对其进行基准测试的工作负载的声明,而你的智能体产生的并不是那种工作负载。
无人协商的组合数学
串联可用性(Series availability)是一个教科书级的案例。如果一个系统依赖于 N 个组件,每个组件的可用性为 A,且当其中任何一个组件失败时任务就会失败,那么总可用性大约为 A^N。三个可用性均为 99% 的组件组合在一起,总可用性只有 97%。二十个可用性均为 99.9% 的组件组合在一起,总可用性为 98.0%。数学是无情的:冗余可以帮你恢复,但一连串的独立调用会使故障概率倍增,而不是成功概率。
带入行业中的真实数字。据报道,在最近的 90 天窗口内,某主要模型 API 的提供商可用性低至 98.95%,另一家整体约为 99.76%,其 API 组件偶尔会长时间跌至 99% 以下。这些是真实的、近期的运行数据 —— 而不是营销口号里的 99.99% —— 它们之所以存在,是因为基础模型基础设施还很年轻,且受到的容量限制是成熟的云 API 所不曾有的。
现在将其与智能体循环结合。假设你的智能体为每个用户任务进行 12 次推理调用 —— 1 次规划器(planner)调用、4 次检索接地(retrieval-grounding)调用、4 次工具结果摘要调用、2 次重新规划以及 1 次最终综合。在每次调用可用性为真实的 99.5% 时,任务可用性约为 0.995^12 ≈ 94.2%。这意味着每月有超过 30 小时的任务失败,而对应的提供商在合同层面却完美达成了 99.5% 的目标。在单次调用 99.9% 的情况下,你得到的任务可用性是 98.8% —— 仍然比提供商状态页面显示的要差一个数量级的错误率。
你签署的 SLA 描述的是提供商负载均衡器可以测量的边界处的单次调用可用性。而你的用户所感受到的数字是你的产品所属边界处的单次任务可用性。这里没有阴谋 —— 只是两个不同的分母而已。
重试无法修复问题;它们在另一个维度上让情况变得更糟
第一直觉是增加重试。来自速率限制器的 429、来自故障区域的 503、来自慢速节点的超时 —— 这些大多数会在几秒钟内恢复,重试可以恢复调用。于是团队增加了带抖动的指数退避(exponential backoff with jitter),并认为问题解决了。
事实并非如此。重试改变了故障分布,但它们引入了三种提供商 SLA 未覆盖的新故障模式:
成功但缓慢路径上的延迟税。 超时重试策略会将一个慢速调用变成“慢速调用+重试调用”。如果 5% 的调用触发了 10 秒超时,并重试后在 2 秒内成功响应,你就将 P95 延迟提高了一倍,而用户感知到的这种减速是任何单次调用 SLA 都无法捕捉到的。在预热过的提供商层级上运行串行调用的评估平台永远看不到这一点。
反馈至速率限制的重试风暴。 发生故障的提供商区域返回 429。你的重试策略向同一区域又发送了三个请求。每一个这样做的智能体都 会将负载放大 3 到 4 倍。如果在故障期间你的集群中有 10% 正在重试,那么有效负载会在提供商最无法处理的时候剧增。提供商并没有违反他们的 SLA —— 他们返回了正确的 429 —— 但你的系统自我放大了问题。重试风暴在几秒钟内将负载放大 10 倍,是智能体集群中已证实的生产环境模式。
失败路径上的成本放大。 一个包含 12 次调用的任务,如果在最糟糕的一次调用上重试三次,就变成了 15 次调用。在故障期间的整个集群中放大这一点,你就会看到一笔可观的每月成本支出,而这仅仅是因为提供商稍微有些不稳定。你的财务团队会在你的 SRE 团队发现原因之前先看到账单。
重试策略正在准确执行它的设计功能。问题在于,“瞬时错误”和“用户感知的任务失败”是不同的事件,为前者校准的修复方案并不能改善后者。
那些应该存在但尚未出现的合同条款
大多数 LLM 供应商的合同都继承了同步 Web API 合同的 SLA 架构。它们以单次请求为界限,探讨可用性百分比和赔偿额度阈值。而真正能保护智能体(Agent)工作负载的条款通常是缺失的。一旦采购团队理解了其中的计算逻辑,在续约时争取这些条款将是杠杆率最高的举措之一。
针对扇出(Fanout)的速率限制突发余量(Burst Headroom)。 标准的速率限制条款是一个稳态上限:每分钟 N 次请求。Agent 不会产生稳态负载——它们产生的突发负载与用户的任务到达模式一致 ,每个任务会快速连续触发 10-20 次调用。相比于将稳态上限提高 50%,在短时间内(例如 15 秒内达到稳态限制的 4 倍)提供明确的突发预算条款要有用得多。
针对瞬时故障的重试容错赔偿。 大多数 SLA 赔偿触发条件是基于供应商视角的“请求”计算出的错误率超过某个阈值。你应该协商一种赔偿核算方式,将“重试后最终成功”的调用也视为部分失败——虽然供应商的指标在第二次尝试时将其计为完全成功,但它们消耗了你的延迟和 Token。
Token 间延迟(Inter-token latency)上限,而非仅仅是首个 Token 耗时(TTFT)。 流式传输 SLA 通常只覆盖首个 Token 耗时。用户感知到的是 Token 间的抖动,而不是首个 Token 的延迟。供应商可能达到了 TTFT 上限,但在响应中途出现了 3 秒的停顿,这在用户看来就是“挂了”。应争取将 p99 Token 间延迟写入合同指标,或者至少作为公开的 SLI。
具有 Prompt 版本一致性的多区域故障转移。 当一个供应商区域发生故障,你路由到另一个区域时,模型版本、Prompt 缓存状态,甚至分词器(Tokenizer)版本都可能存在细微差异。如果合同条款要求跨区域锁定模型版本并承诺协调滚动更新(这样你就不会在区域切换期间遇到跨版本偏差),就能避免一整类看起来像回退(Regression)实则是路由副作用的事故。
协商这些条款的成本相对于交易规模通常很小。而不具备这些条款的代价,则会在三个季度后转化为繁重的事故处理工作。
