Skip to content
预计 1 分钟右侧目录可快速定位

模型调用失败后怎么处理:Error Taxonomy、Routing 与 Fallback ​

前置:如何隔离 Provider 差异:Streaming、Adapter 与 Capability
核心问题:同样是一次 Model Call 失败,哪些错误可以重试、哪些应该换模型、哪些必须立即暴露给 Runtime?

429、context overflow、schema rejection、provider outage 和“当前模型不支持所需 capability”虽然都表现为 model call 失败,但处理方式完全不同。只有先把错误归类,Routing / Fallback 才能在不静默改变能力和安全语义的前提下做选择。

Model Error Taxonomy ​

模型调用失败后,真正重要的不是“报了什么错”,而是 Runtime 下一步应该重试、修改请求、换模型,还是结束当前路径。

类型实际含义常见处理
transport网络连接失败,请求可能没正常完成backoff 后有限重试
rate-limitProvider 暂时拒绝更多请求等待 / 限流后重试
timeoutdeadline 内没拿到可接受结果有剩余预算时重试
context overflow输入超过可处理范围裁剪 / compaction 后重建请求
invalid output返回成功,但不符合 schema/contract校验错误反馈给模型,有限 repair
provider unavailable整个服务暂时不可用尝试兼容 fallback
semantic failure调用技术上成功,但模型决策明显不对replan、验证或升级模型

例如 context overflow 不能原样 retry:

text
Context 太大
→ 原样 retry         ×

正确:
Context 太大
→ 缩减 history / retrieval / tool result
→ 重建 Context
→ retry

因此 Error Taxonomy 的价值是把失败原因映射到恢复动作,而不是多维护几个异常类。

🔍 源码对照:Router 的职责边界:选择 Provider + 串行化 Agent Turn ​

精确定位

ts
function dispatchSendPrompt(agentId, request) {
  const previous = queues.get(agentId) ?? Promise.resolve()
  const next = previous
    .catch(() => undefined)
    .then(() => execute(currentProvider(), request))

  queues.set(agentId, next.finally(() => clearIfCurrent(agentId, next)))
}

async function execute(provider, request) {
  const bridge = provider === "claude-code" ? await createMcpBridge() : null
  return runRoutedProviderText(provider, messages, bridge ? { mcpServerUrl: bridge.url } : { tools })
}

对照理解

  • Router 先读取当前 provider,再把同一 agent 的请求串进 per-agent Promise queue,避免 Turn 顺序被并发打乱。
  • Claude Code 走本地 MCP bridge,而其他 provider 可以直接获得 Tool definitions;这是 provider capability adaptation,不是通用 fallback 算法。
  • Routing 是调用前选择路径;队列、transcript 持久化、stream update 则属于 coordinator/runtime 责任。

Model Routing / Fallback ​

Routing 和 Fallback 发生在两个不同阶段:

text
Routing  = 调用前选择哪个模型
Fallback = 已选模型失败后决定如何恢复

Routing 不能只看 token 长度。40K token 的日志摘要可能很简单,而 30 行并发代码的死锁分析可能很难。更合理的顺序是先按 capability 过滤,再比较质量、成本、延迟和风险:

text
任务要求:tool calling + structured output + context >= 64K
        ↓
排除不满足能力的模型
        ↓
在剩余候选中比较 quality / cost / latency

Fallback 也不是“换一个模型继续调”。备用模型至少要继续满足当前任务依赖的能力和输出契约。否则 Planner 原本返回结构化 Plan,换成只会 plain text 的模型后,Runtime 就无法继续 validate / compile / execute。

还有一类是 quality escalation:模型没有报错,但连续做出差决策,此时可以把任务升级到更强模型。这和 Provider 503 后的故障 fallback 是两种不同恢复路径。

Failure Modes ​

把所有错误统一 Retry ​

context overflow、schema 不兼容、权限错误原样重试通常不会自愈,只会消耗 deadline 和 token。RetryPolicy 应先看 normalized error kind。

Fallback 静默降低能力 ​

主模型失败后切到不支持 structured output / required tools 的模型,却继续按原 contract 执行,会让错误从“调用失败”变成更难发现的语义错误。Fallback candidate 必须先做 capability compatibility check,并把切换原因写入 Run Manifest。

源码对照(B 类) ​

Grok Bot reconstruction 的 inference-router.ts 可作为 provider routing 的案例,但 routing/fallback 的语义仍以本文 error taxonomy 与能力兼容性为准。 - 源码导航:Grok Bot Source Map

自测 ​

  1. 分别遇到 rate limit、context overflow、invalid structured output 和 semantic failure 时,哪些适合原模型重试,哪些更适合 fallback,哪些应直接交回 Runtime?
  2. 为什么“所有 ModelError 都指数退避重试”会同时浪费预算并隐藏不可恢复错误?挑一种错误说明。

Sources ​

AI Engineering · Agent · Harness · Backend Systems