Claude Code 为什么越用越贵?Anthropic 终于公开了 Agent 成本秘密

解读 Anthropic 官方文章讲清 Claude Code 的成本机制:模型选择、输入输出定价差异、Prompt Cache 命中规则,以及一套可以直接照做的省 token 实操清单。

阅读时长: 6 分钟
共 2675字
作者: eimoon.com

上周 Anthropic 官方博客发了一篇很少见的"讲成本机制"的文章 ——《Maximizing the value of your Claude Code sessions》。

不是安利新功能,也不是发布会通稿,而是老老实实地告诉你:同样一个任务,不同的用法,花的钱可能差好几倍。这在过去的开发工具里是不存在的——你的 IDE 不会因为你今天多写了几行代码就多收钱,但 Agentic 编程工具会。


先搞懂一件事:省 token ≠ 少用 token

Anthropic 在文章里提到了一个很重要的观点:

高效使用 token,不意味着减少 token 数量,而是确保每一个 token 都服务于真正的任务。

翻译过来就是:不是让你抠门,而是别让 token 花在你没要求它做的事情上

同样修复一个失败的测试,Claude 可能三两下就读完对应文件改完了;也可能先满仓库 grep 一遍,顺手读了十几个不相关的文件——这些文件读进去之后,接下来的每一轮对话都要重新带着它们,模型也要多花精力"绕开"这堆无关信息去思考。

结果就是:同一个 bug,同一个修复方案,账单可能差出几倍。


决定单个 token 价格的三件事

1. 模型大小

模型越大,单 token 越贵,这个很好理解。原文的建议很实在:问题真的复杂、含糊不清的时候上大模型,routine 的活儿用小模型。这个系数会乘在下面所有因素上,所以模型选错了,后面怎么优化都事倍功半。

2. 输入 vs 输出

请求分两个阶段:

  • Prefill(预填充):模型读你的输入(system prompt、CLAUDE.md、对话历史),这是输入 token。
  • Decode(解码):模型一个 token 一个 token 地往外吐,包括 thinking、工具调用、最终文字回复,这是输出 token。

关键点:输出比输入贵大约 5 倍,因为解码是逐 token 串行生成的,占用 GPU 时间更长。而 thinking token 也算输出,它的用量由 /effort 等级控制。

💡 小技巧:如果你确定这一轮是纯体力活,不需要模型"想",可以用 MAX_THINKING_TOKENS=0 claude 直接关掉 thinking(比 /effort low 还低一档,Fable 5 除外)。

3. 有没有命中 Prompt Cache —— 这是最容易被忽视的一项

这是 Claude Code 成本机制里最关键的一点。

如果一个新请求的开头和上一次请求完全一致,服务器就能直接复用之前算好的状态,只需要重新计算"新增的那部分"。这就是 prompt caching。

  • 缓存命中(读):只要正常输入价格的 0.1 倍
  • 缓存写入:比正常输入贵,最多到 2 倍(但只发生一次)

Claude Code 自动帮你管理缓存,不用手动开。但有些操作会直接打穿缓存,一旦打穿,后面整段对话都要按全价重新预填充一遍:

操作 是否打破缓存
/model 切换模型 ✅ 打破(每个模型有独立缓存)
/effort 切换等级 ✅ 打破(effort 也是缓存 key 的一部分)
Fast mode 开启 ✅ 打破(按 fast mode 价格重新预填充)
/compact ✅ 打破(对话被替换,但 system prompt 前缀不受影响)
超过 1 小时无操作(订阅版) ✅ 打破(API key 默认 5 分钟,可用 ENABLE_PROMPT_CACHING_1H=1 延长到 1 小时)
Resume 旧会话 ✅ 基本必破(缓存早就过期,而且系统提示词会重新构建)

结论很直接:model 和 effort 要在会话开始或刚 /clear 完的时候定好,不要中途改。

还有一个容易被忽略的细节:如果最近几轮跑偏了,别急着 /compact,先试试 /rewind ——它只是把这几轮从对话末尾切掉,前面的内容依然在缓存里,不产生任何额外费用;而 /compact 是重写整段对话,一定会花钱(只是趁着还在缓存期做会便宜很多)。


决定一次会话总共花多少 token

搞懂了单个 token 的价格,第二个问题是:一次会话到底往上下文里塞了多少东西

有个容易被忽略的事实:上下文里的任何东西,一旦进去,后面每一轮都要重新带上它——哪怕是缓存读取,便宜是便宜,但也不是零,而且会占用模型"思考"的空间。

实操清单(这部分是重点,建议直接抄作业)

① 用 @文件名 而不是直接打路径

# 不推荐
帮我修一下 utils.test.ts 里失败的测试

# 推荐
帮我修一下 @utils.test.ts 里失败的测试

@ 引用会让文件直接附到你这条消息里,省掉一次 Read 调用(甚至一次搜索)。注意:同一个文件同一次对话里 @ 一次就够了,它会一直留在上下文里,重复 @ 相当于塞进第二份拷贝。

② 给"吵闹"的命令加静音参数

命令输出会像文件一样永久追加进对话。跑测试打印 400 行 PASS,这 400 行会在接下来所有轮次里反复被重新发送。

# CLAUDE.md 里直接写清楚怎么跑
运行单个测试文件用: npx vitest run <file> --reporter=dot

超过 30000 字符的输出,Claude Code 会自动写文件、只留预览(可用 BASH_MAX_OUTPUT_LENGTH 调整阈值),但阈值以下的中等噪音输出没人帮你处理,得自己加 flag 或者交给子代理。

③ 新会话先跑一次 /context

看看开局默认加载了什么(CLAUDE.md、MCP 工具定义等),该砍的砍:

  • CLAUDE.md 只留具体指令,workflow 类的东西挪到 skills 里(按需加载,不占常驻上下文)
  • 这个会话用不到的 MCP server,/mcp 里直接关掉

④ 任务切换就 /clear,任务内部阶段性完成就 /compact

一次长会话比拆成几次短会话贵得多,因为第 40 轮也要重新"背"前面 39 轮的内容。

# 想保留会话以后再回来?
/rename   # 先改个名字方便找
/clear    # 再清空

/compact 时记得告诉它要保留什么,或者在 CLAUDE.md 里固定一段 “Compact instructions”。

⑤ 警惕看不见的"隐形轮次"

/loop 每次触发都是一次完整的对话轮次,会拖着整段历史一起跑,如果超过 1 小时还会顺带撞上缓存过期。建议开个新终端单独跑 loop,别塞进主会话。

⑥ 大量输出、用完即丢的活儿,交给子代理

子代理有自己独立的上下文窗口(带 system prompt、工具、CLAUDE.md,但不带你的主对话),跑完只把结论带回来,过程全部丢弃。适合"翻日志"这类会产生大量垃圾输出的任务:

帮我用子代理去翻一下这份日志,找出报错的堆栈

缺点是子代理拿不到主会话已经读过的东西,可能要重新读一遍,小任务用子代理反而是净亏。如果某个吵闹任务你天天在跑,干脆给它建一个专属子代理定义,model: haikusonnet,别让它跟着主会话用大模型烧钱。


一张图记住优先级

按对成本影响从大到小排:

  1. 模型选择 —— 系数级影响,选错了后面全白搭
  2. 会话时长 / 是否及时 /clear —— 上下文越滚越大,每轮都在重复付费
  3. 中途切换 model / effort —— 直接打穿缓存,全量重新预填充
  4. 命令输出是否静音 —— 决定了上下文里"垃圾"的密度

写在最后

这篇文章传递了一个更大的信号:Agentic 工具的成本模型,本质上是"上下文经济学"——不是省着用,而是清楚知道什么东西该留在上下文里、留多久、什么时候该换个干净的房间重新开始。

理解这套机制之后,你会发现很多"莫名其妙很贵"的会话,根源往往就是:中途换了模型、开了一堆不必要的 MCP、或者一个长会话从早跑到晚忘了 /clear

原文附了官方的 5 分钟阅读版,建议直接看一遍原文加深理解: 👉 https://claude.com/blog/maximizing-the-value-of-your-claude-code-sessions

关于

关注我获取更多资讯

月球基地博客公众号二维码,扫码关注获取更多 AI 与编程资讯
📢 公众号
月球基地博客作者个人微信二维码,扫码交流 AI 与编程话题
💬 个人号
使用 Hugo 构建
主题 StackJimmy 设计