实测数据显示 Claude Code 在编码前发送 33k token,而 OpenCode 仅 7k。对比工具成本效率的关键参考。
我们将 Claude Code 和 OpenCode 放在相同的模型、机器和任务上,然后检查了所有发送和接收的内容。
当我们要求两个工具回复一行时,Claude Code 在提示词真正到达之前已经使用了约 33,000 个 token 的系统提示、工具模式和注入的脚手架。OpenCode 使用了约 7,000 个。
OpenCode 的请求前缀在我们捕获的每次运行中都是字节相同的;它支付一次缓存负载的成本,然后在每次读取时仅支付几分钱。
Claude Code 则不同,它在会话中间重写了数万个提示缓存 token,在同一任务上,缓存 token 写入量最多是 OpenCode 的 54 倍。
缓存写入当然按溢价计费,这就是使用 Claude Code 时使用量仪表板攀升的原因。
一个生产仓库的 72KB 指令文件(AGENTS.md 或 CLAUDE.md)为每个请求额外添加了(平均)20,000 个 token。五个适度的 MCP 服务器再增加 5,000 到 7,000 个。在真正的工作设置发送第一个请求时,用户甚至还没有输入一个字,就已经耗费了 75,000 到 85,000 个 token。
一个直接完成的任务花费了 121,000 个 token,但当分散到两个子 agent 时花费了 513,000 个 token。这是因为每个子 agent 都是自己的 agent,在每一轮都重新读取自己的系统提示和工具,所以分散操作会让多个完整基线同时运行。
也就是说,父 agent 仅摄取每个子 agent 返回的结果,而不是其完整的记录。
在多步任务上,Claude Code 的整个任务总成本低于 OpenCode,因为它将工具调用分批在较少的请求中进行,而 OpenCode 则在每一轮都重新支付其较小的基线。计价器从较高的起点开始;会话如何展开决定了最终谁花费更多。该优势在我们测试的第一个模型上成立;在较新的模型上重新运行,同一任务花费了大约 298,000 个 token,而 OpenCode 花费了 133,000 个。
以上每项发现都在第二个模型家族上进行了交叉检查。模式保持一致,我们在下面讨论了一个细微差别。
本文的其余部分展示了我们如何在 API 边界处测量所有这些,token 的去向,以及提示词缓存的用处和局限。
工具有效负载的每个 token 都是你无法用于任务的工作上下文 token。
如果你在生产环境中运营 agent 型 AI,特别是在《欧盟人工智能法》下,其中第 12 条要求你记录和理解你系统的行为,"我的 agent 实际发送了什么"是你应该能够用数据回答的问题。
我们在每个工具和模型端点之间插入了一个日志代理。
harness (Claude Code / OpenCode)
→ logging proxy (captures request payloads + response usage)
→ model endpoint
代理记录每个请求的两件事。第一件是工具发出的确切 JSON 有效负载,意味着系统块、工具模式和消息。第二件是 API 返回的使用块,涵盖输入 token、缓存写入、缓存读取和输出 token。
有效负载捕获是工具发送内容的事实依据。使用块是计费内容的事实依据。
我们在这些条件下进行了测试。
工具:Claude Code 2.1.207 和 OpenCode 1.17.18,均固定在 claude-sonnet-4-5(2026 年 7 月)。一个缩小的矩阵(基线、缓存任务和多步任务)后来重新运行时固定在 claude-fable-5;当模型改变结果时,我们会在下文说明。
基线隔离:新配置目录,无 MCP 服务器、无用户设置、无内存;空工作区,无指令文件;权限绕过。乘数通道然后一次添加一个变量。
任务:T1 说"回复完全:OK"并隔离固定开销(每个工具三次运行)。T2 读取一个预设文件并总结它。T3 是针对 FizzBuzz 加上一个检查脚本的写-运行-测试-修复循环。
质量检查:一个单独的十通道基准,每个工具五次运行,针对预设、hash 验证的测试套件,评分通过率同时记录 token 成本;在质量部分报告。
零工具变体:Claude Code 带 --tools "" 和 OpenCode 带 "tools": {"*": false},分离系统提示和工具模式权重。
在数字之前有一个完全披露的说明:
我们的流量通过 Meridian 流动,这是一个本地网关,将 Claude Code SDK 桥接到标准 Anthropic 端点,以便 Claude Max 订阅可以驱动第三方工具。它用 SDK 自己的信封包裹每个请求,一个常数,我们在 Sonnet 路径上测得约 6,200 个 token,在 Fable 路径上测得约 3,500 个(使用裸校准请求),并从以下每个计费数字中减去。
有效负载级别的数字来自捕获的请求正文,网关无法影响,因此是精确的。
组件估计的字符到 token 转换使用每个工具自己测量的 4.1 到 4.4 字符每 token 的比率,源自冷缓存锚点,其中计费的写入等于完整有效负载,而不是通用启发式。
任务是 22 个字符。以下是每个工具在第一个请求中发送的内容。
27,344 字符,3 个块
27 个工具,99,778 字符
10 个工具,20,856 字符
7,997 字符的 <system-reminder> 块
OpenCode 的请求接近最小值。有一个系统块以"You are OpenCode, the best coding agent on the planet"开头,加上十个经典编码工具,加上用户的提示作为唯一内容。
Claude Code 的请求是一个平台引导程序。27 个工具包括编码核心加上整个后台 agent 和编排套件,从 CronCreate 和 Monitor 到 Task 族、worktree 管理和推送通知。
在用户输入的提示之前,其首条消息携带三个注入的提醒块;agent 类型的目录用于委派,可用技能的目录,和用户上下文。
工具模式是两者的主导项。Claude Code 的约 33,000 个 token 中约 24,000 个是工具定义,而 OpenCode 的约 6,900 个中约 4,800 个。
剥离工具可以隔离系统提示本身。Claude Code 的权重为 26,891 字符,约 6.5k token。OpenCode 的是 8,811 字符,约 2.0k token。
当工具被禁用时,两个工具都会轻微修剪它们的提示。即使完全没有工具,Claude Code 的指令集也超过 OpenCode 的三倍大小;残留是行为主义,意味着语气规则、安全指导、任务管理指令和环境描述。
T2 要求每个工具读取一个文件并总结它。两者都生成了正确的总结。
Claude Code 采用了 6 个 HTTP 请求和大约 199,000 个累计计费输入 token。OpenCode 采用了 4 个请求和大约 41,000 个,加上一个 Haiku 侧调用用于会话标题。
这些 token 中的大部分是以输入价格十分之一计费的缓存读取。三件事随有效负载扩展;首轮缓存写入、每轮读取和上下文窗口消耗,缓存折扣不会减少这些。
33k token 的基线意味着每轮开始时已经在 200k 窗口的六分之一处,才有任何代码进入对话。
T3,写-运行-测试-修复循环,反转了基线设置的预期。
Claude Code 将整个工作(两个文件写入和两个脚本执行)分批处理成单一平行工具轮转。OpenCode 每轮恰好进行一个工具调用,共进行了九次。
因为基线在每个请求上重新发送,请求计数乘以基线。OpenCode 支付了其 ~7k 基线九次,Claude Code 支付了其 ~33k 三次,总数收敛了。
整个任务的输入大约等于基线乘以请求计数,加上对话增长。一个大基线但积极批处理的工具和一个小基线但序列化的工具可以最终在同一个地方。
有效负载中出现了两个结构细节:
Claude Code 在对话进行时注入额外的 <system-reminder> 块,第一轮有三个,第一个工具轮转时有四个,因此其脚手架随轮次增长。
OpenCode 的每轮边际有效负载,约 400 到 2,200 字符每轮,是纯对话内容。
我们在 Claude Fable 5 上重新运行了基线以检查差距是否是 Sonnet 的产物,它缩小了(这是我们没有预期的)。
Claude Code 的系统提示是模型条件的。它向 Sonnet 发送了 27,787 字符的指令,但仅向 Fable 发送了 10,526 字符,工具模式也从 99,778 修剪到 82,283 字符。相同的 27 个工具,更少的教义。
OpenCode 的有效负载在两个模型中是字节相同的。
Fable 上的基线差距约为有效负载的 3.3 倍,而 Sonnet 上为 4.7 倍。仍然远比较消耗,但比率取决于模型。
多步收敛也没有度过这个变化:
在 Fable 上,Claude Code 采用了六个请求而不是三个,包括一个 85,686 token 的中会话缓存重写,最终约为 298,000 个 token,而 OpenCode 为 133,000 个。
因此批处理优势是模型行为,而不是工具常数。
这些通道也在整个研究中为 OpenCode 中的唯一中会话缓存写入产生了,一个约 6,000 token 的单一事件;其他所有它发送的内容都保持字节稳定。
一个服务模型说明属于这里:
在 Fable 下,我们交替地收到 claude-fable-5 和 claude-opus-4-8 的响应,与这些层级共享基础设施一致。
Fable 通道是较小样本,基线和缓存任务两次运行,多步任务一次,所以将它们视为方向确认而不是第二项完整研究。
上面的基线解释了一个从精简开始并保持短暂的会话。
真实会话往往要长得多且更加蜿蜒,所以我们尝试通过用堆叠响应测量更长的会话来模拟这一点。
我们将一个真实的 72KB AGENTS.md 从一个生产仓库放入工作区,并重新运行 T1。
效果是对称的且很大。两个工具每个请求都增加了超过 20,000 个 token。OpenCode 的计费总额从 13,152 增加到 33,336。Claude Code 的从 39,005 增加到 59,243。
非对称性在机制中,它在实验期间咬了我们。Claude Code 2.1.207 完全忽略了 AGENTS.md,只有当重命名为 CLAUDE.md 时才摄取文件,将其注入首条用户消息。OpenCode 读取任一文件名并将其注入系统提示。
两个实际结果随之而来。检查你的工具实际遵守哪个文件名,因为被忽略的指令文件是无声的。并且知道重型指令文件几乎将精简工具的基线四倍;它骑在那个仓库中每个会话的每个请求上。
我们在一服务器和五服务器配置中附加了公开的、无凭证的 MCP 服务器。
模式在工具中是相同的,所以税收也几乎相同;每个小服务器约 1,000 到 1,400 个 token,每个请求。五个服务器为 Claude Code 增加了 4,900 个 token 有效负载,为 OpenCode 增加了 6,967 个计费,将工具计数从 27 增加到 69,从 10 增加到 52。
小公开服务器是温和的情况。生产服务器带有丰富的 API,其模式大小数倍,这正是下面的"所有东西"测量显示的。
一个操作脚注。Claude Code 在打印模式下以无声方式忽略项目范围的 .mcp.json,直到传递显式 --mcp-config 标志。如果你假设一个服务器已附加,在边界处验证它。
故事驱动的工作流框架(如 BMAD)将一个斜杠命令扩展为一个大提示模板,包含人设、协议和清单。
我们为两个工具中的同一个 T3 故事运行了一个 8,405 字符的代表性模板作为提示。模板本身仅约 2,100 个 token,但它进入对话历史并被会话中的每个后续请求重新携带。一个 9 请求会话重新发送它九次。
框架税是模板大小乘以请求计数,它堆叠在上面的所有东西上。
我们要求每个工具将工作分散到两个平行子 agent。这是总数攀升最快的地方。
Claude Code 用 9 个模型请求完成了任务,跨三个不同的请求类。有主会话及其完整的 ~33k 基线,和五个子 agent 调用,每个都携带自己的 3,554 字符 agent 系统提示的引导加 27 个工具中的 24 个。
累计计费输入达到 513,000 个 token,而直接完成相同工作为 121,000 个。这是一个 4.2 倍的乘数用于一个适度的分散。父 agent 仅摄取每个子 agent 的返回结果;成本是每个子 agent 是一个新 agent,在其每一轮都重新读取自己的引导,所以两个子 agent 运行多轮各自会为会话增加多个完整基线请求。
OpenCode 的这里设计值得注意的地方是更精简。其子 agent 请求携带一个 1,379 字符系统提示和 5 个工具的缩减轮廓。其子 agent 通道没有通过我们的网关干净地完成,所以我们从捕获的有效负载报告设计差异,并将其总数保留未量化。
如果你的重型会话让你惊讶,这是首先要看的地方。委派是强大的有时正确的;它也是我们测量的单一最大 token 乘数。我们之后在《子 Agent 税》中详细测量了分散机制,跨三个模型家族。
思考输出以输出速率计费,输入速率的五倍,推理块在对话中向前携带。
我们尝试在两个工具中切换扩展思考,并拒绝发布数字。我们的网关应用自己的思考政策,两个工具的切换都没有明显地在路径中生存,我们引用的任何东西都会是噪音。
机制虽然是不容置疑的。在推理繁重的工作上它与上面的每个乘数复合,因为思考块加入得到重新发送的历史。
最后,桥接测量。我们在真实工作配置下再次运行 T1。
对于 OpenCode,这意味着十一个 MCP 服务器涵盖电子邮件和日历、任务管理、参考管理、产品分析等,加上 72KB 指令文件。首个请求计费 90,817 个 token 在冷缓存写入上,携带 179 个工具和 277KB 的模式,在用户输入一个字之前。
对于 Claude Code,四个 MCP 服务器加上已安装的插件和同一指令文件产生了约 75,000 个 token 的 311KB 有效负载,含 118 个工具。
在减去网关信封后,这约为针对 OpenCode 的 ~7,000 token 基线的 12 倍配置乘数。工具设置基线;你的配置设置账单。
两个工具都正确地设置了缓存断点。有效负载写入一次,具有 5 分钟 TTL 的 1.25 倍溢价,然后在之后以十分之一的价格重新读取。
三个成本度过折扣。
首先,写入本身,每当暂停超过 TTL 时重新支付。一个五分钟的思考,一个会议,一个午餐;每个都重新启动完整堆栈以写入速率。
第二,读取乘以请求计数,子 agent 分散和序列工具循环快速膨胀。
第三,上下文窗口消耗,完全免疫缓存。一个 85k token 的引导占 200k 窗口的超过 40%,在每个请求上,在压缩启动并花费更多 token 总结之前缩小了实际代码的空间。
缓存仅在前缀保持稳定时支付,所以我们哈希了数据集中每个请求的工具数组和系统块。
OpenCode 在每个请求和每次运行中发出字节相同的前缀。三个单独的 T1 会话生成了相同的工具字节、相同的系统字节和相同的消息字节;重复运行写入零缓存 token,读取所有内容。其九请求 T3 会话在整个过程中保持一个稳定的前缀。
Claude Code 每个会话发出三个不同的请求类;一个预热探针、主对话和子 agent 调用,每个都有自己的前缀,因此自己的缓存条目。其系统字节也在同一工作区的会话之间变化,其首条消息脚手架在运行之间变化。
后果显示在缓存写入列中:
在同一文件总结任务上,Claude Code 在五个请求中写入了 53,839 个缓存 token,包括一个完整的中任务重写其完整的 ~43k 前缀。OpenCode 写入了 1,003 个。
我们重新运行了匹配的任务以检查这是否是一次性的(它不是)。
大型中会话重写重新生成,第一次运行 43,342 个 token,第二次 36,899 个,而第三次运行针对新预热的缓存写入了几乎没有。OpenCode 在我们能干净地计费的每个 Sonnet 会话中显示零中会话重写。
然后我们在 Claude Fable 5 上重复了匹配的任务:
行为几乎完全复制;另一个完整中会话重写,这次 50,053 个 token,零缓存读取,和针对 Sonnet 的 54 倍的 52 倍缓存写入差距。Fable 上的多步任务产生了一个甚至更大的,85,686 个 token。两个模型家族,同样的模式。OpenCode 在所有 Fable 运行中保持字节稳定,除了约 6,000 个 token 的一次写入,对比 Claude Code 的 37,000 到 86,000 的重复重写。
根据缓存温度,Claude Code 在同一任务上的缓存写入量范围从 OpenCode 的 5.9 倍到 54 倍,缓存写入按溢价计费,5 分钟层级的 1.25 倍基础速率,1 小时层级的 2 倍。
这里应该欠一个归因警告。原则上单个中任务缓存未命中可能是我们的网关驱逐而不是工具移动其缓存断点;跨运行重现使系统工具行为成为更可能的解释,前缀不稳定本身是工具侧,在任何网关参与之前在捕获的字节中可见。
如果你看过使用量计在 Claude Code 下戏剧性攀升,但在使用相同模型的 OpenCode 下保持平坦,这是最可能的机制;更大的前缀,每个会话更多不同的前缀,更多它们的重写,乘以任何子 agent 分散。
一个对上面所有东西的公平反对是"一个账单对工作说不了什么",即支付更多是理性的如果输出更好。
这里的任务被选择使得质量不能是解释。两个工具都完成了每个评分的任务正确。多步任务由一个断言脚本每个工具都必须写然后通过验证,两个都干净地退出。文件总结都是准确的。在这些任务上 token 差距是相同结果的成本差异,这正是使其可测量的。
然后我们直接测量了它的第一片。一个单独的十通道基准给了每个工具相同的工作,在一个预先编写且 hash 验证的十断言测试套件上实现两个日期工具(它无法修改),在五个每个工具的新鲜工作区中;这次套件是预先编写的,hash 验证的,所以两个工具都没有给自己的工作评分。两个通过了五个中五个。针对那个相同的、独立验证的结果,每次通过运行的平均计费成本约为 Claude Code 的 268,000 输入 token 和 OpenCode 的 72,000,约 3.7 倍,两个工具得到相同的模型快照。OpenCode 也在一两分钟内完成了每个通道,而 Claude Code 为四到八分钟。
高级是否在真正困难的工程工作上购买质量是不同的问题,和一个二函数工具是一个首片,不是答案。Claude Code 的背景 agent、技能和编排表面可能在更困难的任务上赚取它们的 token;测试那个声明需要更困难的任务和更多运行,这里的钻机可以驱动两者。
两个发现虽然独立于质量。在会话中间重写一个字节相同的缓存前缀在所有代码质量中都不买;它是相同的内容,以溢价速率支付再次。一个工具无声地忽略的指令文件也不买什么。无论对更大平台的功能论证什么,那两个都是任何定义上的废物。
这个实验的诚实版本是"信任捕获的有效负载",所以我们的方式对待数据集我们告诉客户对待生产推断日志。
所有 273 个捕获的请求/响应记录中的每一个都写入了一个篡改显然、SHA-256 哈希链的审计日志,使用我们的开源库 @systima/aiact-audit-log,链端到端验证。
Chain verified: 273 entries
No breaks detected
Hash chain integrity: VALID
这是库为欧盟人工智能法第 12 条日志提供的同样机制;结构化记录,你可以交给第三方的完整性,和重建恰好发送和返回的什么。
自狗粮也双向切割。一个重建报告了比链包含更多的摄取记录,一个缓冲写故障我们抓住了因为链计数拒绝协调;我们从原始捕获重建并在引用上面的数字之前重新验证。
一个 token 基准是它的低风险使用。一个信用决策 agent 不是。
一台机器,一对版本,两个模型家族用于基线和缓存通道(Sonnet 4.5 和 Fable 5),一个用于乘数通道,小 n(Sonnet 上三 T1 和三 T2 运行,Fable 上两个和两个,五个质量通道每个工具,一个运行每个乘数通道)。工具提示经常改变,所以将数字视为 2026 年 7 月快照,方法视为持久人工制品。
一个本地网关坐在测量路径中。组件级数字来自捕获的有效负载,它无法影响。计费数字是冷缓存锚点针对其测得常数校准;预热运行计费数字是不可归因的,所以我们仅引用冷锚点。网关也以无声方式替代了比我们固定更新的模型快照,这是它自己的课程。如果你不在 API 边界处记录,你不知道你实际运行的是什么模型。在 Fable 路径上网关也在一个通道中恢复了陈旧的服务器侧会话,在另一个中主机侧执行工具;我们排除了两个,用唯一文件名重新运行多步通道以打破网关的对话指纹,这干净地完成了。在 Fable pin 下它也交替地回答作为 claude-fable-5 和 claude-opus-4-8。
T3 收敛是一个观察一个任务形态。一个严格序列任务会推 Claude Code 的请求计数,因此其总数,回上。OpenCode 零工具和子 agent 通道通过网关返回了形式不良的流,所以对于那些条件我们仅报告捕获的有效负载大小。
真实配置数字描述了一个从业者的设置,仅报告大小和计数。你的会不同;方法转移。
测量钻机大约 200 行 Node。它是一个 HTTP 代理,转发到你的模型端点,将每个请求正文和响应使用块写到磁盘,并将每对附加到审计链。
钻机、预先设置质量基准和完整聚合结果在 github.com/systima-ai/agentic-coding-tools-comparison 开源。
原始捕获...