Newshot
Account

Agent反复调用工具烧钱,OpenRouter四道闸封住循环

Summary

发票接口持续超时,Agent 却拿着同一张发票一次又一次重试;你看到调用次数不断上涨,它并没有主动停手。OpenRouter 的测试显示,这类循环不仅会重复消耗工具调用,每轮还会带上更长的对话历史,让单次调用越来越贵。它在 Agent SDK 里加入四道闸:识别并阻止重复调用、归一化参数、限制单次运行的步数与成本,再由 API 密钥额度守住总支出,目标是 在账单失控前先截住循环 。 这四道闸像给自动付款机器人装上四层保险:第一层发现它正反复点同一个按钮,第二层防止它只改一个编号就混过去,第三层限制这一轮最多操作多少次、花多少钱,最后一层则由平台给总账户封顶。类比只用于说明职责不同:前两道识别重复,第三、四道限制支出,平台额度负责代码失效后的最终兜底。 Agent 为什么会越烧越贵? 每轮重试都会把旧错误一并发回模型,输入越来越长,单轮成本跟着抬升。Agent 越烧越贵,不只是因为工具失败后多跑了几次。 OpenRouter 的教程把原因指向一个循环:工具持续报错,模型收到的任务指令却仍要求完成任务,于是它把再次调用工具当成下一步。错误被写回对话后,Agent 本身不会自动统计尝试次数,除非开发者另加停止规则。 一次失败如何进入下一轮 工具调用失败 → 错误写入对话 → 模型再次请求工具 → 完整历史再次发送 每轮输入都包含此前的失败信息,模型看得见服务仍然不可用,却可能继续重试;账单增加的并不只是本次工具操作,还有越来越长的上下文输入。 OpenRouter 在一次逐轮记录的演示中测到,输入从 131 个 token 增至 3,262 个,同一次演示的单轮成本接近四倍。token(模型处理文本时计量长度的单位)增长约 24 倍,单轮价格却接近四倍,说明它不能被直接理解成逐条等比例上涨。 另一个演示给发票查询工具设置了持续超时。循环持续到运行结束,共执行 41 次相同工具调用,费用为 0.0309 美元。41 次调用只花这么点钱,是因为那次设了步数上限;没设上限时它不会自己停。 那次运行设置了步数上限,所以循环才在最后停下。若没有步数上限,OpenRouter Agent SDK(让模型能够调用工具并连续行动的开发工具包)会持续运行,直到模型不再请求工具。换句话说,工具一直失败时,Agent 并没有一个天然终点。 第三次相同调用,它就被拦下 模型拿到上一次工具结果,又…

Original text(via 听说了吗)

Agent反复调用工具烧钱,OpenRouter四道闸封住循环

OpenRouter 用四道闸应对 Agent 反复调用同一工具:识别重复调用、阻止微小改参绕过、限制单次运行步数与成本,并用 API 密钥额度兜住总支出。

封面图来自OpenRouter:Announcements(RSS)(官网正文图)
封面图来自OpenRouter:Announcements(RSS)(官网正文图)
  • 失败重试会重发完整对话,推高单轮成本
  • 重复检测可按连续次数阻止相同调用
  • loopKey 可归一参数差异以识别变体
  • 单次上限之外还需服务端密钥额度兜底

官方教程兼产品演示,测试由 OpenRouter 完成;文中数字为内部实验结果,未见第三方复测。

发票接口持续超时,Agent 却拿着同一张发票一次又一次重试;你看到调用次数不断上涨,它并没有主动停手。OpenRouter 的测试显示,这类循环不仅会重复消耗工具调用,每轮还会带上更长的对话历史,让单次调用越来越贵。它在 Agent SDK 里加入四道闸:识别并阻止重复调用、归一化参数、限制单次运行的步数与成本,再由 API 密钥额度守住总支出,目标是在账单失控前先截住循环。

Agent 为什么会越烧越贵?

每轮重试都会把旧错误一并发回模型,输入越来越长,单轮成本跟着抬升。Agent 越烧越贵,不只是因为工具失败后多跑了几次。

OpenRouter 的教程把原因指向一个循环:工具持续报错,模型收到的任务指令却仍要求完成任务,于是它把再次调用工具当成下一步。错误被写回对话后,Agent 本身不会自动统计尝试次数,除非开发者另加停止规则。

每轮输入都包含此前的失败信息,模型看得见服务仍然不可用,却可能继续重试;账单增加的并不只是本次工具操作,还有越来越长的上下文输入。

OpenRouter 在一次逐轮记录的演示中测到,输入从 131 个 token 增至 3,262 个,同一次演示的单轮成本接近四倍。token(模型处理文本时计量长度的单位)增长约 24 倍,单轮价格却接近四倍,说明它不能被直接理解成逐条等比例上涨。

另一个演示给发票查询工具设置了持续超时。循环持续到运行结束,共执行 41 次相同工具调用,费用为 0.0309 美元。41 次调用只花这么点钱,是因为那次设了步数上限;没设上限时它不会自己停。

那次运行设置了步数上限,所以循环才在最后停下。若没有步数上限,OpenRouter Agent SDK(让模型能够调用工具并连续行动的开发工具包)会持续运行,直到模型不再请求工具。换句话说,工具一直失败时,Agent 并没有一个天然终点。

第三次相同调用,它就被拦下

模型拿到上一次工具结果,又用相同工具、相同参数再要一遍——这就是它拦的循环。

OpenRouter 管这叫“厄运循环检测”(识别工具反复调用并中止运行)。默认规则分三步:连续出现 2 次相同调用时,系统先观察;第 3 次时阻止;连续达到 6 次时,终止整个运行。观察阶段不会立即打断模型,阻止阶段会拦下当前调用,终止阶段则结束这次任务。

什么才算“相同”?工具名称相同,参数也必须等价,而且模型得先拿到上一次执行结果,才有机会再次提出同一请求。若模型尚未看到结果便连续生成请求,不会按这种方式逐次累加。

多数循环没走到第三次。OpenRouter 在六个当前模型上各运行三次,共完成 18 次测试,开启检测后,有 16 次只执行了两次真实工具调用便结束。

整体调用量也随之下降:检测关闭时,18 次运行共调用工具 314 次,费用为 0.29 美元;开启后,工具调用总数降至 64 次,费用降至 0.05 美元。这里记录的是厂商自己的测试结果,目前没有第三方复测数据,不能直接外推到其他模型或不同任务。

OpenRouter:Announcements(RSS) 官方配图 1
OpenRouter:Announcements(RSS) 官方配图 1

参数只改一点,循环检测就会失效吗?

会。逐字比对参数,模型只需轻微改写就能制造出“不同请求”。更稳妥的办法是先归一化参数,再识别它们是否属于同一次调用。

部分模型会改变工具参数,再发起看似不同的请求。检测器若逐字比对,就可能把这些请求当成新调用,让循环继续执行。检测器要比的是参数指向的目标,不是字面写法。

loopKey(把调用归一为同一身份的标记)正是为这类情况设计的。开发者可指定需要忽略的参数差异;系统按规则归一化后,再识别重复调用。模型即使微调参数,也难以靠换一种写法逃过检测,前提是开发者把该忽略的差异配进 loopKey。

归一化还要结合调用所在的轮次。同一轮中的五次相同调用只计作一次重复,不会被当成五段独立工作。检测关注的是同一轮内的重复行为,而非简单累加调用次数。

OpenRouter:Announcements(RSS) 官方配图 2
OpenRouter:Announcements(RSS) 官方配图 2

第三道闸:给单次运行踩刹车

单次运行要同时设步数上限和成本上限:前者限制循环能走多远,后者限制这次最多花多少钱。

OpenRouter Agent SDK(用于构建多轮工具调用的开发包)把停止条件写在 stopWhen(达到条件时结束本次运行) 里,步数和成本两个条件可以一起交给它。stepCountIs(按运行步数停止) 管的是循环能走多远,maxCost(按累计费用停止) 管的是这次最多烧掉多少钱。两道限制分别兜住两类失控:调用次数很多但单次便宜,或调用次数不算多却因模型、工具和上下文变贵。

步数上限并非精确的“工具调用计数闸”。当 stepCountIs(40) 到达上限时,模型此前已经发出的额外工具调用仍可能继续执行一次。因此,开发者不能把“停止”理解成后续请求必然不会发生;工具侧仍需按可能多出一次调用来设计。

如果完全不设置 stopWhen,Agent SDK 不会替开发者猜测何时算“够了”。它会持续运行,直到模型不再请求工具。工具持续失败、模型反复重试或参数不断变化,都可能让结束条件迟迟不出现。

这套限制按每次运行生效,适用于不同原因触发的循环,但不约束所有运行叠加后的总支出。当前 OpenRouter Agent SDK 版本为 0.11.0,开发者需要确认依赖版本,并分别设置步数与成本条件,而不是只押注其中一道限制。

代码失效后,谁来兜住总账单?

当 Agent 的内部止损逻辑失效,OpenRouter 仍会按 API 密钥的总花费执行额度限制。请求一旦越过额度,服务端会让它失败并返回 402,超额请求直接失败,账单停在那里。

前 3 道防护都由 Agent 内部执行:重复调用检测负责识别异常,参数归一化用于识别换皮后的重复,步数与成本限制负责约束单次运行。Agent 代码一旦出错,这些判断可能停摆,账单却仍由使用同一把 API 密钥的请求累积。

密钥额度在服务端执行,开发者不需要依赖 Agent 自觉停下,也不需要假设每一段本地代码都正确工作。代码失效能影响 Agent 怎样调用工具,却不能解除服务端已经设定的支出上限。

防护位置约束对象代码失效后的结果
Agent 内部重复调用、单次运行的步数与成本相关判断可能无法执行
OpenRouter 服务端API 密钥累计花费超额请求仍会失败

前 3 道闸管的是运行过程,密钥额度管的是账户总账,单次运行成本上限不能当成总账单兜底。

额度触发的反馈也可以定位。请求超出密钥额度后会返回 402(表示请求因额度限制被拒绝),返回信息中的 limit_source 为 openrouter_key_limit。这个字段指明拒绝来自密钥额度,而不是 Agent 内部的重复检测或单次运行限制,便于开发者查清账单为何被截住。

回到开场那个画面:当发票接口再次超时,Agent 准备发起下一次重试时,这四道闸会先于失控账单出现。

如果 Agent 必须先完成一张发票查询才能结束任务,哪道闸该先触发?

本文基于OpenRouter:Announcements(RSS)原文撰写(2026-11-12)。厂商公布的数字(跑分、降幅等)均为官方口径,除注明外尚未经第三方独立复测。

术语小典 · 本篇出现的人话注解

深度、研究解读、工具教程的全文和全部播客,都在会员区。

The text above was extracted automatically from the source page and may miss images, tables or code blocks. The original is authoritative.

Published by 听说了吗
This site only summarises and aggregates; copyright stays with the original author. Headlines and summaries follow the source — where they differ, the original wins.
Read the original ↗