ai-engineering-from-scratch 如何为自主智能体配置成本预算与迭代上限以防止失控消费?
【免费下载链接】ai-engineering-from-scratchLearn it. Build it. Ship it for others.项目地址: https://gitcode.com/GitHub_Trending/ai/ai-engineering-from-scratch
当你让一个自主智能体(agent)长时间无人值守地跑任务时,每一轮推理、每一次工具调用都在真实地产生 LLM 账单。智能体一旦陷入重试或轮询循环,账单会持续累积而没有任何机制叫停它——项目文档把这类失败模式称为 "Denial of Wallet"。ai-engineering-from-scratch 仓库的 Phase 15 第 13 课 成本预算、迭代上限与成本治理器 给出了对应解法:用一套分层限制(per-request、per-session、velocity、per-day/month)替代"只设一个月度上限"的单一思路,并附带一个可直接运行的 Python 模拟器和一个上线前的预算审计清单。
本文的操作路径是:先理解按时间尺度分层的限制栈,再运行仓库自带的模拟器观察各层限制的触发顺序,然后按文档给出的参数面(含 Claude Code Agent SDK 的max_turns、max_budget_usd)配置你的智能体,最后用审计清单逐项核对。前置条件只需要 Python 3(模拟器为纯 stdlib,无需安装依赖)和一份仓库代码;课程文档标注的前置课为 Phase 15 · 10(权限模式)与 Phase 15 · 12(持久执行)。
为什么单一上限不够:先确定要配哪几层
课程文档列出的成本治理器(cost-governor)栈共 12 层,其中与"配置预算和上限"直接相关的是:
max_tokensper request:限制单次补全的输出规模,防止任何一次调用无界生成。- Per-task token budget:整个任务不超过 N tokens,到上限硬停。
- Per-task dollar budget:以货币为单位的任务预算,Claude Code 中对应
max_budget_usd。 - Per-tool call cap:单个工具的调用次数上限,例如
WebFetch不超过 N 次、shell_exec不超过 N 次。 - Iteration cap(
max_turns):整个 agent 循环的迭代次数上限,防止无限推理循环。 - Per-minute / per-hour / per-day / per-month cap:滚动窗口上限,在不同时间尺度上捕获泄漏。
- Financial velocity limit:短窗口消费速率上限,文档示例为"10 分钟内花费超过 $50 就切断访问",用于在月度上限触发之前抓住循环型烧钱。
- Tiered model routing:默认走小模型,仅当分类器判断任务需要时才升级到更大模型。
- Prompt caching:系统提示与稳定上下文存入 provider 缓存,重发的 token 成本接近零。
- Context windowing:压缩/摘要使活动上下文低于阈值,直接降低 token 成本。
- HITL checkpoints:已知昂贵动作(长工具调用、大下载、模型升级)执行前要求人工确认。
- Kill switch on budget breach:任何一层上限触发时中止会话,上限被记录,重新启用需走独立路径。
文档同时给出了四层失败模式与捕获层级的对应关系,这是配置时的选型依据:
- Runaway loop(智能体卡进 5 秒级重试循环)→ velocity limit 捕获;
- Slow leak(每个任务实际工作量约为预期的 2 倍)→ daily cap 捕获;
- Bad release(新版本 token 用量翻 5 倍)→ weekly / monthly cap 捕获;
- Legitimate surge(真实需求上涨而非 bug)→ hour / day cap 配合清晰日志捕获。
文档中还引用了 Microsoft Agent Governance Toolkit 记录的一个真实案例:某电商 agent 上线 "order-tracking" 技能后月成本从 $1,200 涨到 $4,800,原因是新工具让 agent 在每个会话里轮询订单状态,而系统没有循环检测、没有 per-tool 上限、没有周环比增长告警。修复方式是 per-tool cap 加 daily-growth 告警。文档由此总结出一条模板:每一个新工具面都是一个新的潜在循环,每个新工具都需要自己的上限和自己的告警。
运行仓库自带的分层限流模拟器
模拟器位于 code/main.py,纯 Python stdlib,模拟一个 agent 在第 30 轮后滑入轮询循环(loop turn 消耗 8,000 tokens,正常 turn 为 2,500 tokens),并对比三种配置:
no caps:不做限制;monthly cap only:只设月度上限;layered stack:per-request + iteration + velocity + session + monthly 全部分层启用。
从仓库根目录执行(命令形式参照 Phase 15 README 中给出的运行模式):
python3 phases/15-autonomous-systems/13-cost-governors/code/main.py每次运行输出一行,形如:
<配置名> turns= 5 tokens= 8,000 dollars=$ 4.80 stopped_by=velocity_limit四个字段分别是执行的轮数、累计 tokens、累计美元、以及最先触发的限制(max_turns/max_budget_usd/velocity_limit/monthly_cap/ran out of simulated turns)。stopped_by字段就是判断"哪一层先兜住"的依据:读三行输出,对比三种配置分别由哪一层终止、终止时累计花了多少,即可直观看到月度上限触发得太晚、分层栈终止得更早。
程序还会打印一段固定的结论块(代码中的字面输出):
HEADLINE: caps must layer, because failure modes differ by time scale Monthly cap fires late: the wallet is already half-gone. Velocity limit ($5/min rolling) catches a loop within minutes. Iteration cap prevents any single run from exceeding N turns. Per-request cap prevents any one completion from being unbounded. Session dollar cap (max_budget_usd) closes the seatbelt on cost. Each layer covers a different failure (loop, leak, surge, release).按练习验证 velocity 与 iteration 的触发顺序
课程练习 1 要求两件事:在轮询循环轨迹上确认 velocity limit 先于 iteration cap 触发;然后关闭 velocity limit,测量 agent 在被 iteration cap 抓住之前多花了多少钱。对应的操作是修改 code/main.py 中Governor的enable_velocity开关再重跑。
有一个细节需要先读代码确认:默认参数下每个 loop turn 消耗 8,000 tokens,按模拟器的DOLLARS_PER_KTOK = 0.003折合约 $0.024/turn;而默认seconds_per_turn=30.0(每轮 30 秒)时,滚动窗口内的消费速率远低于默认的velocity_usd_per_min=5.0阈值,因此默认运行中先触发的会是max_turns。要让 velocity limit 真正先于 iteration cap 触发,需要在副本中调整轨迹速度(调小seconds_per_turn)或调低 velocity 阈值,再对比stopped_by字段和累计dollars。
Governor的参数面如下(默认值均取自 code/main.py 中的数据类定义):
| 字段 | 默认值 | 对应概念 |
|---|---|---|
max_tokens_per_request | 10_000 | 单次请求 token 上限 |
max_turns | 200 | 迭代上限(iteration cap) |
max_budget_usd | 50.0 | 会话美元上限,超出即停 |
velocity_usd_per_min | 5.0 | 滚动窗口每分钟消费速率上限 |
velocity_window_min | 10.0 | velocity 的统计窗口(分钟) |
monthly_cap_usd | 500.0 | 月度硬上限 |
enable_request_cap/enable_iter_cap/enable_velocity/enable_session_cap/enable_monthly_cap | 均为True | 各层开关,练习中用于逐层关闭做对比 |
seconds_per_turn | 30.0 | 模拟器中每轮耗时(分钟换算用) |
在自己的环境里按与main.py相同的方式构造覆盖参数即可,例如:
g = Governor( max_turns=200, # 迭代上限 max_budget_usd=50.0, # 会话美元上限 velocity_usd_per_min=5.0, # 每分钟滚动消费速率上限 enable_velocity=True, )需要说明:模拟器中的DOLLARS_PER_KTOK = 0.003是代码注释标注的"mid-2026 Sonnet-class 模型混合费率"假设,仅用于演示,不代表真实账单;真实部署的预算数值要按你所用模型的实际价格测算。
在真实智能体上配置预算与迭代上限
模拟器验证的是"分层"这个机制;落到真实智能体,课程文档以 Claude Code Agent SDK 为例给出了对应的参数面(公开文档):
max_turns——迭代上限;max_budget_usd——美元上限,按会话累计成本结算,breach 时中止会话;allowed_tools/disallowed_tools——工具白名单与黑名单;- 工具调用前的 hook 点——用于接入自定义成本核算。
配套的权限模式课程 Phase 15 · 10 补充了两点:预算控制与 Auto Mode 分类器并列存在(分类器审查每个动作,max_turns、max_budget_usd、每工具调用次数上限负责成本);且 per-tool 调用次数上限(如WebFetch不超过 N 次)也是预算控制的一部分。两课共同的判断是:autoMode会话如果不设max_budget_usd,属于"ungoverned autonomy"——Anthropic 明确把 Auto Mode 定位为需要预算控制配合的模式,分类器与成本是正交的两层,不能互相替代。
与"防止失控消费"直接相关的两条边界来自课程文档本身:
- Claude Code 的
max_budget_usd只按会话累计成本触发。课程练习 5 明确要求你自行设计一个外部的 velocity limit 作为补充:触发切断的条件是什么、恢复启用(re-enable)流程是什么,都要自己定义。也就是说,会话级美元上限不能替代短窗口速率限制。 - kill switch 必须位于智能体可编辑面之外。第 12 层要求"任一上限触发即中止会话,上限被记录,重新启用走独立路径";Phase 15 · 14(kill switch、熔断器与金丝雀令牌) 进一步规定:agent 不能把自己设为 off、每个关键动作都要检查、重新启用是显式人工操作而非自动超时。
上线前用预算审计清单核对
配置完成后,仓库提供了一个可直接使用的审计 skill:skill-agent-budget-audit。它按 12 层参考栈逐项审计一个拟上线的 agent 部署,产出五部分:层清单(每层是否配置、配置值)、失败模式映射(loop / leak / release / surge 各由哪层多快捕获)、per-tool 上限(每个工具一个会话级上限及理由,"没有显式上限的工具就是开放循环")、告警阈值(与上限分开:什么消费速率下通知人类)、kill-switch 路径(触发、动作、重新启用流程,并确认 kill switch 在 agent 外部)。
该清单定义了五条硬性拒绝项,可作为上线核对的判定标准:
- 自治部署缺少 per-task dollar budget——拒绝;
- 无人值守长时程运行缺少 velocity limit——拒绝;
- 新增(<30 天)的工具面没有 per-tool cap——拒绝;
- kill switch 可以被 agent 自己修改——拒绝;
- 只有月度上限、其余时间尺度全部不设防——拒绝。
另有三条拒绝规则约束预算数值本身:无法按当前模型价格给出最坏单次运行估价时必须先补成本估算;预算超过组织对单次失误可接受损失时必须调低上限;把 Auto Mode 分类器当作预算替代品时必须拒绝——分类器与成本正交,两层都要有。
限制与下一步
需要明确这套机制的边界:成本治理器只约束智能体能花多少钱,不约束它在预算内能做什么——Phase 15 · 14 开篇即指出,带 $50 velocity 上限的 agent 依然可以泄密、误发布或删除资源,昂贵动作往往恰好是 token 上便宜的动作。因此预算栈之外还要叠加 kill switch、熔断器和金丝雀令牌,这是该课的后续课程范围。
另外两点限制来自课程文档:EU AI Act 与 OWASP Agentic Top 10 的语境下,若在欧洲生产环境运行,日志与上限执行"不是可选项";模拟器输出的具体美元数由代码中的费率假设决定,只能用于理解触发顺序,不能作为真实成本预估。
延伸阅读路径都在 Phase 15 · 13 课程文档 中:先回读权限模式课把max_turns/max_budget_usd放进权限阶梯理解,再进入 kill switch 课补齐行为侧的检测层。
【免费下载链接】ai-engineering-from-scratchLearn it. Build it. Ship it for others.项目地址: https://gitcode.com/GitHub_Trending/ai/ai-engineering-from-scratch
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考