把一个自主智能体(autonomous agent)丢进生产环境,最先崩溃的往往不是能力,而是账单。2026年5月,一个开发团队眼睁睁看着单个自主体在4小时内烧掉2,847美元——而此时他们所有的监控仪表盘全绿。这种"语义性失败"是21世纪的无限循环:API返回的是HTTP 200,延迟正常、CPU几乎不动,但每一次迭代都在以指数速率烧token。本文基于2026年四份生产级复盘报告,拆解自主体烧钱的五种失效状态——自愈死循环、重试风暴、上下文二次方膨胀、影子重试、方案无限膨胀——并给出从"保险丝"升级到"熔断器"的工程解药。核心结论:步数上限(step budget)只是事后吹断的保险丝,真正的防线是运行时美元熔断 + 语义循环检测,二者配合可把单次风暴成本从2美元压到0.01美元,降幅200倍。
| 烧钱态 | 触发机制 | 放大倍数 | 监控盲区 | 首选解药 |
|---|---|---|---|---|
| ①自愈死循环 | 解析失败→重喂错误→重复幻觉 | 4小时=$2,847 | 仪表盘全绿(HTTP 200) | 语义错误计数器(连错3次熔断) |
| ②重试风暴 | 全上下文×重试×级联 | 3^5=243次理论值 | 200×成本差隐藏在并发里 | 工具级熔断+退避抖动 |
| ③上下文二次方膨胀 | 历史每轮重计费 | 43.3×(vs单遍) | 缓存只省系统提示 | 滑动窗口+协调-专家架构 |
| ④影子重试 | LLM自己决定再试一次 | 与基础设施重试叠加 | 双重重试链路不可见 | 工具层幂等+调用指纹去重 |
| ⑤方案无限膨胀 | 生成百万token计划永不执行 | 单步+20%~数百倍 | "看起来在思考" | 预算性提前评估+计划体积上限 |
这是最经典的烧钱剧本,也是团队最晚发现的。其机制极其简单:自主体被赋予"自我修复"能力,当LLM返回的JSON有语法错误时,解析层抛异常,自主体把错误信息原样塞回去——"你提供的JSON无效,请修复并返回完整报告"。LLM再次产生同一个幻觉。循环往复。
n1n.ai记录的真实案例把这个剧本量化了:一个负责生成复杂JSON报告的GPT-4o高上下文自主体陷入"重构循环",反复试图修复一段超出其自身输出限制的代码片段——本质上是在反复把一加仑水倒进一品脱杯里。关键数据:每次迭代成本约11.80美元,每分钟迭代4次,持续240分钟,理论峰值11,328美元,实际落地2,847美元。
# 烧钱态①的自愈死循环(反模式)
while not task_complete:
response = llm.create(messages=context)
try:
report = parse_json(response)
return report
except JSONError as e:
# 致命:把错误原样塞回,触发重复幻觉
context.append({"role":"user",
"text": f"你提供的JSON无效:{e},请修复并返回完整报告"})
# 没有"连续失败计数",没有预算检查
它的恐怖之处在于可观测性的彻底失效。传统微服务监控的是"黄金信号"——延迟、流量、错误、饱和度。当服务出故障,你看到5xx;当过载,延迟飙升。但自主体的失败是语义性的,不是结构性的:每次调用都返回HTTP 200,延迟一致,本地CPU几乎为零(重活在LLM那头)。Datadog和New Relic看到的全是健康的绿色,而你的账单正在指数级膨胀。解药是引入语义错误检测器——当解析器连续三次返回相同错误时,立即升级到人工或切换到更重的推理模型(如o3)打破循环,而不是无限重试。
分布式系统工程师跟重试放大(retry amplification)斗了几十年,但自主智能体把它放大到了一个全新的量级。原因在于成本结构:传统微服务一次重试只花费一次HTTP往返;自主体每次重试都要把完整对话上下文重新提交给LLM。
tianpan.co给出了一个干净的算例。一个带着8,000 token对话上下文的自主体调用某工具,返回429限流。采用naive的3次重试策略:
一次生产团队在API中断期间实测:失控重试在30秒窗口内为单次对话消耗约2美元token,熔断后降到约0.01美元——200倍的成本削减。
更危险的是三种放大模式会叠加。纵向放大(单工具内重试)是基础款,但自主体有个特有变种——LLM看到上下文里的失败响应,会自己决定再调一次同一工具,形成独立于你工具层重试逻辑的"影子重试"。横向放大(跨工具级联)中,5个串行依赖步骤若各自3次重试,单点失败理论可产生3^5=243次重试,实践中常见10–50倍放大。递归放大(多智能体委派)最致命:Agent A→B→C,C的工具失败,B重试整个工作流(含对C的委派),A再重试整个工作流(含对B的委派),呈指数级爆炸。传统的熔断器在递归委派这种树形结构上表现最差。
# 烧钱态②的指数退避+抖动(正确姿势)
import random, time
def call_tool_with_breaker(tool, args, breaker, max_retries=3):
for attempt in range(max_retries):
if breaker.is_open(tool.name): # 工具级熔断:先查闸门
return FallbackResponse()
try:
return tool.invoke(args)
except TransientError as e:
breaker.record_failure(tool.name)
delay = min(2**attempt, 32) + random.random() # 指数退避+抖动
time.sleep(delay)
breaker.trip(tool.name) # 连续失败→跳闸,后续直接短路
raise CircuitOpen(tool.name)
这是最隐蔽的烧钱态,因为它不是bug,而是naive架构的数学必然。大多数LLM API是无状态的:每次调用都要把完整对话历史发回去并计费。自主体循环是状态化的——每轮迭代后,工具输出、观察、推理轨迹都被追加到消息历史。这意味着第N步要为前N-1步的内容全部重新付费。
augmentcode给出了精确的成本公式:
Total_naive = N×S + u×N(N+1)/2 + r×N(N-1)/2
# S=系统提示, u=每轮新增输入, r=每轮输出, N=总迭代数
那个 N(N+1)/2 的三角数项就是成本陷阱。一个20步、每步生成1,000 token的循环,累积输入token是210,000,而按"每步估算"你只会预期20,000——10倍的差。
在Claude Sonnet 4.6($3.00/$15.00 每百万input/output token)上的实测更扎眼。一个文件读取自主体(S=1,000系统token,u=8,000/轮,r=500/轮,N=10):
| 架构 | 总输入token | 总成本 | 相对单遍 |
|---|---|---|---|
| naive 10步循环 | 472,500 | $1.49 | 43.3× |
| 约束式(W=2滑动窗口) | 260,000 | $0.86 | ~29× |
| 单遍 | 9,000 | $0.03 | 1.0× |
很多人第一反应是上prompt caching,但缓存只解决公式里的 N×S 项(固定系统提示部分)。在Claude Sonnet 4.6上,缓存读取是$0.30/1M,对比未缓存的$3.00/1M,前缀能省90%。但不断增长的对话历史才是多步循环的主导成本,而每个新的工具输出和推理轨迹都是逐轮唯一的,无法被缓存。缓存降低了 N×S,却原封不动地保留了那个二次方的 N(N+1)/2。真正的解药是滑动窗口(只保留最近W轮) 和 协调-专家架构(coordinator-specialist,把上下文裁剪到每步必需的最小集),把472,500 token直接砍到260,000。
这是tianpan.co点出的、被绝大多数团队忽略的烧钱态。在传统微服务里,重试逻辑住在基础设施层(比如Envoy、Resilience4j),完全可控。但在自主体里,LLM本身就是重试决策者:它看到上下文里的失败响应,自行决定再调一次同一个工具。这创造了一条独立于你工具层重试逻辑的"影子重试链路"。
后果是双向叠加:你的工具层配了3次退避重试,LLM又在语义层决定"我换个参数再试5次",于是对一次底层故障产生了15次甚至更多调用。更隐蔽的是,agent的上下文现在装满了原始失败历史,模型可能持续尝试同一调用的变体,每次都把累积的失败历史随新请求一起发送——这又直接喂回了第三态的二次方膨胀。影子重试是第二态(重试风暴)和第三态(上下文膨胀)的乘法器。
# 烧钱态④的语义循环检测(破解影子重试)
import hashlib
from collections import deque
class SemanticLoopDetector:
def __init__(self, window=7, repeat_threshold=3):
self.recent = deque(maxlen=window)
self.threshold = repeat_threshold
def observe(self, tool_name, args):
# 关键:对 工具名+参数 指纹化,而非仅工具名
fp = hashlib.md5(f"{tool_name}:{sorted(args.items())}".encode()).hexdigest()
count = sum(1 for h in self.recent if h == fp)
self.recent.append(fp)
if count >= self.threshold:
raise LoopDetected(f"{tool_name} 在窗口内重复 {count} 次,疑似影子重试")
# 效果:read_file('/etc/config') 连调5次→立即熔断,而非等账单爆炸
防御影子重试的核心是语义循环检测:对每次工具调用连同其参数做哈希,在滑动窗口里查重复。如果自主体在过去7步里调了5次 read_file("/etc/config"),那就是影子重试的铁证,立即熔断——而不是等到步数预算吹断才发现。这是把可观测性从"结构层"推进到"语义层"的关键一跃。
前四态都是"停下来之前烧光",第五态则是"根本没停下来就在烧":自主体生成一个百万token级别的计划,然后永远不去执行。tianpan.co描述的症状是"它生成一个永远不执行的百万token计划",以及"它在两个前置条件互相否决的计划之间反复振荡"。
这类烧钱更阴险,因为它看起来像在认真思考——输出长、推理深、仪表盘显示"working"。augmentcode的研究补充了量化维度:上下文中像 AGENTS.md 这类项目说明文件,会让单次会话推理成本上涨超20%,但对复杂任务的成功率提升微乎其微,有时甚至降低。原因在于,更宽的上下文诱导自主体更广泛地探索——而这种探索往往是反生产的,即"越探索越错越烧钱"。
第五态的深层问题是成本密度的高度不均。一个调用推理模型、带着200K上下文窗口的步骤,比一个调用小模型、短提示的步骤贵几百倍。一个统一的步数预算(比如50步)对单遍检索自主体和深度研究自主体是完全不同的成本天花板。当任务难到撑爆预算时,团队的本能是把预算翻倍——但翻倍一次,下一次失控的爆炸半径就翻一倍。保险丝越换越大,线路还是原来的线路。解药是对每个工作流做预评估(pre-flight):在执行前估算计划体积与预期产出比,给计划本身设token上限,超限直接驳回重来,而不是放任它思考到天亮。
把五态压成一句话:步数上限是保险丝,自主体需要的是熔断器。保险丝的致命缺陷是它在损害发生之后才吹断——而到那时,token账单已经四位、下游API已限流、对话历史已膨胀、客户会话已超时十几次。
二者的本质区别在于三个维度,熔断器全胜:
| 维度 | 步数上限(保险丝) | 真正的熔断器 |
|---|---|---|
| 触发时机 | 事后(已做完N件事) | 事前(探针半开状态先行试探) |
| 成本粒度 | 步数≠成本(推理步贵几百倍) | 美元/tenant实时累计 |
| 信号类型 | 滞后("做太多") | 前瞻(语义重复+费率感知) |
工程上,最低限度的防线是三层叠加:第一层是每任务/每租户的运行时美元熔断器(active cost enforcement),从LLM响应的usage元数据实时累计花费,超阈值直接抛 BudgetExceededException,绝不靠次日账单邮件兜底;第二层是语义循环检测器(见第四态代码),用工具调用指纹+滑动窗口在前瞻地拦住重复;第三层才是步数上限,作为最后的物理兜底。企业级还需按租户归因——若某个客户的数据触发幻觉循环,只熔断该租户而非整个API。
# 生产级三层防线:美元熔断 + 语义检测 + 步数兜底
def run_agent_safely(task, breaker_usd=5.0, max_steps=20):
budget = CostCircuitBreaker(limit_usd=breaker_usd)
loop = SemanticLoopDetector(window=7, repeat_threshold=3)
steps = 0
while not task.done:
if steps >= max_steps: raise MaxSteps(steps) # 第三层:物理兜底
steps += 1
resp = llm.create(messages=task.ctx)
budget.track_usage(resp.usage) # 第一层:美元熔断
for call in extract_tool_calls(resp):
loop.observe(call.name, call.args) # 第二层:语义检测
task.ctx = narrow_context(task.ctx, window=2) # 压制第三态膨胀
result = call_tool_with_breaker(...) # 第二态工具级熔断
task.advance(result)
flowchart TD
A[自主体任务启动] --> B{运行时美元熔断器}
B -->|未超阈| C[调用LLM]
B -->|超阈| Z[BudgetExceeded 终止]
C --> D[解析工具调用]
D --> E{语义循环检测<br/>指纹+滑窗}
E -->|首次/正常| F[执行工具]
E -->|窗口内重复≥3次| Y[LoopDetected 熔断]
F --> G{工具级熔断器<br/>退避+抖动}
G -->|成功| H[追加结果到上下文]
G -->|瞬时错误| G
G -->|连续失败跳闸| X[CircuitOpen 短路]
H --> I{narrow_context<br/>滑动窗口W=2}
I --> J{步数≥max?}
J -->|否| B
J -->|是| W[MaxSteps 兜底]
style Z fill:#ffcccc
style Y fill:#ffe0b3
style X fill:#ffe0b3
style W fill:#ffcccc
style I fill:#c8e6c9
三层闸门(美元/语义/步数)形成纵深防御:最贵的美元熔断在最外层,最廉价的步数兜底在最内层,中间夹着语义检测与工具熔断——任何一个状态命中,都比"跑到账单爆炸"早得多。
个人/原型阶段(< $50/月):只上步数上限(max_steps=15)+ 简单重试上限(max_retries=3)。这个量级保险丝够用,不值得为熔断器写代码。但务必在循环里加 narrow_context 的滑动窗口,否则第三态的二次方膨胀会让你在20步时付10倍的钱。
SaaS多租户生产($$$/月):三层防线必须齐全,且美元熔断器必须做到per-tenant。这是规避2,847美元惨案和200倍重试风暴的底线。配套可观测性要从结构信号升级到语义信号——监控"连续相同解析错误计数"和"工具调用指纹重复率",而不是只看HTTP状态码。优先用便宜模型(如DeepSeek-V3)做输出校验,再决定是否进入昂贵的下一步。
深度研究/编程自主体(高上下文、长程):第三态是主战场。必须用协调-专家架构把每步上下文裁到最小,并接受"缓存只能省系统提示"的现实。给计划本身设token预算(pre-flight),第五态的百万token计划在生成阶段就该被驳回。影子重试(第四态)在这种长程场景最猖獗,语义循环检测器不可省。
一句话决策:如果你的自主体会调用付费工具、会自我修复、或会多步推理——它一定会陷入某一种烧钱态。区别只是你用2,847美元学会,还是用一行 CostCircuitBreaker 提前拦住。
[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
