
你有没有遇到过这种情况月底收到 Claude API 的账单一看数字比上个月多了三成第一反应是Anthropic 悄悄涨价了但翻遍官方价格页每百万 Token 的单价纹丝不动。我前两个月就实打实遭遇了一次——账单从 214 美元涨到 278 美元涨幅正好 30%可价格表上一分钱都没变。问题到底出在哪这不是个例。Claude Code 的日常使用、多轮对话的上下文累积、prompt caching 的读写计费差异、extended thinking 的隐藏输出……任何一个环节的细微变化都可能让账单悄悄爬升。这篇我把自己排查账单的思路、定位根因的方法、以及最后落地的成本控制清单完整写下来给所有用 Claude API 的同学做参考。不管你是个人开发者跑脚本还是团队在 Claude Code 上做 Agent 开发这套分析框架都适用。1. 先用账单结构说话Claude API 到底按什么收费很多人对 Claude API 的计费理解停留在按 Token 数收钱这个理解没错但太粗糙。实际账单里每一项费用的构成完全不同不搞清这些你根本没法分析为什么账单会涨。1.1 四种计费入口普通输入、普通输出、缓存写入、缓存读取从 API 返回的 usage 对象看一次请求的用量被拆成了四个字段input_tokens用户消息和 system prompt 消耗的输入 Tokenoutput_tokens模型回复消耗的输出 Tokencache_creation_input_tokens第一次写入缓存时消耗的输入 Tokencache_read_input_tokens命中缓存时读取的输入 Token这四个数字的单价完全不同。以 Sonnet 系列的官方价格为例实际以官方价格页为准计费项单价每百万 Token备注输入 Token3 美元基础输入价格输出 Token15 美元约是输入价格的 5 倍真正的成本大头缓存写入3.75 美元比普通输入贵 25%一次性成本缓存读取0.30 美元只有普通输入的 10%命中越多越省钱这里有一个很多人忽略的事实输出 Token 的价格是输入 Token 的 5 倍。也就是说两个请求一个输入 100K Token 输出 1K Token另一个输入 1K Token 输出 100K Token后者的成本反而远高于前者。分析账单时如果只看调用次数或总 Token 数很容易被误导。1.2 混用多个模型账单会被平均价格扭曲很多团队的实际调用里不会只用一款模型。简单任务路由到 Haiku复杂分析用 Sonnet偶尔重活交给 Opus。账单上的总金额是所有模型费用的加总但如果你拿总金额 ÷ 总 Token 数去反推单价会得到一个被模型比例扭曲的平均价。这个平均价本身没有太大意义但很多人在做成本对比时正好掉进这个坑里——明明模型切换比例变了却以为价格变了。我在排查那 30% 涨幅时做的第一件事就是把账单金额按模型拆开、按天列出。这一步做完很多问题立刻现形。1.3 价格没变不代表单位成本没变这句话是整篇文章的核心。单价不变的情况下账单上涨只可能来自两个变量Token 量变多同样的功能每次调用消耗的 Token 变多了或者调用次数变多了。Token 的贵贱组合变了比如缓存命中率下降原本便宜的缓存读取被替换成更贵的缓存写入或普通输入。把这两个变量盯住任何账单异常都逃不掉。下一部分就按这两个变量展开看看最常见的上涨入口有哪些。2. 按风险排名拆解账单悄悄涨 30% 的五个入口根据我自己的观察和身边团队的反馈Claude API 账单上涨通常不是某一个惊天大坑造成的而是几个小变化叠加的结果。但排在前面的一定有规律。2.1 第一名Agent 场景下的上下文累积这是 Claude Code 类应用最典型的成本杀手。一个 Agent 会话从开始到结束每一次工具调用都要把之前的全部对话历史重新发给模型。假设每次工具调用消耗的上下文是 50K Token一个会话跑了 20 轮工具调用光输入就累计了 1M Token。这里面虽然有缓存机制兜底但缓存只对重复部分生效新增的内容每一次都要按更高价格写入。这里还有个隐藏点Claude Code 这类 Agent 工具会把系统提示system prompt、工具定义、环境信息都算进输入里。这些你看不见的 Token 往往比你自己写的 Prompt 大得多。我用 tool use 做了一个简单任务单次请求的输入里工具定义就占了 12K Token——比我实际写的业务代码提示长一个数量级。2.2 第二名缓存命中率下降单价悄悄变贵很多人启用 prompt caching 之后就不管了觉得我开了缓存肯定省钱了。但缓存是否真的在省钱取决于命中率。如果缓存命中率从 90% 掉到 70%意味着有更多请求走了 25% 溢价的缓存写入路径或者完全走了普通输入路径成本自然往上走。缓存失效的原因非常隐蔽常见的有三种请求参数里多了一个时间戳字段导致 cache key 每次都变system prompt 里拼了动态内容比如当前日期、随机用户信息消息顺序发生变化比如把用户消息插到历史消息中间随便哪一个都会让缓存的实际效果大幅缩水。2.3 第三名extended thinking 带来的隐藏输出Claude 的思考模式extended thinking在 API 里会额外产生 thinking tokens而思考 Token 是按输出价格计费的。很多场景开 thinking 是合理的但如果你在不需要复杂推理的简单任务上也开着 thinking每一分输出都比原来贵得多。更头大的是很多调用方只在代码里开了 thinking 参数日志里却不打 usage 明细导致账单涨了都找不到源头。2.4 第四名重试风暴和并发放开API 偶发 529/500 错误时如果重试策略写得比较粗暴比如固定重试 3 次、无退避一次故障可能让同一请求被执行 3~4 次而每次执行都是全额计费。我见过一个案例某天 Anthropic API 出现短暂抖动某团队的重试逻辑让当天请求量翻了 2.6 倍账单当天就多花了 40 多美元。另外很多同学在压测或者上线新功能时会放开并发限制max concurrency但忘了同步评估单次请求的成本导致整体费用像坐电梯一样往上走。2.5 第五名模型路由悄悄偏航有的团队做了低成本优先路由简单问题走 Haiku复杂问题走 Sonnet。但路由逻辑如果依赖模型自身的判断比如用 LLM 判断复杂度偶尔会把简单问题误判成复杂问题路由到贵模型。这种偏差单次看不出来但一个月累计下来相当可观。以上五个入口是我在实际排查中遇到概率最高的。接下来我完整走一遍排查过程用真实数据演示怎么定位到具体是哪一个入口。3. 从 214 到 278一次 30% 涨幅的完整排查链路那段时间我管理的一批 Claude API 应用账单从上个月的 214 美元涨到了 278 美元。价格页面没变调用量看起来也没大涨那 64 美元去哪了3.1 第一步拉取明细按天按模型聚合排查任何成本问题最重要的前提是有日志。如果你的请求没有经过网关或中间件直接连 Anthropic API那现在立刻去检查至少有这些字段需要记录时间戳模型名称请求来源哪个应用/任务四个 token 计费字段input、output、cache creation、cache read是否开了 extended thinking是否走了 batch 接口我用一个简单的网关把请求日志落到了 ClickHouse跑了个按天聚合日期请求数输入 TokenM输出 TokenM缓存写入M缓存读取M估算成本美元6月1日1,20318.43.14.252.83.26月15日1,35225.84.67.960.14.86月30日1,50138.25.912.455.36.7这里能看出几个趋势请求数只涨了 25%但输入 Token 涨了 108%缓存写入涨了 195%缓存读取反而下降了。答案其实已经被锁定了大半。3.2 第二步对比缓存命中率与上下文分布继续看缓存读取比例。定义缓存命中率大致为cache_read ÷ (cache_read cache_creation input_tokens)。我算下来6 月中旬之前命中率稳定在 75% 左右6 月下旬掉到了 58%。同时单次请求的平均输入 Token 从 15K 涨到 25K。两个数据一交叉结论就出来了上下文在变长平均输入涨了 66%说明对话历史/上下文累积比原来更严重。缓存命中率在下降说明请求之间的公共前缀在变少或者缓存 key 在被污染。3.3 第三步翻代码定位具体改动我继续查了 6 月中旬前后的代码提交记录找到了两个嫌疑犯。第一个一个同事在 system prompt 里加了当前时间的动态字段用于给模型提供实时日期。这个改动直接让缓存 key 每天变化甚至每次请求都变化命中率自然崩了。第二个一个对话类应用把用户历史对话从只保留最近 5 轮改成了保留最近 10 轮而且没有做任何摘要压缩。上下文长度翻倍输入 Token 直接翻倍输出量虽然没有明显变化但整体成本被输入部分拉高。这两个改动单独看都很小叠加起来就造成了 30% 的涨幅。修复也很简单动态时间戳改为使用缓存的 key 策略时把时间精度从秒级改成小时级对话历史加上滑动窗口摘要。3.4 这次排查沉淀出的可复用方法这次排查链路可以沉淀成一套方法所有请求必须打日志别让 usage 数据流失。按天聚合四个 token 字段立刻可以看出异常拐点。算缓存命中率、平均输入/输出 Token定位是量的问题还是单价组合的问题。结合代码提交时间线做交叉验证。这套方法我已经在多个项目里验证过绝大多数账单异常都能在半小时内定位。4. 三个最容易吃钱、又最不容易发现的场景排查心得之外我想再展开三个具体场景。这三个场景我用真金白银买过教训值得单独写下来。4.1 Claude Code 跑批量任务长会话 工具循环的叠加Claude Code 在跑批量任务时一次会话可能持续几十分钟工具调用几十次。每次调用系统提示 工具定义 命令历史 文件内容全部算输入工具调用的输出还要再作为下一轮的输入这类任务的成本公式几乎等于上下文长度 × 调用轮数 × 单价。上下文一旦涨到 100K单次会话的成本就非常可观。我的建议是批量任务尽量拆分成短小会话每个会话只做一件事跨会话需要共享的信息放到记忆文件里而不是塞到上下文里。4.2 RAG 检索库变大无关内容也进了上下文做 RAG 的同学要特别注意。检索出来的文档块如果超过 5 个每个 500 Token一次请求的输入直接多出 2500 Token再加上原始问题、历史对话、系统提示输入轻松过万。如果检索质量不好还会带上无关内容白白烧钱。控制方法是调整 vector 检索的 top_k、对文档块做重排、检索前先做 query 改写压缩。4.3 批处理任务里的隐形成本放大器定时任务的高频全量很多人没用 batch 接口还开着高频定时任务比如每 5 分钟全量巡检一次。高频 全量这两个词组合在一起几乎必然导致成本失控。我的调整思路是把 5 分钟的全量巡检改成增量巡检 15 分钟全量非实时任务统一走 batch。5. 算明白账之后我的 Claude API 成本控制清单最后分享一套经过实践验证的控制手段按投入产出比从高到低排列。5.1 建立 usage 日志与每日告警没有数据一切优化都是空谈。至少在网关层记录四个 token 字段每日聚合后设置告警阈值比如单日成本环比超过 20% 就通知。这一步只需要半天工作量但能避免 90% 的账单失控。5.2 缓存策略评审启用 prompt caching 后定期检查命中率。一个简单的判断标准如果命中率低于 70%说明你的 prompt 设计或缓存 key 设计有问题优先排查动态字段。固定前缀尽量稳定把经常变化的字段移到可变部分。5.3 分层路由让每个模型干它擅长的活儿把任务按复杂度分层简单分类、格式化、关键词抽取交给 Haiku需要推理、写作、代码生成的交给 Sonnet只有极少数高难度场景才动用 Opus。同时在路由层记录每次模型选择的结果定期审视路由是否合理。5.4 控制上下文而不是无限膨胀长会话一定要有瘦身机制对话超过 N 轮就做摘要历史消息压缩成结构化记忆工具调用的中间结果及时清理。RAG 场景严格控制检索块数量和长度。5.5 非实时任务走 batchAnthropic 的 batch 接口有折扣而且 24 小时内完成非常适合报表生成、数据标注、批量分类这类任务。迁移成本极低就是把请求方式从单条调用改成批量提交。5.6 重试策略必须做指数退避把简单的固定重试 3 次改成指数退避 最大 5 次 随机抖动同时在重试前判断错误类型如果是 529 过载退避时间长一点如果是 400 参数错误重试也没用。那次 30% 的涨幅修复之后我顺便把上面这套逻辑固化成了团队的成本巡检流程。最近三个月账单不仅回到了原来的水平还因为 batch 和分层路由省下了大约 18% 的支出。回头看最大的教训其实就一句话API 的成本不是单价 × 次数这么简单Token 的构成、缓存的命中、上下文的长度、模型的分配任何一个变量都在悄悄影响你的账单。如果你现在也遇到价格没变但账单涨了的情况别急着怀疑平台偷偷调价——从 usage 明细入手半小时之内你就能找到那个藏在细节里的凶手。