这篇解决什么困惑

给 Agent 一个 modelTokenBudget: 2000,并不等于它最多花 2000 个 Token。预算究竟约束什么?模型供应商没有返回 usage 时怎么办?工具已经执行了一半,预算耗尽后应该继续还是停止?

预算不是一个配置字段,而是 Harness 对时间、步骤、模型和外部副作用施加的共同边界。

当前已经有什么

Agent Loop 目前有三类确定性护栏:最大步骤数、deadline 和模型 Token 预算的存在性检查。每一步开始前都会检查这些边界;达到上限时,系统不会再偷偷向模型请求一次决策。

这已经能防止最直接的失控,但它还不是完整成本控制。当前代码还没有根据每次供应商返回的真实 usage 持续扣减预算,也没有把不同模型、工具时间和重试成本换算成统一费用。

为什么 0/0 不代表零消耗

Spring AI 或供应商适配器可能在响应对象里留下占位用量。若把 inputTokens=0outputTokens=0 直接累加,报表看起来很准确,实际却只是“没有拿到数据”。

当前 Trace 把用量分为 RECORDEDUNAVAILABLE。只有真实元数据存在时才累加 Token;缺失时保留不可用状态,并通过 usageComplete 告诉查询方不能把聚合结果当作完整账单。

可靠系统宁可显示“未知”,也不能把未知伪装成零。

预算应该在哪些边界检查

收到请求
  → 校验最大步骤 / deadline / Token 上限
  → 决策前再次检查
  → 外部调用前检查时间与权限
  → 结果落盘并记录真实 usage
  → 计算剩余预算
  → 继续、降级或停止

至少需要检查四次:请求进入时防止明显超限;模型决策前防止无意义调用;工具执行前防止已经没有时间或权限;外部结果返回后更新实际消耗。

只在循环最外层检查一次,会给工具和重试留下预算盲区。

步骤预算、Token 预算和费用预算

三者不能互相替代:

预算 约束对象 典型停止原因
步骤 Loop 迭代次数 防止原地循环
时间 wall-clock deadline 防止请求无限等待
Token 模型输入和输出 防止上下文或重试膨胀
费用 不同模型与工具的价格 防止账单超出授权

一个运行可能没有超出步骤数,却因为上下文变长消耗大量 Token;也可能 Token 很少,却因为工具反复重试占满时间。预算要分别记录,再由停止策略综合判断。

预算耗尽后怎么办

停止不是唯一动作,但每种替代方案都需要明确边界:

  • 直接停止:最安全,返回当前已验证的部分结果;
  • 降级模型:需要预先定义哪些模型可以替代,以及上下文是否兼容;
  • 缩小上下文:只能丢弃非必要信息,不能丢掉完成结论所需的证据;
  • 转人工:适合已有部分结果但继续执行风险较高的任务。

不能让模型自己决定“为了完成任务再多花一点”。预算授权属于 Harness,不属于被预算约束的模型。

恢复与预算的关系

Checkpoint 恢复时,已经落盘的工具结果不会重复执行;崩溃窗口中的不确定调用可能重放。这个重放本身也要计入预算,否则每次故障都会获得一份隐藏的免费额度。

因此未来的真实扣减应和调用结果、重试次数、模型 usage 一起进入同一个受守卫的事务边界。预算扣减失败时,不能推进 Checkpoint,也不能让 Trace 看起来像调用已经被授权。

还缺哪些能力

当前仍缺少供应商真实 usage 驱动的预算扣减、模型价格表版本化、重试成本核算和费用上限 API。工具执行时间和外部服务费用也还没有统一映射到同一个预算模型。

这些缺口并不影响当前 Loop 的学习和固定集验证,但意味着它还不能承诺“每次运行最多花多少钱”。

最终判断

预算设计的核心不是把数字写大或写小,而是让系统知道自己知道什么:步骤和 deadline 可以确定地约束,Token 和费用只有拿到真实元数据后才能精确扣减,未知用量必须保持未知。

一个成熟的 Agent 不会为了完成任务突破预算;它会在预算耗尽时给出可解释的停止、降级或转人工结果,并把这次决定留下足够的证据。

更新时间:2026-08-30