正文
Circuit Breaker 熔断器机制
Circuit Breaker(熔断器) 在 Agent系统里,指的是一种保护性停止机制:当某个自动恢复路径连续失败、重试已经没有收益时,系统主动停止继续尝试,避免无限消耗 token、大模型API配额和执行时间。
一句话理解:熔断器不是修复错误,而是阻止错误被无限放大。
在 Claude Code 这类 Agent Loop(智能体循环)里,模型会反复经历 “准备上下文 → 调模型 → 执行工具 → 写回工具结果 → 再调模型” 如果 compact(上下文压缩)、模型调用、工具执行或错误恢复没有边界,Agent 很容易在一个失败路径里一直转圈。
一、为什么 Agent 需要熔断器
Agent 的危险点在于它会自动继续。一次失败如果没有边界,可能变成一串失败。
prompt_too_long(提示词过长)后,系统尝试 reactive compact(响应式压缩)。- reactive compact 后仍然超限,系统继续 compact。
- 继续失败后又继续 compact。
- 用户没有得到结果,但请求、时间、token 都在消耗。
熔断器要做的事很简单:失败可以重试,但不能无限重试。
flowchart LR
A[执行请求] --> B{成功?}
B -- 是 --> C[继续任务]
B -- 否 --> D[记录失败]
D --> E{达到上限?}
E -- 否 --> F[重试或恢复]
E -- 是 --> G[熔断<br/>停止自动尝试]
这里的关键不是”失败一次就停”,而是累计失败证据。只有当系统判断继续尝试收益很低时,才进入熔断。
二、真实对话:没有熔断器会怎样
用户:帮我读完整个项目,然后总结架构。
Agent:我先读取项目文件。
系统:Agent 连续读取大量文件,messages(消息列表,保存用户、助手和工具结果的历史记录)迅速膨胀。
Agent:准备调用模型总结。
API:prompt_too_long。
Agent:我做一次 reactive compact,然后重试。
API:还是 prompt_too_long。
如果没有熔断器,后面可能变成这样:
- Agent:我再 compact 一次。
- API:还是
prompt_too_long。 - Agent:我再 compact 一次。
- API:还是
prompt_too_long。 - Agent:我再 compact 一次。
- API:还是
prompt_too_long。
这时系统没有产出任何有效结果,只是在同一个错误上反复消耗资源。带熔断器的处理应该是:
Agent:已经执行过 reactive compact,重试后仍然超限。自动恢复失败,停止继续重试。建议缩小读取范围,或按目录分批总结。
关键理解:熔断器保护的不是某一次请求,而是整个 Agent 循环。
三、Claude Code compact 里的熔断场景
在 Claude Code Context Compact(上下文压缩)里,熔断器最典型的场景是 auto compact(自动压缩)连续失败。
用户:把 src/ 下所有文件都读完,找出认证逻辑的问题。
Agent:开始读取文件。
系统:工具结果持续进入 messages,依次执行:
tool_result_budget(工具结果预算,把大输出落盘)snip_compact(中段裁剪)micro_compact(微压缩)
系统:上下文仍然超过阈值,触发 auto compact。
Agent:保存 transcript(完整对话归档),调用 LLM(Large Language Model,大语言模型)生成 summary(摘要)。
API:摘要请求失败。
系统:记录 auto compact 失败 1 次。
下一轮又失败,记录第 2 次。再下一轮仍失败,记录第 3 次。
熔断器触发:连续失败 3 次后,停止继续 auto compact,避免摘要请求在同一个失败路径里反复消耗 API 调用。
这里的重点不是”3”这个数字,而是连续失败阈值。它表达的是一个工程判断:同一类自动恢复连续失败多次,就不要假设下一次一定会成功。
四、熔断器和重试的关系
Retry(重试)和 Circuit Breaker(熔断器)经常一起出现,但它们的职责不同。
- 重试:给暂时性错误一次恢复机会。比如网络抖动、429 rate limit(请求被限流)、529 overloaded(服务过载)。
- 退避:重试前先等待,常见做法是 exponential backoff(指数退避,失败后等待时间逐步变长)加 jitter(随机抖动,避免大量请求同时重试)。
- 熔断:当重试或恢复达到上限,停止自动继续。
- 降级:熔断后换策略,比如缩小任务范围、切换模型、保存现场、请求用户决策。
可以这样理解:重试负责给机会,退避负责别添堵,熔断负责踩刹车,降级负责换路线。
flowchart LR
A[失败] --> B{可恢复?}
B -- 是 --> C[重试/退避]
C --> D{达到上限?}
D -- 否 --> C
D -- 是 --> E[熔断]
B -- 否 --> E
E --> F[降级或人工接管]
没有重试,系统太脆;没有熔断,系统太莽。
五、Agent 系统里常见的熔断类型
熔断器的分类不必脱离 Agent 场景去讲。对 Claude Code 这类系统来说,最常见的是下面几种。
| 类型 | 触发条件 | Agent 场景 |
|---|---|---|
| 连续失败熔断 | 同一恢复动作连续失败 N 次 | auto compact 连续失败 3 次后停止 |
| 重试上限熔断 | 同一请求重试达到上限 | reactive compact 后仍然 prompt_too_long |
| token 预算熔断 | 上下文或输出预算持续超限 | 大量文件读取后拒绝继续塞入上下文 |
| 工具执行熔断 | 工具多次失败、超时或输出异常 | bash 命令反复失败后停止自动执行 |
| 模型输出熔断 | max_tokens(最大输出 token 数)多次截断 |
continuation prompt(续写提示)达到上限后停止 |
| 服务错误熔断 | 429 / 529 多次出现 | 重试退避后仍失败,停止继续打 API |
| 权限风险熔断 | 操作风险超过自动执行边界 | 删除、覆盖、发布等动作要求用户确认 |
| 成本熔断 | token、费用、时间超过预算 | 长任务自动拆分或要求缩小范围 |
这些类型可以组合。例如一次长任务可能同时触发 token 预算、compact 失败上限、API 退避和工具执行熔断。
六、熔断器通常需要哪些参数
设计熔断器时,不能只写”失败就停”。要把触发、等待、恢复和降级都定义清楚。
- 失败阈值:失败多少次触发熔断,例如连续 3 次 auto compact 失败。
- 时间窗口:在多长时间内统计失败,例如 1 分钟内多次 529。
- 重试上限:最多允许自动尝试几次,例如 reactive compact 只尝试一次。
- 冷却时间:熔断后等待多久再试探恢复。
- 试探请求:恢复前先放少量请求验证是否正常。
- 降级策略:熔断后怎么处理,例如返回错误、缩小范围、切换模型、保存现场、交给用户判断。
- 恢复条件:什么情况下清空失败计数,回到正常流程。
对 Agent 来说,最重要的是降级策略。熔断后不一定只是报错,也可以转成更小、更稳的任务。
例如:
- 原任务:读完整个项目并总结。
- 熔断后:先只总结
src/auth/。 - 原任务:继续 reactive compact。
- 熔断后:要求用户选择”分批读取”或”只保留最近上下文”。
- 原任务:继续调用失败模型。
- 熔断后:切换 fallback model(备用模型)或暂停等待。
七、最终理解
熔断器是一种边界机制。它不负责把错误变成功,它负责在自动恢复失效时停止损耗。
在 Agent 系统里,它回答的是这个问题:当压缩、重试、退避、续写、切换模型都没能解决问题时,系统什么时候应该停下来?
答案不是”永远继续”,而是:
- 到达阈值就停止。
- 保留现场。
- 换更小的任务、更稳的模型或让用户决策。
这就是熔断器的价值:让自动化有边界,让失败可控。