[控场AI]
· 12 分钟阅读· 6,449 字

空提示词的真实成本:四款编程Agent CLI基线Token实测

空提示词的真实成本:四款编程Agent CLI基线Token实测

编程 Agent CLI 的空提示词其实携带大量前缀,跨工具计费规则不一,必须在自己机器上实测基线成本。

文章指出,编程 Agent CLI 在用户提示前会发送包含系统提示词、内置工具、MCP 工具定义与指令文件的前缀,空会话也会重复付费,CI 与 headless 运行同样计入。作者对比 Claude Code、Codex、Copilot CLI、OpenCode 四款工具,发现缓存计费规则不同:Anthropic 的 input_tokens 不含缓存,需要与 cache_creation、cache_read 相加;OpenAI 则已含缓存,直接对齐原始数字会产生误导。指令文件存在交叉加载,Copilot CLI 合并多个生态文件,OpenCode 在缺省时会读取 ~/.claude/CLAUDE.md。MCP 加载策略也不统一,Claude Code 默认延迟,OpenCode 文档警告会显著增加上下文。作者给出空仓库实测方法,并建议用前缀 Token 乘以会话频率与费率来量化成本。

空提示词的真实成本:四款编程Agent CLI基线Token实测

你给编程 Agent 发一句“ping”,它真正读进去的远不止这个字。OpenAI 官方文档中 codex exec --json 的示例行显示:24,763 个输入 Token,其中 24,448 个被缓存,而输出仅 122 个 Token。文档没有说明是什么提示词产生了这组数字,但无论原提示是什么,模型每写一个 Token,背后读了两百个 Token。

这不是个例。Claude Code、Codex、GitHub Copilot CLI、OpenCode——每一款编程 Agent CLI 都会在你的任务开始之前先发送一段前缀:系统提示词、内置工具定义、已配置的 MCP 服务器工具、以及沿途找到的每一份指令文件。新会话会重发这段前缀,CI 中每一次 headless 运行也不例外。

原文作者明确指出:不要照抄任何人的数字,包括上文中引用的样本。前缀会随 CLI 版本、模型、全局配置和启动目录变化。唯一可靠的方式是在自己的机器上实测。

空提示词只是首次请求中很小的一部分

提示词出发前,谁已经搭上了车

前缀由两部分构成:属于厂商的系统提示词与内置工具;属于你自己的 MCP 服务器与指令文件。

厂商部分随 CLI 版本更新而变动,你无法控制,但可以观测。自己的部分才是成本大头,也是最容易被忽视的地方。

MCP 服务器的加载策略差异巨大

各家 CLI 对 MCP 工具定义的加载策略完全不同,这是基线差异的主要来源:

  • Claude Code 默认延迟加载 MCP 工具定义,会话启动时“只加载工具名和服务器指令”(据 Claude Code MCP 文档)。
  • OpenCode 文档则明确警告相反的情况:MCP 服务器“会增加上下文”,某些服务器(如 GitHub MCP)“往往添加大量 Token”(据 OpenCode MCP 文档)。
  • Copilot CLI 内置了 GitHub MCP 服务器(据 GitHub 文档)。
  • Codex 的 MCP 文档没有说明是否延迟加载,这本身就构成实测理由。

同一份 MCP 配置,在不同 CLI 下的成本可能相差一个数量级。

MCP 与工具定义膨胀:Model Context Protocol(MCP)由 Anthropic 于 2024 年开源,用于让模型通过统一协议访问外部工具与数据源。其代价是每个 MCP 服务器都会向模型描述自己的工具清单(名称、描述、JSON Schema 参数),这些描述在每次请求中作为系统提示词的一部分发送。一个功能齐全的服务器可能注册十几个工具,每个工具的定义动辄数百 Token,叠加后极易突破数千 Token。"延迟加载"(Deferred Loading / Tool Search)是为缓解此问题而生的优化:启动时只加载服务器名称与元数据,当模型实际需要某个工具时再动态注入其完整定义。不同厂商对这一优化的默认策略截然不同——这正是同一份 MCP 配置在不同 CLI 下成本相差一个数量级的技术原因,也是必须实测而非依赖文档的根本所在。

指令文件的交叉加载陷阱

指令文件是“空提示词”不再空的关键。原文整理了一份容易被忽略的对照表:

CLI启动时加载的指令文件
Claude CodeCLAUDE.md,无项目级 CLAUDE.md 时回退到 AGENTS.md(v2.1.277+),另加载 auto memory
Codex~/.codex/AGENTS.md,然后从 git 根目录向下到当前文件夹的 AGENTS.md,上限 32 KiB
Copilot CLIAGENTS.md、.github/copilot-instructions.md、~/.copilot/copilot-instructions.md、CLAUDE.md 和 GEMINI.md,全部合并加载
OpenCodeAGENTS.md(回退 CLAUDE.md),加 ~/.config/opencode/AGENTS.md,缺失时改用 ~/.claude/CLAUDE.md

最后两行值得反复阅读:没有全局 OpenCode 文件时,你的 ~/.claude/CLAUDE.md 会跟着进入 OpenCode;某个仓库的 CLAUDE.md 同样会落入 Copilot CLI 的前缀。你为 Claude 写的一次性规则,可能在四个 CLI 里各付一遍钱。

AGENTS.md 与厂商专属文件的演进:AGENTS.md 是 2024 年由社区推动形成的跨工具指令文件约定,目标是给所有编程 Agent 提供一个统一的"项目说明"入口,避免为每个 CLI 各写一份。Claude 早期使用 CLAUDE.md,后来逐步兼容 AGENTS.md(如 v2.1.277+ 的回退逻辑);OpenCode 则相反,主用 AGENTS.md 并回退到 CLAUDE.md。这种"双向兼容"正是交叉污染的根源:为了兼容旧用户,工具会读取其他生态的约定文件,导致本意服务于单一工具的规则被多方加载。类似的还有 GEMINI.md(Google 生态)和 .github/copilot-instructions.md(GitHub 生态)。实践上,把工具专属规则放进 skills 或按需拉取的模块,而非全部塞进这些"人人都会读"的文件,是控制前缀膨胀的最有效手段。

实测方法:在空仓库里跑“ping”

原文给出的方案很直接:先创建空 git 仓库,避免项目文件混入,但全局文件依然加载——这正是你当下真正付出的基线。

mkdir -p ~/tmp/baseline && cd ~/tmp/baseline
git init -q

注意 Claude Code 和 OpenCode 还会搜索父级目录,需要确认 ~ 和 ~/tmp 下没有 CLAUDE.md 或 AGENTS.md。Codex 则在 git 根目录停止搜索。

各 CLI 的读取命令

Claude Code 用 --output-format json 返回 usage、total_cost_usd 和按模型的 modelUsage 细分:

claude -p "ping" --output-format json > claude-1.json
jq '.usage, .total_cost_usd' claude-1.json
jq '[.usage.input_tokens,
     .usage.cache_creation_input_tokens,
     .usage.cache_read_input_tokens] | add' claude-1.json

第二条命令是关键。在 Anthropic 的 usage 对象里,input_tokens 只统计最后一个缓存断点之后的部分,完整输入是三个字段之和。只看 input_tokens,基线会显得极小。另需检查 .num_turns:如果 Agent 为回答“ping”调用了一次工具,usage 会覆盖多次模型请求,前缀会被重复计算。

Codex 使用 codex exec --json 流式输出 JSONL,turn.completed 事件携带 token 数据:

codex exec --json "ping" > codex-1.jsonl
jq -c 'select(.type=="turn.completed") | .usage' codex-1.jsonl

这里缓存计数已包含在输入计数内,所以 input_tokens 就是前缀加一个字提示词——前提是该轮只有一次模型调用。

Copilot CLI 的程序化参考文档没有记录 usage 字段,其 -s 标志会抑制统计信息。启动 copilot 后输入 /context,可以分别看到 System Prompt、Custom Instructions、System Tools、MCP Tools 和 Messages 的逐层拆分。

OpenCode 用 opencode run --format json 输出原始 JSON 事件,记录每个步骤的 input、output、reasoning 和 cache.read/cache.write。据 OpenCode 追踪器上的一份会话记录,某步骤显示 input 209、cache read 18,944,必须把缓存字段加到 input 上。若该命令无输出,可改用 opencode stats --days 1 从已存储会话读取。

Token 缓存的计费机制:主流 LLM 提供商(Anthropic、OpenAI)都支持提示词缓存(Prompt Caching),其核心逻辑是将不变的前缀部分缓存起来,后续请求命中缓存时按折扣价计费。Anthropic 的缓存分为两档:cache_creation_input_tokens 是首次写入缓存的 Token,按标准输入费率的 1.25 倍计费;cache_read_input_tokens 是命中缓存的 Token,费率仅为标准输入价的约 0.1 倍。缓存有效期通常为 5 分钟(可扩展至 1 小时),因此"跑两次"策略之所以有效,正是因为第二次运行在缓存窗口内,能显著拉低平均成本。OpenAI 的自动缓存则是隐式触发的,不单独列出写入费用,input_tokens 中已隐含缓存折扣。理解这套机制是正确归因基线成本的前提:同理跨厂商比较时,必须先把缓存字段归位到统一的"完整输入"口径,否则会得出错误结论。

关键提示:跑两次

几分钟内运行每条命令两次。第一次运行倾向于把前缀写入缓存,第二次读回。在 Claude 模型上,缓存读取的计费可以低至输入费率的 0.1 倍,因此冷启动首会话比热重复贵得多。

各 CLI 需要记录的数值汇总:

CLI该轮完整输入读取位置
Claude Codeinput_tokens + cache_creation_input_tokens + cache_read_input_tokens--output-format json 结果中的 .usage
Codexinput_tokens(缓存已包含在内)turn.completed 事件
Copilot CLI各层加总交互式会话中的 /context
OpenCodeinput + cache.read + cache.writestep_finish 事件或 opencode stats

第二轮:加一个 MCP 服务器和一份 AGENTS.md

有了基线,再加两样大多数仓库都会生长的东西。

MCP 服务器可以使用官方的 “everything” 参考服务器,或你实际在用的服务器。记忆文件则写一份简短的 AGENTS.md:

cat > AGENTS.md <<'EOF'
# Project rules
- Run `npm test` before you say a task is done.
- Never edit files under migrations/ without asking.
EOF

随后各 CLI 分别注册该 MCP 服务器并重跑。Claude Code 值得做一次对照实验:分别以默认配置和 ENABLE_TOOL_SEARCH=false 运行,两者之间的差距就是这一个服务器的工具定义在每个新会话中的价格。Claude Code 通过默认延迟加载避开了这笔开销,而 OpenCode 等工具则需按文档警告直接承担。

把差值换算成钱

第一轮与第二轮的差值,就是一个 MCP 服务器加一份记忆文件对每次会话启动的额外成本。换算方式:前缀 Token × 每日新会话数 × 模型的输入或缓存写入费率,再加上每次后续轮次重发前缀时的缓存读取。Headless 运行算在内,并行 Agent 也算在内。

账单形态取决于你的方案。Claude Pro 或 Max 订阅下,/usage 中的美元数字“与计费无关”,但 Token 仍会消耗你的套餐限额。Copilot 方面,方案已转向 GitHub AI Credits,“根据 Token 消耗计算,包括输入、输出和缓存 Token”。API Key 模式下,每一个 Token 都在计费。

如果差值出乎意料,修复手段相当朴素:把工作流专用指令从 CLAUDE.md 移到按需加载的 skills 中,并把 CLAUDE.md 控制在 200 行以内;关闭不使用的 MCP 服务器;检查全局文件,因为它们会在每个仓库中随行。

多源交叉验证的结论

综合四家官方文档与作者实测方案,可以确定几条跨来源一致的事实:

  1. 前缀是真实的、可测量的成本——四款 CLI 都提供了某种形式的 Token 用量读取手段,说明厂商自身也将其视为需要观测的对象。
  2. 缓存计费规则因厂商而异——Anthropic 的 input_tokens 不含缓存部分,OpenAI 的 input_tokens 包含缓存部分,直接对比原始数字会产生误导。
  3. 全局文件的交叉污染是真实风险——Claude Code、Copilot CLI、OpenCode 都会读取彼此的指令文件,这一点在各自官方文档中都可交叉验证。

存在分歧的一点是 MCP 工具的加载策略:Claude Code 默认延迟,OpenCode 文档警告直接增加,Codex 未说明。这意味着跨 CLI 的基线比较必须依赖实测,而非文档推断。

原文作者同时是 Hermes IDE 的开发者,并在文中给出了利益披露。他提到 Hermes 2.3.4 提供了上下文计量表,可以在会话首条消息发送“ping”时直接显示基线,并在侧边栏展示每个会话的上下文占用、Token 总量和预估成本。这部分属于单一来源的产品自述,读者应结合该披露自行判断。

核心方法论值得独立于任何工具:不要相信任何人的基线数字,在空仓库里用一字提示词,在自己机器上跑两遍,把三种缓存字段加对,然后乘以你真正的会话频率。

#编程Agent CLI#Token成本#Claude Code#Codex#GitHub Copilot CLI#OpenCode#MCP服务器#上下文基线#缓存计费
分享:

相关推荐