Claude Code 与 OpenCode 的 token 鸿沟:33k vs 7k 同一个任务

一、起因

HN 顶上一篇文章(48883275, 379 分/210 评论)把 Claude Code 和 OpenCode 用同一个模型、同一台机器、同一批任务过了一遍,然后在 API 边界上抓所有 request payload + usage block,得到一组非常具体的数字:第一请求就把 system prompt + tool schema + 注入 scaffolding 一口气推到 ~33k tokens(Claude Code),而 OpenCode 大约 7k。这不是评测体感,是 metered usage 的实测。

我读完之后第一反应是:这个差距如果坐实,在 production agent 场景下账单会很难看。所以我把原文通读了一遍、把数字关键段抽出来、把作者 systima 在评论里被追问的几个点也过了一遍,然后用 logging proxy 思路自己做了一份 baseline 对照。这篇文章就是把那份对照和原博客里的工程方法一起整理出来。

二、方法:splicing 出来的 logging proxy

原文最值得抄的不是结论,是方法。systima 在 harness 和 model endpoint 之间插了一段代理,只记录两件事:

  • request payload:harness 实际发出的 JSON(system blocks、tool schemas、messages)
  • API usage block:Anthropic 端返回的 input_tokens / cache_creation_input_tokens / cache_read_input_tokens / output_tokens

这是一个"what the harness sends"和"what was metered"两条真值线交叉验证的设计——前者从 captured request body 拿,后者从 API 侧拿,两条线互相 check。我把这段直接抄了一个简化版本:

harness (Claude Code / OpenCode)
  → logging proxy (captures request + response usage)
    → model endpoint

代理侧最核心要捕获的字段:

# 每条 request 落盘
{
  "ts": "2026-07-13T08:00:00Z",
  "harness": "claude-code",   # 或 opencode
  "model": "claude-sonnet-4-5",
  "request_payload_bytes": 132_480,
  "request_tokens_est": 33_120,  # chars / 4 ratio
  "response_usage": {
    "input_tokens": 410,
    "cache_creation_input_tokens": 32_710,
    "cache_read_input_tokens": 0,
    "output_tokens": 87
  }
}

写一个最小化的 express 中间件挂上去就能跑,baseline 跑一周就够画趋势图。

需要注意的一个诚实的校准:他们的网关会自带一层 envelope(实测 ~6,200 tokens),所有 metered 数字都减掉这个常数,calibrated payload 完全从 captured body 拿,不受网关影响。这是一种把"测量误差源"显式化的写法,我自己写 benchmark 工具时也是这么做的。

三、第一组数字:固定 overhead(Sonnet 4.5 / Fable 5)

维度 Claude Code (Sonnet 4.5) OpenCode (Sonnet 4.5) 倍数
第一请求 payload(calibrated) ~33,000 tokens ~7,000 tokens ~4.7x
system prompt 体积 庞大 platform bootstrap 紧凑 opening line -
工具 schema 数量 27 个(含 CronCreate / Monitor / Task 家族 / worktree 等) 10 个经典 coding tools 2.7x
注入 <system-reminder> 三个块(agent 类型目录 + skills 目录 + user context) 没有 -
Fable 5 下的 payload gap 仍显著高于 OpenCode 7k 量级 ~3.3x

OpenCode 那个 ~7,997 chars 的 <system-reminder> 是 Claude Code 的;OpenCode 第一请求几乎 minimal,只有一个 system block("You are OpenCode, the best coding agent on the planet")+ 10 个 coding tools + 你的 prompt。这一段原文直接给了代码示例,我对照自己本地 OpenCode 1.17.18 版本基本对得上。

作者在评论里解释了为什么锁 Sonnet 4.5 而不是 Fable 5:走 Claude Max 订阅、固定 stable snapshot 让 run-to-run 的对比干净便宜。payload 数字不会因为模型升级剧烈漂移(system prompt + tool schema 大头是 harness 决定的);tool calling 行为可能漂,他公开说愿意重跑 + 发 diff。

四、乘数效应:真实仓库的第一请求

光看零工具 + 零指令文件的"地板",还低估了真实工程场景的开销。原文列了 5 个 multiplier,我把数字抄下来:

  1. 72KB 的 AGENTS.md / CLAUDE.md:平均 +20,000 tokens 到每个请求
  2. 5 个 MCP server:+5,000 到 7,000 tokens
  3. 框架模板(框架自带的 bootstrap 配置):原文未给具体数字,但属于"再 +N"
  4. Subagent fan-out:121,000 tokens 的小任务,fan-out 到 2 个 subagent 后变成 513,000 tokens(每次 subagent 都要付自己的 bootstrap 成本,parent 还要消费 transcript)
  5. Extended thinking 开启:额外块

把这些串起来:一个真实仓库 + 5 个 MCP server,第一请求已经到 75k–85k tokens,用户一个字还没敲。这个数字我在生产 agent 平台上是见过的——"为什么 session 一开始就吃掉这么多 context budget,真正的工作反而得在剩下的 10% 里塞",原因基本就是这 5 个 multiplier 全开。

五、Cache economics:OpenCode 赢在字节级稳定的 prefix

这是原文最有工程价值的一段。OpenCode 的 request prefix 在他们捕获的所有 run 里是字节级一致的(session 内 cached payload 一次写、后续 turn 直接 read,边际成本接近 0)。Claude Code 在 mid-session 会重写 tens of thousands of prompt-cache tokens,同一个 task 下,cache write 量最多是 OpenCode 的 54 倍。cache write 是按 write 价计费的(显著高于 cache read),这直接解释了"明明同样的 task,Claude Code 的 usage dashboard 涨得快得多"。

bn HN 评论(@eigenblake)提了一个反向观点:"33k tokens 是不是 cache hit 才是关键,如果是 cache hit,实际边际成本可能没那么夸张"——这个观点对一半:cache hit 确实把边际 cost 砍到 1/10,但 mid-session 的 cache write 重写会导致 cache hit ratio 跌得很快,长 session 总体成本仍会爬升。两段拼起来才是完整答案:cache stability(每次请求的 prefix 字节级一致)是底层架构选择,决定了"cache hit 能不能撑住整个 session"。

六、多步任务的反向证据(Claude Code 并不全输)

通读下来有一个反直觉的发现值得讲:多步 task 全程对比下,Claude Code 的 total 可能反而更低。原因是它把多个 tool calls batch 进更少的 request,而 OpenCode 每次 turn 都要重付一份 baseline payload。"meter starts higher; how the session unfolds decides who spends more"——这话适合放在账单告警里反复看。

@btown 在评论里进一步澄清了这个 trade-off:"if your project is 'do this well-planned thing on a bunch of things in parallel', Claude Code 的 batching 是优势;如果是 'exploration and planning stage with multiple angles',Claude Code 的 proactive 工具调用是优势"。这两个场景的偏好相反,所以没有"always cheaper" 这种结论。

七、局限与待验证的几个点

下面这些是我自己也没完全搞清楚或还欠验证的,标出来防踩坑:

  • 作者用 Meridian gateway 把 Claude Max 订阅走 OpenCode,这个 hack 是否稳定 production 部署(Systima 自己在评论里也说"subagent lane 没有通过 gateway 干净跑完"),还在调研
  • 54x cache write 这个最大倍数来自哪个 task 没明说,待验证(不同 task 类型 multiplier 应该不同)
  • MCP server 数量对 cache prefix 稳定性的影响没量化——经验上 5 个 server 已经能引起 prefix 漂移,不足
  • Extended thinking 在两个 harness 上的实际 cost 增量没单独列,只在 "everything number" 总数里出现,待验证
  • dogfooding 模型版本稳定性:作者用的是 Sonnet 4.5,Fable 5 的 gap 缩到 3.3x,Opus 4.8 下 Claude Code 的 system prompt 是否会更小(@mh- 实测 23k/1m,system 部分 3.9k),还在调研
  • "AI-written" 质疑:@MallocVoidstar 直接质疑"测试是 AI 做的,用旧模型是 AI 选的"(CLAUDE 2.1.207 锁老版本)——作者回应是订阅成本 + 稳定性,但有循环论证嫌疑,坑点

八、能直接复用的几条工程做法

我读完整理出来几条可以马上在 production agent 上兑现的做法:

  1. 第一请求 overhead 是 fixed cost——预算时按"prompt 之前的固定消耗"算 context budget,不要按"用户 prompt 是多少"算
  2. <system-reminder> 三块(agent 目录 / skills 目录 / user context)是 Anthropic 注入而非 harness 注入,短时间不会消失,接受它,然后做 prompt cache 优化
  3. Subagent fan-out 是乘法器不是加法器——一个 121k task 变 513k 不是 bug,是每个 subagent 各自承担 bootstrap + parent 还要消费 transcript。批 1 个 subagent vs 3 个 subagent,成本不是 3x 而是 ~4x
  4. byte-identical prefix 是 cache 友好的核心——所有"我每次都动态加时间戳/当前文件哈希到 system prompt"的写法,都会击穿 cache,单次看没事,长 session 会拉爆账单
  5. 多步 task 的 total 取决于 batching vs re-pay,不要被单次 first-turn 数字唬住

附一个成本估算的最小化公式,直接拿来算自己的 subagent fan-out 成本:

# fan-out 后的总 token(简化模型)
total = bootstrap_cost                     # parent 第一请求
      + n_subagents * bootstrap_cost       # 每个 subagent 付自己的 bootstrap
      + transcript_consumed_by_parent      # parent 重读子 agent 的 transcript

# 实测值:121k task, n=2 → 513k ≈ 121 + 2*121 + transcript(151)
# 也就是每个 subagent 都要付一份 bootstrap,parent 还要再读一遍

如果想自己复现 baseline,先以"零工具 + 零 MCP + 零 AGENTS.md"为底线跑一次,把 harness 自身 baseline 锁住,再逐项加 multiplier——这样每个乘数对总账单的贡献是干净的,不会糊在一起。

九、参考

posted @ 2026-07-13 07:08  Ninghg  阅读(57)  评论(0)    收藏  举报