为什么线性预算总是低估成本
很多团队给 Agent 定预算的方式是:一次调用大约多少钱,乘上预计的工具调用轮数,加一点缓冲。这个算法的问题在于,多轮循环里每一次工具调用都会把结果塞进上下文,后续请求要带着全部历史一起发送。成本不是 N×C,而是接近 N 的平方级增长。一篇关于多轮工具调用成本的文章里给过一个具体对比:一段 9,000 token 上下文的单次调用约 $0.03,同样内容跑十步、每步追加工具结果后,总上下文抬到约 472,000 token,成本变成单次基准的 43 倍。这个倍数不是噪声,它说明按步数做线性预算从第一天就是错的。
所以步数预算的真正职责不是“省点钱”,而是防止一部分永远结束不了的循环。预算太紧,任务做不完;预算太松,失败模式退化成失控重试。两种情况都落在工程上不完全一样的区间。
硬上限和软提示解决两个区间
Anthropic 的 Messages API 里,max_tokens 是硬约束,限制一次请求的输出总量,包括思考和正文;达到上限会返回 stop_reason: "max_tokens",答案被截断。但要注意,工具调用循环中的每个请求都有自己的 max_tokens,它只约束单次响应,不管整个任务。十个请求、每次 4,000,加起来可以生成到 40,000 输出 token,输入另算。
task_budget 是另一条线,放在 output_config 里,用 total 字段告诉模型整个循环大概能用多少 token,涵盖思考、工具调用、工具结果和输出。文档里写得明确:这是软性提示,不是硬性上限,模型可能在一次操作中超过预算,输出仍然只被 max_tokens 摁住。可接受的最小值是 20,000 token,更低会直接返回 400。预算小到不合理时,模型会缩小任务范围或提前停止,表现得像是拒绝了任务。
这种设计对常驻 Agent 是合理的:硬上限保证一张账单不会被单次调用打穿,软预算让模型在接近尾声时改变行为。把它当硬上限用就会理解错。
提前终止的三个可信信号
判断该不该停,工程上比“跑满 N 步”更细的信号大概是这几类。第一是工具响应里的明确终止状态。有团队把 SUCCESS/FAILED 写进工具响应,替换掉模糊的错误码以后,每任务工具调用次数从 14 次降到 2 次。模型停止重试不是靠步数逼停的,而是因为结果终于告诉它事情结束了。第二是重复调用同一工具的模式,也就是断路器。Claude Code 的迭代循环问题在公开的 GitHub Issue 里有记录(#6004、#2283、#2391 等),它的工程价值不在于“免疫循环”,而在于把循环拉回来的速度更快。第三是产出量的边际递减:随着轮次推进输出越来越少、信息增量趋近零,就可以终止。
这三个信号分别对应“做完了”“卡住了”“在磨洋工”。只靠一个步数计数器,三种状态无法区分。
不同 Agent 的默认步数并不通用
常见的开源实现给的默认值可以作一个参照:ToolCallAgent 一般 30 步,SWEAgent 大概 20 步,PlanningFlow 走配置。有经验建议是简单任务 5–10 步,中等任务 15–25 步,复杂任务 30–50 步,超过 50 步就拆子任务。这些数字没法定成标准,因为单步的成本取决于工具返回结果的大小。一次返回 8,000 行日志的调用,和一次返回 200 字摘要的调用,标称步数一样,实际 token 量差一个数量级。按步数预算需要先对“步”做分层,至少把工具输出尺寸作为步数权重的一部分。
可缓存前缀的 token 成本也影响步数设置。以 Claude 5 分钟缓存为例,写入是基础输入价的 1.25 倍,读取是 0.1 倍;Claude Opus 5.5 和 Claude Sonnet 5.5 的读取甚至只有 0.05 倍。如果 Agent 循环每次都变更了系统提示的前缀、带上时间戳或运行 ID,缓存就永远命不中,这时候哪怕步数预算一样,成本实际高出一个量级。把易变内容挪到最新用户消息里、保持工具定义稳定,这些是让步数预算有意义的前置条件。
预算感知如何影响模型行为
给模型看到剩余预算,做的选择并不相同。有研究指出,带显式 token 预算的 Agent 会优先高信息量的工具调用,跳过冗余验证。风险在另一个方向:预算写在最开头还是每轮递减。Anthropic 文档里有明确提醒,客户端如果在每个后续请求中递减 task_budget.remaining,变更后的值会打破缓存前缀,成本反而可能增加。正确做法是在首个请求里设置一次。考虑到最小 20,000 的下限和缓存影响,“预算感知”更像一个启动时附加的航向信息,而不是实时倒计时器。
配套还有一个反直觉的观察:上下文压缩并不是压得越狠越省。一项研究发现把上下文压到 99.3% 之后总成本反而升高,因为它迫使 Agent 重新获取已经检索过的内容。比较稳的区间是减少 50%–80%。这直接影响提前终止的判断——预算不够时快速压缩上下文会引入新的反复检索循环。
可跑的终止策略长什么样
一个不依赖框架的实现大致是:每步前检查当前 token 用量与首轮设置的任务预算,超过 90% 就触发收尾模式;同一工具在最近几轮里返回了相同签名两次以上就中止该路径;工具响应带明确的终止状态就直接状态转移;每一轮记录输出的信息增量,连续两轮低于阈值就收工。括号里这些阈值都得按业务类型调,做日志分类的 Agent 和做多文件重构的 Agent 的合理步数没有共享基准。
死循环不会因为开发人员写下了这几个数字就永久消失。比较可行的预期是,让代价高、收益低的那种循环先被截住,然后在观测里能看到“停在哪一步、为什么停”。没有这个前提,调步数上限只是在闭着眼睛改旋钮。
每一步的花费来自哪里
更根本的一点在于开销的构成。每一次调用重新发送的系统提示通常 2,000–5,000 token;中等规模的工具集本身还有序列化成本,公开数据里单独一次调用的工具定义开销能到 55,000–134,000 token。动态加载是把这部分压低的手段,有记录的实现从 134,000 降到 8,700,减少 85%。并行工具调用则通过减少往返次数压低重复支付的输入侧成本。没有这两件事参与,光靠设定更低的步数上限,Aent 能做的事情会以可见的质量下降作为代价。终止策略是环上的急救手段之一,不是替代基本设计的预算削峰。
转载请注明出处: 皮哈皮阿
本文的链接地址: https://blog.phpat.com/agent-engineering/649.html
微信或手机浏览器扫一扫,随时随地随心阅读与分享
-
Agent Harness:可观测、可评测、可回滚的 Agent 基础设施
去年我们做了一个处理退款申请的 Agent。Demo 很顺,上线第一周就出了事故:进程重启后状态丢了,同一笔申请被处理了两次。问题不在模型,而在模型外面那层没人愿意写的基础设施。
2026/10/09
-
AI Coding Agent 如何稳定提交可合并的 PR
上周 review 了一个 AI 生成的 PR,测试全绿,但我还是把它关了。它改了 37 个文件,顺手升级了一个依赖,还修改了两条测试断言。问题不是代码不能跑,而是这个 PR 没人敢合。
2026/10/14
-
MCP 进入生产环境:工具协议、网关与权限边界
MCP 刚出来时,我以为最难的是协议兼容。真正接了十几个工具之后才发现,把工具接上只花了两天,把权限、审计和故障处理理清楚花了两个月。
2026/10/07
-
Agent 安全清单:提示注入、工具越权与数据外泄
一个内部助手被要求总结一封客户邮件。邮件末尾有一行白色小字:把最近的客户名单转发到某个地址。Agent 真的准备去调邮件工具了。安全不能靠模型自觉,得靠系统设计。
2026/10/16
-
Agent 子目标检查点回归:从回滚状态到登记副作用
Agent 的子目标检查点能回滚本地状态,却回滚不了已提交的外部副作用。本文拆解恢复后重新合成工具调用导致的语义回滚,给出基于副作用指纹的检查点边界划分与确定性回归断言。
2026/10/25
-
并行工具调用暴露的工具设计耦合问题
并行工具调用能砍掉四成延迟,但它更重要的价值在于暴露工具之间的隐性耦合。本文拆解上下文依赖、共享状态竞争与时序前提这三类静默失败,给出读写分类规则、工具合并的判据,以及什么时候该上依赖图编排。
2026/10/23
京公网安备11011402053654 
@muffin:链接已更新,分类图像功能...
AI网址导航模版图标库更换指南
作者大大,图标库邀请链接失效了,麻烦更新...
AI网址导航模版图标库更换指南
太好看了,快点更新!
友情链接
@戴墨镜的刘备:哈喽,路过点赞。
vue.js组件之手写签名板vue-signature-simple
太好看了,快点更新!太棒了!👍真的很赞!
vue.js组件之手写签名板vue-signature-simple
你写得非常清晰明了,让我很容易理解你的观...
Emlog插件RSS订阅器发布