Agent 调订单查询工具,模型把工具返回的 null 当成需要再查,循环 8 轮后触发上游 429,一次会话烧了 12 万 token,账单肉眼可见地涨。

一开始怀疑是「异常没有终止循环,反而被当成可重试」,查了一圈,方向不对。

原因不止一个,得分开看。没有设置 recursion_limit 或 max_iterations。还有一种是工具返回 null 时没有包装成明确的否定文案。

另外,重试间隔为 0,轮次之间没有任何退避。

上来先看这次会话的轮次与 token

python -c "import json;d=json.load(open('trace.json'));print(len(d['steps']),d['usage']['total_tokens'])"

再往下设置 recursion_limit 并让超限走兜底回复

python -c "print({'recursion_limit':6,'on_limit':'handoff_to_human'})"

接着把 null 统一转成明确文案

python -c "r=None;print('未查询到该订单' if r is None else r)"

给每轮之间加退避并统计轮次分布

python -c "print([round(0.5*2**i,1) for i in range(5)])"

排查用的命令都是临时敲的,没有写成脚本,事后才整理。

改完先别撤,确认这几项。同一场景的会话固定在 3 轮内结束,token 消耗降到 1.8 万,429 不再出现,超限的会话都转到了人工。

Agent 的循环上限是成本闸门,工具返回的空值必须有确定语义,否则模型会一直认为「还没查到」。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。

作者 9823189