[控场AI]
· 6 分钟阅读· 3,098 字

无人值守Claude循环一夜烧掉13%额度,我总结了三道保险

无人值守Claude循环一夜烧掉13%额度,我总结了三道保险

无人值守 LLM 循环因缺少退出条件一夜烧掉 13% 套餐额度,作者总结三道硬上限保险。

作者复盘了一次真实事故:一个没有停止条件的 LLM 循环在无人看管下跑了一整夜,Claude 套餐用量上升 13 个百分点。文章先解释了 Claude 套餐限额的共享机制——聊天应用与 Claude Code 共用同一个池子,终端用量分解不包含应用侧消耗;接着说明切换模型只在提示点名具体模型时有效,通用限额下无济于事。根因被明确为循环缺少退出条件,换便宜模型只是烧得慢一点。作者给出的解决方案是至少设置两道硬上限:连续失败次数、总调用次数、墙钟时间,并提前测试守卫逻辑。文章还特别提醒 429 冷却不是上限而是恢复机制,会让循环在每个新限额窗口自动复活。最后附上无人值守运行前的五项检查清单。

无人值守 Claude 循环一夜烧掉 13% 额度,我总结了三道保险

一个没有停止条件的 LLM 循环,在订阅账户上自己跑了一整夜,醒来时套餐用量掉了 13 个百分点。这不是单价问题——代码里根本没有能结束循环的逻辑,也没有人盯着。作者在 dev.to 上复盘了这次事故,并给出了 Claude 套餐限额的运作方式、用量读取方法,以及他现在给每个无人值守循环加上的三道保险。

Claude 套餐用量截图

限额是共享的,聊天应用也在吃你的额度

Claude Code 包含在 Pro 和 Max 订阅里,限额由两个计量器构成:5 小时会话限额和 7 天周限额。按 Anthropic 帮助页面的说法,Claude 聊天应用和 Claude Code 共用同一个池子——你在聊天窗口里花掉的,就是 Claude Code 能用的余量,反之亦然。

这正是早上看到「异常高」的用量条却从终端里解释不清的原因。如果部分用量来自聊天应用,它不会出现在终端的用量分解里。

撞到限额时有两个容易搞错的细节。切换模型只对点名了模型的提示有用(比如 Opus 专属限额);对于「所有模型」的通用提示,切模型什么也改变不了。可选做法是等待、开启 usage credits,或者在重置后自动继续——后者在 v2.1.234 及以上版本通过 /rate-limit-options 配置,组织则使用 autoContinueAtUsageLimit 设置。

开启 usage credits 有副作用:提示缓存寿命从 1 小时降到 5 分钟,同样的工作习惯会变得更贵。另外,Max 附带的月度 API 额度不能用来延长 Claude Code 的限额。

正确读 /usage 的方式

在 Claude Code 里输入 /usage。作为订阅用户,忽略 Session 区块,看套餐用量条和它下面的分解。分解包含三部分:归属(按技能、子代理、插件和 MCP 服务器划分的用量占比)、行为标记(比如长上下文和缓存未命中)、循环(每个计划任务的运行次数和 token 数,需要 v2.1.242 或更新版本)。

按 d 看最近 24 小时,按 w 看最近 7 天。有一个限制:这些数字来自你所在机器上的本地记录,其他设备和 claude.ai 应用的用量不在其中。这意味着仅凭屏幕上的数字,有时无法完整归因早上那条高高的用量条。

提示缓存(Prompt Caching) 是 Anthropic API 与 Claude Code 中的一项优化机制:相同的前缀提示(系统提示、长文档、工具定义等)在短时间内重复使用时会被缓存,后续请求可直接复用,从而显著降低延迟与 token 成本。缓存有生命周期,默认约 1 小时,超过后需重新写入。开启 usage credits 后该寿命会被压缩到 5 分钟,意味着同一套工作流在很短时间内就会失去缓存命中,实际花费随之上升。这也解释了为什么「买额度」并不等于「保持原价」——它改变的不仅是可用额度,还有计费效率。

那次夜间事故到底是什么样

2026-08-01,一个 LLM 循环在无人批准的情况下跑了一整夜,套餐用量上升了 13 个百分点。这个 13 是用量表的读数,是前后差值。作者刻意没有把它换算成 token 数,因为任何换算系数都只是估算。

根因是循环停不下来。如果有人看着,它几分钟内就会被杀掉。换成更便宜的模型也解决不了任何问题——缺失的退出条件依然在那里,只是烧得慢一点。

墙钟时间(wall-clock time) 指从任务开始到当前的实际流逝时间,与 CPU 时间或 token 数无关。在 LLM 循环中,它是最直观也最容易被忽略的守卫维度:一个循环可能调用次数不多,但每次都触发长上下文或多次重试,仅凭调用计数无法拦住它。以墙钟时间为上限(例如 3 小时)可以兜住这类「慢速泄漏」。它与连续失败上限、总调用次数上限互补,三者覆盖了错误型、量型和时间型三种失控路径。

给循环装三道保险

示例上限:连续失败 3 次、200 次调用、3 小时

至少选两道并写进代码:连续失败上限、总调用次数上限、墙钟时间上限。作者自己用的数值是连续失败 3 次、200 次调用、3 小时。

import time

MAX_FAILS, MAX_CALLS, MAX_SECONDS = 3, 200, 3 * 3600

def run(task, step):
    start, calls, fails = time.time(), 0, 0
    while not task.done():
        if fails >= MAX_FAILS:
            return "stopped: 3 consecutive failures"
        if calls >= MAX_CALLS:
            return "stopped: 200 calls"
        if time.time() - start >= MAX_SECONDS:
            return "stopped: 3 hours"
        calls += 1
        try:
            step(task)
            fails = 0
        except Exception:
            fails += 1
    return "done"

检查在每次迭代前执行,函数返回停止原因以便记录。先测试这些守卫:给 step 传入一个总是抛异常的函数,确认在第 3 次尝试后拿到失败信息。

有一个陷阱:429 冷却不是上限,而是恢复机制,因为它会在每个新的限额窗口里复活循环。它让循环永远礼貌地跑下去。

429 冷却(rate-limit backoff) 指客户端在收到 HTTP 429「请求过多」后暂停一段时间再重试的策略。它的设计目标是应对短暂拥塞,而非终止任务。当它被嵌进无人值守循环时,循环会在限额窗口重置后自动恢复,形成「撞墙—等待—继续」的无限循环。因此冷却逻辑必须与硬上限配合:冷却只决定「何时重试」,上限决定「何时彻底放弃」。两者混为一谈,等于给循环装了一个永动的重启器。

无人值守运行前的检查清单

  1. 开始前写下预期用量。
  2. 让人工批准这个估算。
  3. 至少设置两道上限并测试它们。
  4. 退出时记录停止原因和用量。
  5. 每月审计所有 cron 任务、调度器条目和后台运行器。

这套守卫只覆盖你自己写的循环。对于 Claude Code 自带的 /loop,查看 /usage 里的 Loops 行,手动关掉或拉长间隔。而且因为应用用量不在分解里,早上那条高高的用量条并不总能仅凭屏幕归因。

文章来自 dev.to 作者对一次真实事故的复盘,完整版本(含限额、额度和模型切换的常见问题)在原博客中。对经常跑无人值守任务的开发者来说,教训很直接:问题不是模型贵,而是循环不会自己停。

#Claude Code#Claude 套餐限额#无人值守循环#LLM 循环停止条件#用量监控#rate limit#开发者事故复盘
分享:

相关推荐