Agent 成本工程:当 Token 变成账单,谁来证明你的省钱策略真的有效?
Agent 成本工程当 Token 变成账单谁来证明你的省钱策略真的有效摘要功能可以靠演示证明可靠性可以靠评测集证明但成本这件事有个特殊之处——它每天都在真实发生却很少有人真的去核算。本文讨论 Agent 工程里长期被忽视的第四个维度成本。先解剖 Agent 循环为什么会让账单以平方级速度膨胀再把经典缓存工程的整套方法——多级缓存、预热、穿透/击穿/雪崩防护——搬进上下文窗口讲清 Prompt 缓存的命中条件与失效陷阱然后给出一套带预算熔断的成本核算实现最后回答一个更根本的问题当你声称缓存让成本降了 80%“时用什么证明这个数字不是错觉。核心判断与此前各篇一脉相承模型和工具厂商会告诉你我们支持缓存、成本大幅下降”而账单不会说谎——单位成本、命中率与质量回归数据才是成本工程唯一有效的验收标准。引子两笔没人核算过的账先讲两个来自社区实践的对照案例。第一个案例关于工具选择。一位开发者长期在用某编程 Agent后来公开坦言自己实在用不起转头开了一个更便宜的订阅换了另一个工具接着干。有意思的地方在于支撑他做这个决定的不是模型能力的对比报告而是每个月真实扣掉的账单。功能差距可以被营销话术稀释价格差距不能。第二个案例关于浪费的真实形态。另一位用户让 Agent 把一套协作方法整理成分享内容Agent 理解偏了方向但理解偏了照样把活干得非常完整——写满了路径、软链和校验流程每个技术细节都没错唯独不是用户真正想讲的东西。结果前面的产出全部推翻重来。事后这位用户的总结很精准这不是让模型聪明几倍的问题而是错误方向上的高质量工作每一个 token 都是白烧的。把这两个案例放在一起能看到 Agent 成本问题的两个真实切面一是账单会直接改变工程决策贵到某个阈值用户会连能力都不谈直接换工具二是浪费的主形态不是单次调用贵而是整条错误路径上的重复产出——一次调用几毛钱没人心疼一个跑偏的任务循环几十轮、每轮携带全部历史上下文账单数字就开始吓人了。大多数关于 Agent 成本的讨论止步于两条建议“换便宜模型和精简提示词”。这两条都对但都太粗了。真正的成本工程需要回答三个问题钱花在哪了哪些钱是可以省的、怎么省以及最关键的——省下来之后你怎么证明真的省了、而且没把质量省没了本文按这三个问题展开。一、Agent 循环的成本解剖账单为什么是平方级的先看一次性问答和 Agent 循环在成本结构上的根本差异一次性问答 Agent 循环N 轮 ───────────────── ──────────────────────────────── 轮1: [系统提示问题] ── 回答 轮1: [系统提示工具定义任务] ── 工具调用 轮2: [系统提示工具定义任务轮1结果] ── 工具调用 输入规模: O(1) 轮3: [系统提示工具定义任务轮1轮2结果] ── ... ... 总成本: 1 次输入 1 次输出 轮k 的输入包含前 k-1 轮的全部结果 总输入 token ≈ O(N²) 累积这个平方级累积是 Agent 账单的第一条数学规律工具返回的结果一旦进入上下文就会在后续每一轮被重新计费。一个三十轮的长任务中间某次工具返回了两万字的数据这笔数据会被重复携带二十多次——除非你有意识地处理它。第二条规律是成本构成里输入占大头。模型定价中输出 token 单价通常是输入的数倍但在 Agent 场景下输出只有下一步决策 工具调用参数通常几百 token而输入是系统提示、工具定义、对话历史和工具返回结果的累积动辄数万 token。这意味着 Agent 优化的主战场在输入侧而不是输出侧——这与很多人的直觉相反。第三条规律与此前讨论过的错误处理篇相呼应重试和降级都是乘法项。一次超时重试意味着这一轮的全部输入 token 再计费一次一次降级切换到备选模型意味着同样的上下文在第二个模型那里从头再计一遍。一个设计不良的工作流重试逻辑本身就能吃掉一半预算。把三条规律合起来成本解剖的结论是优化顺序应该是先砍结构性浪费错误路径、无意义重试、重复携带的上下文再做单价优化模型选择、缓存最后才是提示词层面的精修。反过来做等于在漏水的池子里舀水。二、Prompt 缓存把经典缓存工程搬进上下文窗口结构性浪费里有最大的一块恰好有一个成熟的解法缓存。主流模型厂商如今都提供 Prompt Caching 能力例如 Anthropic 的 prompt caching 与 OpenAI 的 prompt caching 指南机制大同小异如果本次请求的前缀与近期某次请求完全一致命中的前缀部分按大幅折扣计价——通常只有常规输入价的十分之一左右首次写入缓存会有小幅溢价缓存有存活时间过期失效。国内厂商同样跟进比如 DeepSeek 的上下文硬盘缓存把命中折扣做到了更激进的价位。很多团队看到十分之一价格就开通了但真正的工程问题在于你的请求前缀具备命中条件吗这正是经典缓存工程积累了二十年经验的地方。做过后端缓存的人对下面这套问题毫不陌生穿透、击穿、雪崩、预热、多级缓存。把它们逐项映射到 Agent 场景会发现几乎每个经典问题都有对应的 Agent 版本经典缓存问题传统场景Agent 场景对应防护手段穿透查询不存在的数据请求全部打到存储任务间塞入随机 ID、时间戳等易变内容前缀永远不命中把易变内容挪到提示词末段击穿热点 key 恰好过期瞬时流量打穿长会话超过缓存 TTL 后整体冷启动控制会话时长在 TTL 窗口内雪崩大量 key 同时失效批量任务同时启动、同时冷缓存任务错峰下发、启动前预热缓存污染不同业务混用同一 key多项目共用会话前缀互相打架按项目隔离会话前缀映射的核心洞察只有一句话缓存命中的最小单位是前缀而前缀的最小成本单元是稳定性。据此Agent 的提示词应该按稳定性分层组织┌──────────────────────────────────┐ │ 第一层系统提示与角色定义稳定 │ 跨任务、跨天基本不变 ├──────────────────────────────────┤ │ 第二层工具定义与项目规则半稳定 │ 随项目固定任务内不变 ├──────────────────────────────────┤ │ 第三层已完成的对话历史只追加 │ 每轮 N但旧部分不变 ├──────────────────────────────────┤ │ 第四层当前任务指令与工具结果易变│ 每轮都变放最末尾 └──────────────────────────────────┘ ↑ 命中概率从上到下递减前缀顺序不可打乱这个分层结构解释了两个实践中的自杀行为。其一把当前时间戳、随机数或每轮变化的计数器放进系统提示——一个变量污染整个前缀缓存永远 miss。其二任务中途修改工具定义或系统规则——前缀从修改点开始全部失效前面攒的命中前功尽弃。修改规则应该放在任务边界处做而不是任务中途。预热同样适用。经典缓存的预热思路是提前把热点数据填进缓存Agent 场景的对应做法是在批量任务启动前先用一个轻量请求把稳定的系统前缀焐热让后续所有任务直接命中。一些 JIT 编译器花了很大力气解决预热期拖慢启动的问题服务端缓存有缓存预热四步法——识别热点、选缓存系统、预填充、保更新——这套思路原样适用于 Agent 批处理识别所有任务共享的稳定前缀任务下发前先预热批量执行期间命中就是纯收益。还有一个容易被忽略的细节多级缓存思路在这里同样成立。模型端的 Prompt 缓存是最远的一级工作流框架内部的结果缓存相同工具、相同参数直接返回上次结果是更近的一级对话历史本身的摘要压缩此前上下文工程一篇详细讨论过则是减少需要缓存的数据量。三层叠加成本曲线才真正压得下来。TTL 的处理也值得单独说明。击穿的 Agent 变体之所以高发是因为长任务的执行时长很容易超过缓存窗口一个跑了四十分钟的任务如果中途停顿超过 TTL下续轮次就要整体冷启动重付一次写入溢价。务实的做法有两种一是把长任务拆成段段内会话控制在 TTL 窗口内段间交接走检查点恢复此前断点续跑篇的方案在这里直接复用二是接受偶发冷启动但把冷启动的代价算进预算模型而不是在故障报告里第一次发现它。三、预算控制工程从感觉贵到可核算缓存解决的是单价问题但单价便宜不等于总账可控。成本工程的第二块拼图是核算与预算控制——这里的原则是每一次模型调用都必须留下可审计的成本记录。大多数模型 API 的响应里带有 token 用量字段且近年逐步细分到缓存命中与缓存写入各家的字段名不同社区网关如 LiteLLM 做了归一化处理。基于这些字段可以写一个很薄的成本核算层# cost_guard.py —— Agent 调用层的成本核算与预算熔断importtimefromdataclassesimportdataclass,field# 价目表单位为元/百万 token按 input / output / 缓存读 / 缓存写 分列PRICE{input:4.0,output:16.0,cache_read:0.4,cache_write:5.0,}dataclassclassCallRecord:ts:floattask_id:strinput_tokens:int0output_tokens:int0cache_read_tokens:int0cache_write_tokens:int0defcost(self)-float:未命中部分按常规输入计价命中与写入按各自折扣计价plain_inputmax(0,self.input_tokens-self.cache_read_tokens-self.cache_write_tokens)returnsum([plain_input/1e6*PRICE[input],self.cache_read_tokens/1e6*PRICE[cache_read],self.cache_write_tokens/1e6*PRICE[cache_write],self.output_tokens/1e6*PRICE[output],])classBudgetGuard:def__init__(self,monthly_budget:float,task_budget:float):self.monthly_budgetmonthly_budget self.task_budgettask_budget self.records:list[CallRecord][]defrecord(self,task_id:str,usage:dict)-CallRecord:recCallRecord(tstime.time(),task_idtask_id,input_tokensusage.get(input_tokens,0),output_tokensusage.get(output_tokens,0),cache_read_tokensusage.get(cache_read_input_tokens,0),cache_write_tokensusage.get(cache_creation_input_tokens,0),)self.records.append(rec)returnrecdeftask_cost(self,task_id:str)-float:returnsum(r.cost()forrinself.recordsifr.task_idtask_id)defcheck(self,task_id:str)-str:每次发起下一轮调用前检查返回决策超预算则熔断ifself.task_cost(task_id)self.task_budget:returnABORT_TASK# 单任务熔断转人工ifsum(r.cost()forrinself.records)self.monthly_budget:returnABORT_ALL# 月度熔断停止派发新任务returnPROCEED这段代码的重点不在实现——它只有几十行——而在它强制建立的三个习惯。第一逐调用记账缓存的折扣只体现在细分字段里不逐次记录月底只有一张总数账单任何优化分析都无从谈起。第二双预算熔断单任务预算防跑飞单个失控任务烧穿预算月度预算防系统性超支两级阈值对应两种不同的故障模式。第三熔断转人工预算触顶不是异常是设计内行为——被熔断的任务带着已完成的中间状态进人工队列而不是无声失败这与此前错误处理篇的降级原则完全一致。在记账基础上还应该维护一个比总账单重要得多的指标单位任务成本——每成功完成一个任务的平均花费。总账单会随业务量波动单位成本才反映工作流的健康度上一节说只看总额会掩盖优化效果指的就是这个。四、验证用什么证明真的省了现在到了本文的核心问题。前两节给出了缓存分层和预算核算两套工程手段但一个团队做完这些改造后怎么知道效果是真的这正是 Deep Skill Finder 系列一贯的主张任何能力声明——包括你自己做的优化——都要用模型之外的结构性证据来验证。成本领域同样存在三个高频误区。误区一命中率凭感觉宣称。“我们开了缓存成本降了不少”——降了多少缓存命中率的计算口径是什么按 token 数还是按请求数没有逐调用记录这些数字全靠印象。验证方式很直接从 cost_guard 的记录里统计cache_read_tokens / input_tokens的加权比率按任务类型分组。命中率低于预期时最常见的根因就是第二节列出的前缀污染——而这个问题只有数据能暴露肉眼检查几十个提示词模板是查不出来的。**误区二省了钱把质量也省没了。**这是成本优化最危险的暗礁。压缩上下文、砍掉工具结果、换便宜模型每一项都省钱每一项都可能伤质量——而且质量退化往往不立即显现。正确的流程是把成本优化当成一次代码变更对待改造前用评测集此前评测工程一篇给过完整方法OpenAI 的 evals 指南是通用参照记录基线通过率改造后跑同一评测集成本指标和质量指标必须同时验收。只验收成本不验收质量的优化等于没有验收。误区三把 A/B 对照做成了前后对比。“上个月花了 3000这个月花了 1800优化有效”——这个推理有两个漏洞业务量可能变了模型价格也可能调了。严格的做法是固定任务集做对照取一批有代表性的任务分别用旧配置和新配置各跑一遍对比同一任务集上的单位成本与评测通过率。成本对照实验的总开销通常不到一次月账单的百分之几却是唯一能隔离归因的验证方式。三个误区合起来成本优化的验收清单其实很短命中率有逐次记录支撑、单位任务成本在固定对照集上下降、评测集通过率不回退。三条全绿才敢说这次优化有效任何一条缺证据声明就停留在自我描述层面——而本文第一节的案例已经说明靠自我描述做工程决策的代价是整条错误路径上的重复产出。五、实战案例一条日更工作流的成本治理把前面四节的方法串到一条真实形态的工作流上。设想一个典型场景一个内容生产 Agent每天定时执行选题、写作、配图、发布四段流程每天上午下午各跑一轮中间穿插大量的文件读写与平台交互。治理前这条工作流的成本画像通常是系统提示与工具定义占总输入的一半以上且每轮重新全价计费平台交互产生的页面文本每次原样进入上下文偶发的失败重试不设上限。治理动作按本文顺序展开——第一步前缀分层改造把角色定义、工具定义、固定的操作规范整理成稳定的系统前缀类似把项目规则沉淀进固定规则文件的做法这也是社区里被反复验证有效的用法任务相关的动态内容全部后置。改造后稳定前缀跨任务持续命中缓存读折扣直接作用在最大的成本块上。第二步结果级缓存平台交互的页面解析结果按内容哈希做框架内缓存同样的页面在一轮任务内不重复解析。这属于更近的一级缓存与模型端缓存叠加。第三步预算熔断接入第三节的 cost_guard单任务预算设为正常任务成本的五倍——正常任务永远不会触发跑飞的任务会在烧穿前被拦下转人工。第四步分级模型路由选题、筛选这类低风险步骤换用便宜模型写作与发布这类关键步骤保留原模型路由依据正是评测集按步骤拆分后的各段通过率而不是模型厂商的跑分。这一步在对照集上又拉下了约两成单位成本且关键步骤的评测通过率未动。第五步验收固定二十个代表性任务做对照改造前后各跑一遍。验收结果用一张表归档指标改造前改造后验收依据单位任务成本1.00基准约 0.35同一任务集对照逐调用记录前缀缓存命中率0%78%按 token 加权cost_guard 统计评测集通过率基线无回退改造前后各跑一遍失控任务拦截无每月 1~2 次熔断转人工熔断日志这四个数字构成一条完整的证据链命中率解释了成本为什么降对照集排除了业务量干扰评测通过率排除了省出质量问题熔断日志证明预算控制是活的机制而不是摆设。归档这四个数字的意义与此前视觉验收篇强调的证据链一致——三个月后有人质疑这次优化是不是以牺牲质量为代价你能在十分钟内拿出数据回答而不是重新吵一遍。六、总结与展望回到开头的问题当 Agent 每天在真实烧钱谁来证明你的成本策略真的有效答案是一套四层的成本工程结构先做成本解剖认清循环的平方级累积与输入占大头这两个结构性事实再做缓存工程用稳定前缀分层把经典缓存方法搬进上下文窗口防住穿透、击穿与雪崩的 Agent 变体然后是逐调用记账与双预算熔断让每一分钱可审计、让失控有边界最后是验收——固定对照集上的单位成本、命中率数据与质量回归三者同时达标优化声明才成立。这条主线与评测工程、结构化输出、并发验证诸篇一脉相承Agent 工程的可靠性从来不来自模型的自我描述成本领域只是把这个主张变得最无法回避——因为账单是唯一一个不配合任何演出的证据源。能力可以演示、可靠性可以抽检唯独成本每天都在全量发生它天然就是检验一个团队是否真的在工程化使用 Agent 的试金石一个连自己工作流每天花多少钱、钱花在哪一层都说不清楚的团队它对工作流其他方面的可靠性声明同样应该打上问号。如果你正在运营一条长期运行的 Agent 工作流不妨今天就做一个最小改造在调用层加上逐次记账月底统计一次单位任务成本和缓存命中率。这个动作的成本不超过半天但从此以后所有关于成本的讨论——无论是要不要换模型还是缓存到底有没有用——都从印象之争变成数据之争。关于 Deep Skill Finder本文讨论的成本治理前提是你先知道自己工作流里的每个环节——用了哪些模型、哪些 Skill、哪些工具——各自的真实成本与真实能力。Deep Skill Finder 是一个基于真实用户语料的 Skill 发现与选型工具它把社区里被反复验证过的使用经验沉淀成检索与匹配能力帮你回答这个 Skill 在我的场景里到底值不值得用、信不信得过。如果你在读完本文后想给自己的工具链做一次能力与成本的盘点具体的获取方式与使用入口可以在评论区留言或私信交流。