有一次文档与代码的核对跑了 85 个 agent,按 API 价格算大约 $26。这 85 个 agent 全部跑在最贵的模型上,可没人选过它:脚本里没写模型,agent 就沿用了会话的模型。我翻了这一次和另外三次运行的日志,想弄清 Claude Code 省token 该从哪里下手。结论是模型的回答几乎不花钱,钱都花在每个 agent 一遍遍重读自己的上下文上。
这是 workflow 系列的第二篇。workflow 是什么模式、怎么启动、有哪些限制,我在第一篇 Claude Code workflow 文章里讲过。这里只放数字,以及测量之后我改了脚本里的哪些地方。
要点:
- 模型的回答只占一次运行成本的 2% 左右,65% 到 84% 花在把上下文写入缓存上。
- 最贵的环节是复核发现的问题,占一次运行的 50% 到 78%。
- 没人选过的那个模型成了最大的开销。给每个角色指定模型之后,一次提交的 review 从 $3.20 降到 $1.23。
- 没有新提交时再次运行,成本不到一美分:一个小 agent 对一下状态就退出。
- 没有基准任务集,省了多少就无法老实地量化。我暂时没有这样的集合,这是最大的待办项。
我是怎么算的#
workflow 里每个 agent 都有日志:~/.claude/projects/<项目>/<会话>/subagents/workflows/wf_*/agent-*.jsonl。模型的每条回答记录里都有 message.usage 字段:输入 token、缓存读取、缓存写入、输出。我按环节把它们加起来,再乘以 2026 年 11 月 6 日的 API 价格:
| 模型 | 输入 | 缓存写入,5 分钟 | 缓存读取 | 输出 |
|---|---|---|---|---|
| Opus 5.5 | $4 | $5 | $0.20 | $20 |
| Sonnet 5.5 | $2 | $2.50 | $0.10 | $10 |
| Haiku 5.5,提示词不超过 10 万 | $0.10 | $0.125 | $0.01 | $0.50 |
价格按每百万 token 计。订阅套餐不会按次扣钱,但同样的 token 会消耗套餐额度,所以比例是一样的。
有一点要说明。日志里的输出 token 少得可疑,每次请求只有 30 到 100 个,看起来模型的思考过程没有记录进去。因此输出占比只是下限。这不影响结论:就算把输出乘以十,它也不到成本的 20%。
Claude Code 省token 之前,先看 token 费用花在哪#
同一个分支上的四次运行,所有 agent 都用 Opus 5.5:
| 运行 | agent 数 | 请求数 | ≈ $ | 复核占比 |
|---|---|---|---|---|
| review 整个分支,60 个文件 | 58 | 379 | 14.2 | 66% |
| review 一次提交,4 个文件 | 10 | 57 | 3.2 | 50% |
| 文档与代码核对并修改页面 | 85 | 349 | 26.1 | 78% |
| 构建并跑测试直到全绿 | 1 | — | ≈ 0.1 | — |
机制很简单。agent 启动时带着大约 5 万 token 的上下文:系统提示词、工具、CLAUDE.md、记忆、任务。光是 CLAUDE.md 和记忆就有 1.1 万到 1.3 万 token,这还没到任务的第一行。之后 agent 发出 5 到 8 次请求,每次请求都带着全部已积累的上下文和工具返回的结果。大致就是:agent 数 × 每个 agent 的请求数 × 上下文大小 × 模型单价。这四个乘数都能往下压。
缓存并不总是管用。Opus 5.5 的缓存读取是 $0.20,写入是 $5,贵 25 倍。在 review 里,复核的 agent 从邻居写好的缓存里读到了共同的前缀,第一次请求的缓存写入中位数是零。到了文档核对,76 个复核 agent 每个都重新写了一遍自己的前缀,每次 3.2 万 token。26 美元里大约有 12 美元,只是为了把同一份内容往缓存里放 76 遍。
为什么这次缓存没有共享,我没查清。按 workflow 文档,只有模型、effort 级别、agent 类型、工具、返回结构和工作目录都一致时,agent 才会读取彼此的缓存。workflow agent 的缓存只保留五分钟,订阅用户也一样。
复核:贵,而且常常白做#
“一个 agent 找问题,另一个 agent 来反驳”,这是 workflow 里最好的设计,也是最费钱的。每条发现都会启动一个单独的复核 agent,带着它自己的上下文。
在文档核对里,复核 agent 推翻了 76 处不一致中的 36 处,占 47%。这个环节近一半的钱,花在了筛掉本来就不存在的不一致上。每条被确认的发现,成本在各次运行里都差不多,$0.9 到 1.2。
由此得出一个起初看着奇怪的结论:把查找做严格,比多雇复核者更省钱。如果要求查找的 agent 必须附上页面的原话和它读过的那行代码,不存在的不一致在复核之前就会少很多。
外部研究的结论一致。预印本 Refute-or-Promote 里,十个 reviewer 一致确认了一个 OpenSSL 里并不存在的漏洞,最后是一个实证测试把它否掉的。那里没有对照实验,只是单个案例。但教训很清楚:十个 agent 意见一致,并不等于事实。CodeX-Verify 里每多一个复核者,收益都比上一个小:准确率依次提高 14.9、13.5 和 11.2 个百分点。
我在脚本里改了什么#
一共五处改动,每一处针对一个乘数。
每个 agent 明确指定模型。 按文档,没指定模型的 agent 用会话的模型。现在每个脚本开头都有一张表,启动时可以覆盖:
const M = {
scope: 'haiku',
find: A.thorough ? 'opus' : 'sonnet',
verify: A.thorough ? 'opus' : 'sonnet',
state: 'haiku',
...(A.models || {}),
}Haiku 5.5 的缓存写入是 $0.125,Opus 是 $5,便宜 40 倍。侦察(哪些文件变了)和写入状态交给它。查找和复核用 Sonnet。Opus 留给发布前的那次运行,外加一个例外:审计第三方代码时,我让它继续读安装脚本,因为漏掉一个恶意钩子的代价,比任何 token 都高。机械性的工作和小问题的复核我设了 effort: 'low'。
重复的发现在复核前合并。 三个 reviewer 经常从不同角度发现同一个错误。文件相同、行号相差不超过三行,这条发现就只复核一次。超出上限的小问题不复核,而是放进单独的清单并写进日志,这样删减不会悄无声息。
复核者必须拿出事实。 一次调用、调用栈上层的一个条件、命令的输出、一句原话。拿不出事实,这条发现就驳回:
`Keep a finding only with evidence — what you found and where ` +
`(file:line or command output). No evidence → reject.`三票表决只留给发布运行里的严重问题。
只检查新内容。 review 会把最后一次检查过的提交存进 .git 里的一个文件(git rev-parse --git-path change-review-state.json),所以它不会进到提交里。下一次运行看 lastReviewedSha..HEAD,并把没动过的文件上尚未关闭的发现带过来。完整运行放在提交 pull request 之前、rebase 之后和提示词变更之后:脚本里为此有一个提示词版本号。CodeRabbit 的增量 review 和 CI 里按改动选测试,用的是同样的思路。
我没有取消完整运行,是有原因的。当天最严重的一个错误就是它找到的:这个错误把客户端、服务和设置串在三个不同的文件里。逐个文件做增量检查,是看不到它的。
提前退出。 如果距上次运行什么都没变,侦察之后脚本直接返回结果,一个 reviewer 都不启动。
同一个仓库上的结果:
| 运行 | agent 数 | 请求数 | 模型 | ≈ $ |
|---|---|---|---|---|
| review 提交,旧脚本 | 10 | 57 | Opus | 3.20 |
| review 提交,新脚本 | 10 | 40 | Haiku + Sonnet | 1.23 |
| 同上,没有新提交时重跑 | 1 | 2 | Haiku | < 0.01 |
这里的质量对比不严格。旧脚本看的是 review 修改之前的提交,新脚本看的是之后的,两边的发现各不相同:确认了三条对两条。价格仍然可比,因为工作量一样:4 到 6 个文件,10 个 agent。
还有一处改动与钱无关,而是关于“检查 → 修改”这个循环。在我的翻译脚本里,修复 agent 是最后一个动手的,改完没人再读一遍。现在修改之后会跟一次简短的复核,用 Sonnet,effort: 'low'。循环应该以检查收尾,否则最后的改动会没人读过就进了提交。
还没验证的事#
- 没有基准集。 需要 30 到 50 个过去的 pull request,里面有已知的错误,再加上几个故意植入的错误。没有它,我没法说 Sonnet 比 Opus 漏掉了多少细微问题。
- 文档核对里缓存为什么没共享,还不清楚。每次运行最多 $12。
- 1.1 万到 1.3 万 token 的公共规则(21 KB 的
CLAUDE.md加上记忆)仍然会加载进每个 agent。费用文档建议把CLAUDE.md控制在 200 行以内,把特殊规则挪到按需加载的 skill 里。我暂时还没做。 - 除 review 的实测之外,所有节省额都是推算,不是测量。
单独说一下文档核对。它最大的毛病是每次运行都把每一页从头检查到尾。下一步是只核对与改动文件绑定的页面。怎样把页面和代码绑起来、让页面自己知道已经过期,我在那篇讲代码里的文档锚点的文章里写过。
如果你已经保存了 workflow,先跑这一条命令:grep -n "agent(" ~/.claude/workflows/*.js。输出里每个选项中没有 model 的调用,多半就在用你会话的模型。



