一、先说结论:模型相同,账单也可能差 70 倍
很多开发者选择 AI 编程工具时,首先比较的通常是模型价格:
- 每百万输入 Token 多少钱
- 每百万输出 Token 多少钱
- 上下文窗口有多大
- 模型的代码能力有多强
但最近一组 Coding Agent 测试揭示了一个容易被忽略的问题:即使使用完全相同的模型和 API,不同 Agent Harness 完成任务时的 Token 消耗,也可能相差约 70 倍。
测试涉及 Aider、Claude Code、Codex、OpenClaw、OpenCode、Hermes 等常见工具。其中一个测试中,每完成一个任务:
- Aider Architect 模式约消耗 3500 Token
- OpenClaw 约消耗 29.2 万 Token
- 其他 Agent 分布在两者之间
底层模型没有变,任务也基本相同。真正拉开账单差距的,是模型外面的那套 Agent 运行系统。
二、什么是 Agent Harness?
调用大模型最简单的方式,是发送一段 Prompt,然后等待回答:
User question
↓
LLM
↓
Model answer
Coding Agent 则复杂得多:
User requirement
↓
Read project rules
↓
Scan code files
↓
Select tools
↓
Call LLM
↓
Run shell or edit files
↓
Read execution result
↓
Call LLM again
↓
Run tests
↓
Continue fixing
负责管理这个循环的程序,就是 Agent Harness。
Claude Code、Codex、Aider 和 OpenClaw 虽然都能调用大模型完成编程任务,但它们在以下方面的设计完全不同:
- 系统提示词
- 工具数量
- 项目文件选择
- 上下文管理
- 记忆与摘要
- Prompt Cache
- 失败重试
- 测试验证
- 子 Agent 调用
- 会话压缩
因此,“使用同一个模型”并不意味着发送给模型的内容相同。
三、第一笔隐形开销:Agent 启动税
在用户输入第一个字之前,Coding Agent 通常已经准备了一大段内容。这些内容可能包括:
- Agent 身份和行为规范
- 文件读写规则
- Shell 工具定义
- Git 操作说明
- MCP 工具 Schema
- 项目目录信息
- 安全权限规则
- 输出格式要求
- 错误恢复策略
- 当前环境变量摘要
测试把这部分成本称为“Startup Tax”,也就是 Agent 启动税。
测试结果显示,不同工具的启动上下文差异非常大:
- Aider Architect 模式:约 700 Token
- OpenClaw:约 26000 Token
这里的 26000 Token 还没有包含真正的项目需求,只是 Agent 开始工作前携带的基础信息。
这相当于你只是说了一句“帮我修改登录接口的一个 Bug”,Agent 在把这句话发给模型之前,可能已经附带了几万 Token 的系统说明、工具定义和运行环境信息。
四、启动税为什么会被不断放大?
如果启动上下文只发送一次,问题还没有那么严重。但大模型 API 通常是无状态的。
模型完成一次工具调用后,Agent 下一轮请求仍然需要重新提交必要的上下文,包括:
- 系统提示词
- 工具列表
- 对话历史
- 已读取的代码
- 上一轮工具结果
- 当前任务状态
假设某个 Agent 每轮固定携带 26000 个基础 Token,一个任务需要 15 轮交互:
26000 × 15 = 390000 Token
仅固定脚手架就可能产生 39 万输入 Token。这还没有计算代码文件、命令输出、测试日志和模型回答。
测试发现,“每轮固定上下文大小 × 调用轮数”与最终 Token 消耗高度相关。这说明很多昂贵 Agent 并不是因为项目代码特别大,而是每一轮都背着一个很重的基础上下文。
五、第二笔隐形开销:Prompt Cache 命中率
只看 Token 总数,还不能准确计算费用。因为模型厂商通常会区分:
- 普通输入 Token
- 缓存写入 Token
- 缓存命中 Token
- 输出 Token
重复出现的系统提示词和对话前缀,如果能够命中 Prompt Cache,价格通常会比普通输入低很多。
相关测试披露的输入缓存占比大致为:
- Claude Code:约 1.5%
- Codex:约 70%
- OMP:约 57%
这意味着两个 Agent 即使使用了接近的输入 Token 数量,最终账单也可能完全不同。
可以把实际费用简化为:
Actual cost
= uncached input tokens × normal input price
+ cached input tokens × cache price
+ output tokens × output price
因此,不能看到某个工具“使用了 100 万 Token”,就直接用普通输入价格相乘。必须先确认其中多少 Token 命中了缓存。
六、哪些操作容易让缓存失效?
Prompt Cache 通常依赖稳定的前缀。如果 Agent 频繁修改前面已经发送过的内容,后面的缓存可能全部失效。常见原因包括:
- 每轮在系统提示词里加入动态时间
- 工具定义顺序不断变化
- 每次重新生成项目摘要
- 在对话前部插入新消息
- MCP 工具 Schema 发生变化
- 不同请求使用不同模型
- 会话压缩后整体 Prompt 结构改变
- API 网关没有正确传递缓存相关字段
所以,“删除一些上下文”并不一定能节省费用。如果删除操作破坏了原有缓存前缀,Token 虽然变少了,未缓存输入反而可能增加,最终费用甚至更高。
七、第三笔隐形开销:工具返回内容
Coding Agent 最容易失控的并不是用户 Prompt,而是工具输出。
例如 Agent 运行:
npm test
如果测试输出了两万行日志,而 Harness 把完整结果重新传给模型,这些内容就会进入下一轮上下文。
类似的高消耗操作包括:
- 输出整个 Git diff
- 读取完整日志文件
- 打印整个数据库查询结果
- 返回大体积 JSON
- 扫描全部项目文件
- 一次加载完整 API 文档
- MCP 工具返回未经裁剪的数据
- 反复读取相同文件
一个看起来很简单的报错“测试失败,请继续修复”,背后可能附带了几万 Token 的终端输出。
更麻烦的是,Agent 在下一轮又执行相同命令,产生几乎相同的日志,然后再次发送给模型。
八、第四笔隐形开销:Agent 循环次数
Agent 的典型工作流程是:观察 → 思考 → 操作 → 验证 → 再观察。这个循环可以提高复杂任务的成功率,但也会成为 Token 放大器。
例如,一个 Agent 可能采用以下流程:
- 扫描项目
- 查找相关文件
- 读取文件
- 制定方案
- 修改代码
- 运行测试
- 分析报错
- 读取更多文件
- 再次修改
- 再次运行测试
- 检查 Git diff
- 总结结果
另一个更轻量的 Agent 可能直接:
- 读取用户指定的文件
- 修改代码
- 运行一次测试
- 返回结果
后者更省 Token,但不一定适合陌生、复杂或者描述不清楚的项目。
因此,不能简单得出“最省 Token 的 Agent 就是最好用的 Agent”。真正应该比较的是:完成一个经过验证的任务,需要多少成本。
九、便宜的 Agent 不一定真的便宜
假设有两个 Agent:
- Agent A:每次任务花费 0.03 美元,成功率 40%
- Agent B:每次任务花费 0.08 美元,成功率 80%
如果只看单次调用,Agent A 更便宜。但按成功任务计算:
- Agent A:0.03 ÷ 40% = 0.075 美元
- Agent B:0.08 ÷ 80% = 0.1 美元
两者差距已经没有表面上那么大。
如果 Agent A 失败后需要开发者重新描述、重新执行或者人工修复,它的真实成本还会继续增加。
因此,比较 Coding Agent 至少要同时记录四个指标:
- 每个任务的总 Token
- 实际 API 费用
- 任务成功率
- 每个成功任务的平均费用
只比较模型单价,或者只比较 Token 数量,都可能得出错误结论。
十、如何查看一次调用到底消耗了多少 Token?
如果使用兼容 OpenAI SDK 的模型接口,可以从响应中的 usage 字段记录输入和输出 Token。下面是一段最小测试代码:
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["AI_API_KEY"],
base_url="https://genvis.xyz/v1",
)
response = client.chat.completions.create(
model="gpt-5.6-luna",
messages=[
{
"role": "system",
"content": "You are a code review assistant. Only point out high-risk issues.",
},
{
"role": "user",
"content": "Check the following Python function for resource leaks.",
},
],
)
usage = response.usage
print("Input tokens:", usage.prompt_tokens)
print("Output tokens:", usage.completion_tokens)
print("Total tokens:", usage.total_tokens)
details = getattr(usage, "prompt_tokens_details", None)
if details:
cached_tokens = getattr(details, "cached_tokens", 0)
print("Cached tokens:", cached_tokens)
这段代码只能看到一次模型请求的消耗。如果要评估 Claude Code、Codex 或 OpenClaw 等完整 Agent,还需要累计整个任务中的所有请求,并记录:
- 任务 ID
- 模型
- Agent 工具
- 请求次数
- 输入 Token
- 缓存 Token
- 输出 Token
- 总费用
- 运行时间
- 是否完成
- 测试是否通过
十一、一套更可靠的对比方法
如果想比较不同 Coding Agent,最好使用同一组固定任务。例如准备以下五类任务:
- 修复一个明确的单文件 Bug
- 增加一个需要修改多个文件的功能
- 定位一个只有报错日志的问题
- 给陌生项目补充单元测试
- 重构一段代码并保证测试通过
然后固定以下条件:
- 使用相同模型
- 使用相同 API 入口
- 使用相同代码仓库
- 从相同 Git Commit 开始
- 设置相同最大运行时间
- 设置相同最大调用次数
- 每类任务至少重复运行三次
- 用测试程序判断成功,而不是让另一个模型打分
最终记录:
cost per successful task = total run cost ÷ number of successful tasks
这样得到的结果才比“我感觉 Claude Code 更省”或者“Codex 好像用得更快”可靠。
十二、降低 Coding Agent 成本的 8 个方法
1. 给 Agent 明确的文件范围
不要只说“帮我检查一下整个项目”,可以改成“只检查 controller/login.go 和 service/auth.go,不要扫描 node_modules、dist、日志和生成文件”。文件范围越明确,Agent 前期探索消耗越低。
2. 把大任务拆成可验证的小任务
不要一次要求 Agent 完成“重构认证系统、升级数据库、补齐测试并优化性能”,可以拆成“第一步只分析认证系统,输出需要修改的文件和原因,不修改代码。确认后再执行下一步”。这不仅降低 Token 消耗,也能减少 Agent 走错方向后产生的大量返工。
3. 限制工具输出长度
终端和 MCP 工具应当支持:
- 最大返回行数
- 最大字符数
- 只返回错误摘要
- 保留开头和结尾
- 完整结果保存到文件
- 模型需要时再按范围读取
例如测试日志可以先筛选:
npm test 2>&1 | tail -n 120
而不是把数万行输出全部塞进上下文。
4. 保持系统提示词稳定
不要在系统提示词前部加入每轮都会变化的信息。动态信息可以放在消息末尾,或者通过独立工具提供,以提高 Prompt Cache 命中率。
5. 减少不必要的 MCP 工具
每增加一个工具,通常就需要向模型发送工具名称、参数和说明。如果一个会话挂载了几十个 MCP 服务器,模型每轮可能都要携带大量工具 Schema。只启用当前任务真正需要的工具。
6. 简单任务使用轻量模型
并不是每一步都需要最强模型。可以按照任务分级:
- 文件检索、摘要、格式转换 → 轻量模型
- 常规代码修改 → 中档模型
- 架构设计、复杂调试 → 强推理模型
- 最终审查 → 强模型
这通常比整个任务始终使用最高规格模型更划算。
7. 给 Agent 设置硬预算
至少应该限制:
- 最大执行时间
- 最大调用次数
- 最大输入 Token
- 最大输出 Token
- 最大任务费用
- 连续失败次数
例如 Agent 连续三次运行相同测试仍然失败时,应当暂停并请求人工判断,而不是无限循环。
8. 用测试结果结束任务
没有明确结束条件的 Agent,很容易继续检查、继续优化、继续消耗 Token。可以提前定义“当以下三个测试全部通过后立即停止”:
- go test ./service/...
- 登录接口返回预期状态码
- git diff 中没有无关文件
明确的停止条件,往往比要求 Agent“尽量完善”更节省费用。
十三、为什么统一 API 入口越来越重要?
当团队同时使用 Claude Code、Codex、OpenClaw 和自研 Agent 时,成本问题已经不只是选择哪个模型。还需要统一处理:
- API Key 管理
- 模型切换
- 调用日志
- Token 统计
- 失败重试
- 额度限制
- 不同任务的模型路由
- 单个 Agent 的费用核算
如果每个工具分别连接不同模型供应商,账单和日志会散落在多个平台,很难回答这些问题:到底哪个 Agent 消耗最多?哪个任务一直在重试?缓存是否真正生效?某个模型涨价后应该切到哪里?一次成功任务的真实成本是多少?
所以,AI 开发成本优化正在从“比较模型价格”,转向“管理完整 Agent 调用链”。
十四、如何看待“70 倍”这个数字?
这个数字很有冲击力,但不能被理解成固定结论。相关测试存在几个限制:
- 部分组合只运行一次
- Agent 执行具有随机性
- 不同 Harness 可能针对不同模型优化
- 任务规模相对有限
- Token 更少不代表成功率更高
- 缓存价格与模型供应商有关
- 不同版本的 Agent 可能迅速改变结果
因此,这次测试不能证明 Aider 永远最省,也不能证明 OpenClaw 永远最贵。它真正揭示的是:在 Agent 系统中,模型只是成本的一部分。系统提示词、工具 Schema、调用轮数、上下文策略和缓存命中率,可能比模型单价更影响最终账单。
十五、最后的结论
以前选择 AI 编程工具,我们经常问“哪个模型更聪明”。现在还需要继续问:
- 这个 Agent 每轮给模型发送了什么?
- 它需要调用多少次才能完成任务?
- 多少输入命中了缓存?
- 工具输出有没有被裁剪?
- 失败后会不会无限重试?
- 一个成功任务到底花了多少钱?
模型决定了 Agent 能力的上限。Harness 决定模型如何观察、思考、行动和验证,也决定这份能力最终需要付出多少成本。
下一次看到 Coding Agent 账单突然增长时,不要急着更换模型。先检查它每轮背着多少上下文,又重复发送了多少次。真正昂贵的,可能不是模型本身,而是模型外面那套看不见的“Agent 脚手架”。