
上周我把一个大模块的重构拆成四个独立任务开了四个 Agent 并行跑本想着能省一晚上的时间。结果第二天看到账单API 消耗直接翻了 4 倍数字大到让人肉疼。问题不在我用的模型本身变贵了而是这 4 个 Agent 全在用又大又全的配置做那些本来只需要小模型就能完成的活。准确说是 Claude Code 在并行调度子任务时把主会话的模型设置一路传递了下去。最后真正把账单压回来的不是少开 Agent也不是把主模型换便宜而是只动了一个配置给只读、检索、总结这类子 Agent 单独指定小模型。就这么一个字段省下来的钱比我想象中还夸张。这篇把整个排查链路、费用结构和这个配置的用法一起捋一遍给同样在玩 Agent 并行开发的人做个参考。1. 事情是怎么失控的1.1 我当时的并行方式我当时的场景挺典型手上有四个改动方向分别是接口重构、日志链路调整、测试用例修补、文档同步更新。这几个方向虽然都落在同一个仓库里但涉及的文件基本不重叠逻辑上也相对独立按道理很适合并行处理。于是我在终端里开了四个 Claude Code 会话用了类似 tmux 多窗口那种方式四个会话同时跑。另外主会话里我还挂了几个子任务用来做代码搜索、文件阅读和变更摘要。从编排角度看这已经是一个典型的 Agent 框架用法了一个主 Agent 负责任务拆解和决策多个子 Agent 分别执行窄任务。概念上没问题账单一出来问题就大了。我翻了下费用明细四个会话并行跑了大约一个多小时输入 token 消耗几乎是原来单用户会话的六倍总费用则到了原来的四倍多。第一反应是模型是不是被切成更贵的档位了结果查了一圈模型没变变的是每一笔请求都在重复付“读资料”的钱。1.2 账单结构长什么样我去控制台把按模型拆分的用量拉出来看到了一个很典型的现象output token 其实没有暴涨很多真正暴涨的是 input token。如果把一次完整请求拆开看里面大头不是模型生成回复的那段而是每次都要带上的 system prompt、工具定义、代码索引、历史消息这一大坨都按 input 计费。以我当时的基线做参照大概是这样一组数据场景输入 token 消耗输出 token 消耗缓存命中率账单变化单会话、单轮小任务基线 1x基线 1x较高基线单会话长任务2-3x1.5x中等1.5-2x4 个会话全并行6-8x2x很低4x4 个并行 子 Agent 继承主模型10x3x极低6-8x我属于最后一行那种情况既开了多会话又在会话里继续派生子 Agent。两个因素叠在一起账单自然就压不住了。1.3 什么任务适合并行什么不适合这里要先说一句公道话并行 Agent 不是原罪。它最适合的场景是任务之间文件不重叠、状态不共享比如我刚才说的接口重构和文档更新各改各的文件互不影响。真正不适合的是多个 Agent 同时写同一个文件或者多个 Agent 共享同一份可变状态。我见过有人让两个 Agent 同时改一个配置文件A 改完 B 又覆盖回来两边反复“救火”来回折腾了七八轮才结束。每一轮都是一次完整的 API 请求成本直接线性叠加。这种不是提效是花钱买冲突。所以并行之前先判断依赖关系。依赖关系清楚的并行是效率放大器依赖关系乱成一团的并行只会让 Agent 框架替你承担“沟通成本”最终的代价还是会落在账单上。2. 账单为什么翻 4 倍三个问题叠加2.1 基础上下文被多份重复计费这是最核心的机制问题。每次调用 API模型并不知道上一个请求发生了什么它看到的只有当前请求里携带的上下文。Claude Code 为了让对话连续会把之前的消息、工具结果、文件内容一并塞进下一次请求。这个设计在单会话时没问题一旦并行问题就来了。四个会话各自维护独立的上下文等于同一份代码库摘要、同一份 system prompt、同一批工具定义被复制了四份。每一份都按 input token 计费。这不是四倍的小开销而是好几倍的重复开销。我当时请了四个“专家”来改代码每请一位专家都要把整摞资料从头念一遍。四个专家同时进场就是四份资料的重复阅读费。更关键的是这些资料里大量内容是重复的系统提示词一样、项目说明一样、最近一次 git 变更一样但它们分散在四个不同的上下文里谁也共享不了谁。这里就牵出 Anthropic 的 prompt caching 机制。它本意是好的请求里命中缓存的部分按很低的折扣计费。但缓存命中有前提它依赖请求前缀的一致性。四个并行会话如果从不同的工作目录启动废话不多说继续把错误分摊到四份独立账单里缓存几乎全部落空。缓存命中率一旦跌到谷底成本就不是线性涨而是几何级涨。2.2 模型继承导致“高射炮打蚊子”第二个问题出在模型选择上。Claude Code 的自定义 Agent 允许你给每个 Agent 单独指定模型但如果你不写这个字段很多情况下它会沿用主会话的模型设置。我最初图省事直接在 settings 里把主模型设成了很强的档位想着这样能保证质量。结果所有子 Agent 也全部走了这个模型计费。检索一段代码、总结一个文件、跑一遍测试结果这些都算在贵模型头上。打个比方让全科主任医师去给每个病人量体温体温是量得准可这个人力成本完全不合理。更隐蔽的是子 Agent 有时候还会被用于一些后台辅助任务比如自动生成任务标题、整理变更摘要。这些任务的输入输出都不长但请求次数频繁。如果它们也继承贵模型那每一笔小额支出都会变成一个小额放大镜次数一多总额就非常可观。真正合理的用法是分级需要推理、规划、改代码的任务用强模型只做检索、过滤、摘要、格式整理的任务用便宜模型。就像团队里既有架构师也有实习生架构师定方案实习生收集资料这样才能把人力成本压到最低。2.3 失败重试与工具膨胀的隐形消耗这一块是最容易被忽视的。并行 Agent 跑起来之后非常容易触发 API 的速率限制报错信息会直接出现在终端里类似 agent execution terminated due to error。Claude Code 遇到这类错误通常会做自动重试。一次重试不是重新算一遍这么简单而是把整个请求重新发送一遍等于同样的成本再付一次。我排查日志的时候发现最严重的那个会话在十分钟内重试了六次其中有三次是限流导致的有两次是上下文超长被截断后重推。这些重试请求基本没有产出有效结果却全部按正常 token 计费。这就解释了为什么我的 output token 没有暴涨但总费用还是冲了上去。另一个大坑是工具定义膨胀。Claude Code 里挂的 MCP 服务器、插件、自定义工具每个请求都要带上工具描述。工具越多每次请求的 input token 越大。单个会话可能感觉不出来四个会话并行之后工具定义被重复加载四遍哪怕没实际调用描述文本也已经计入费用了。如果某个 MCP 服务器的描述写得特别啰嗦那它几乎是在偷偷烧钱。3. 一个配置解决给子 Agent 指定专用模型3.1 配置入口和具体写法先说结论这个配置写在项目的.claude/agents/目录里。Claude Code 允许你用 Markdown 文件定义自定义 Agent每个文件代表一个 Agent文件头部有一段 YAML frontmatter里面可以声明 name、description、tools 和 model。我的做法是给使用频率最高的几个子 Agent 分别建了文件并且统一加上了 model 字段全部指向便宜的小模型。举个例子我建了一个代码检索 Agent--- name: code-searcher description: 在仓库中检索代码、查找定义和引用关系输出结构化结果 tools: Read, Grep, Glob model: claude-haiku ---再比如变更摘要 Agent--- name: change-summarizer description: 读取 git diff 和相关文件生成简洁的变更说明 tools: Read, Grep model: claude-haiku ---关键就是那个 model 字段。没有这个字段时子 Agent 走的是主会话的模型配置费用高填上之后它就按照你指定的模型去跑单价立刻降下来。这就是标题里说的那一个配置。可能有读者会问所有子 Agent 都写 model 字段会不会很麻烦。我的经验是值得的你只需要给那些高频、窄任务、只读类型的 Agent 写上小模型真正负责写代码的主力 Agent 保留强模型就行。一个仓库里这种文件的个数通常不超过十个一次配置长期生效。3.2 配置之后账单发生了什么变化我改完配置之后重新跑了一轮同样的任务效果非常直接。子 Agent 承担了大量检索、阅读、摘要工作这些工作以前按强模型计费现在按小模型计费成本单价大概下降了一个数量级。整体账单回到开并行之前的水准某些重复性任务甚至比单会话全量跑还低。成本变低不等于质量下降。关键是我把任务边界也理清了子 Agent 只做范围明确的窄任务最终方案和代码改动还是由主 Agent 拍板。窄任务对模型能力的要求本来就不高用便宜模型完全够用。反而是以前那种让强模型去反复检索文件的做法既浪费钱速度还慢。这里给一个直观的换算思路。假设一次子任务消耗的 input token 相同模型 A 的输入单价约为模型 B 的十分之一那么同样的任务单位成本就是原来的十分之一。如果整个工作流里有六成 token 消耗发生在子 Agent 身上那总成本能省掉差不多一半以上。这是最简单的算术但前提是这个配置得真的写对。3.3 如果你还是想开多个终端会话如果你和我一样确实需要同时开多个终端会话跑不同任务那除了子 Agent 配置还有几个配套做法需要跟上。第一尽量用 continue 模式延续会话不要每次都从全新的空会话开始。延续会话至少能保住一部分 prompt 前缀让缓存命中率不至于跌到零。我从多个会话平行切到续跑模式之后缓存命中率上来了input token 的浪费少了不少。第二不同任务不要各自为战地开在不同目录。Claude Code 的上下文很吃工作目录目录不同、加载的 MCP 配置不同缓存前缀就对不上。要么统一在同一个项目根目录启动要么干脆就用子 Agent 来区分任务而不是再开一整份会话上下文。第三控制并发上限。一个简单的 Bash 脚本就能做到串行队列for task in task-a task-b task-c task-d; do echo running $task claude -p 执行 $task 目录下的重构任务只输出最终变更 done这个脚本把四个任务排成队每个跑完再跑下一个。虽然总耗时变长了但成本比四个全并行低很多。如果你想微调也可以用类似 GNU parallel 的工具控制最大并行数设为 2效果介于全并行和全串行之间。4. 排查方法和避坑清单4.1 快速定位账单增长点遇到账单异常第一件事不是去改配置而是先搞清楚钱花在哪。我建议去 Anthropic 控制台的用量页面按模型维度看 token 消耗分布。如果发现某个贵模型的 input token 数量远超你预期那大概率就是模型继承问题。第二个办法是看缓存命中率。控制台通常能体现缓存相关数据缓存命中率的趋势一旦明显下行就可以怀疑是并行会话导致的重复上下文。这时候把多个会话改成续跑模式或者统一从同一目录启动命中率会很快回暖。第三个办法是开调试模式观察请求细节。Claude Code 支持查看请求日志你可以确认每个请求实际使用的模型名称看看是不是有子 Agent 在偷偷用贵模型。这个日志在排查阶段特别有用比对着账单猜要快得多。4.2 避坑速查表场景现象处理方法子 Agent 未指定模型用量记录里贵模型 input 暴涨在.claude/agents/里给子 Agent 写 model 字段多个会话并行缓存命中率极低input 重复上涨用 continue 延续会话或改用子 Agent 而非重量级会话MCP 服务器挂太多每次请求 tools 描述很大精简子 Agent 的 tools不往子 Agent 堆一堆 MCP 服务器频繁报错重试成功次数少但费用高降低并发数检查是否触发速率限制必要时做任务排队上下文被截断后重推输出 token 不高但 input 异常高调小单次任务范围不要让一个会话揽全仓库的活这张表基本覆盖了我这次踩坑的所有场景。对照着排查半小时内就能定位到问题根因。4.3 几个容易被忽略的细节再分享几个细节层面的坑。第一子 Agent 里的 tools 越少越好。tools 字段不只是权限声明它还会直接影响每次请求携带的工具描述。子 Agent 能干活的前提是它有足够的工具但给它塞一堆不需要的 MCP 工具只会让 input token 白白膨胀。第二注意配置文件的覆盖顺序。Claude Code 的配置有全局、项目、本地之分.claude/settings.local.json会覆盖项目配置。如果你改了项目配置但没生效先检查本地配置里是不是有同名项。第三给 Agent 命名的时候description 要写得具体一点。Claude Code 调度子 Agent 时会根据 description 判断该调哪个 Agent。描述含糊会导致主 Agent 选错子 Agent选错了就得重新跑来回折腾的每一轮都是钱。把 description 写清楚比如“只负责检索不负责修改代码”调度准确率会高很多。5. 成本优化不是不开 Agent而是分级5.1 让每一层 Agent 干它该干的活经过这一轮折腾我对 Agent 编排的理解变了不少。以前总觉得 Agent 多开就是提效现在更倾向于把 Agent 分成不同层级每层用不同模型、不同工具、不同权限。主 Agent 承担规划、决策、代码修改它需要强模型和完整工具链子 Agent 承担检索、验证、摘要、翻译它需要小模型和窄工具集。这种分级方式和 Agent 框架里的 harness 与 agent 的关系很类似harness 提供运行环境和调度骨架agent 在骨架里执行具体任务。框架解决了“怎么跑起来”的问题但没帮你解决“谁该用什么模型”的问题后者得自己配置。Skill 和 Agent 的区别也值得拎出来说一下。Skill 更像是一组能力包比如“代码审查技能包”“测试生成技能包”它不绑定模型可以被不同 Agent 调用。Agent 则是带模型、带工具、带权限的执行单元。成本优化的重点不在 Skill而在 Agent 的模型和工具组合。模型贵不贵、工具多不多直接决定了每一轮任务的单价。5.2 警惕 Agent 记忆带来的上下文重复热词里有 Agent 记忆相关的讨论我也踩到了边。并行 Agent 各自有各自的上下文彼此不知道对方已经读过哪些文件。如果每个 Agent 为了完成任务都把仓库的核心文件重新读一遍那多 Agent 的记忆优势就变成了成本灾难。解决方式也很简单任务描述里给出足够上下文但不要给整段对话粘贴。比如子 Agent 需要知道某个函数的位置直接把函数签名和文件路径给它而不是让它自己从头读一遍整个项目。更不要在主上下文里塞入子 Agent 已经读过的东西能不重复就不重复。我这里要特别提醒多个 Agent 并行改代码时最好的状态是“各看各的文件”最怕的状态是“每个人都把项目目录扫一遍”。想判断是不是犯了这个错可以看每次请求的 token 数如果单个请求动不动就几万 input token且其中大部分是和任务无关的全局文件那就要做上下文收敛。5.3 把配置沉淀进仓库团队一起受益这个改善不能只停留在个人配置里。我最后把.claude/agents/目录提交到了仓库里面每个 Agent 文件都写清楚了模型和工具团队其他人拉下来就能直接用。这样大家都不会掉进模型继承的坑新人也省得自己从头摸索。另外我还在项目 settings 里做了预算相关的提醒隔一段时间看一眼用量不用等账单炸了才反应。成本优化的本质不是不开 Agent而是用最合适的配置让每个 Agent 干最擅长的事付最匹配的价钱。我这几天把配置改成上面的样子并行还是照开只是每个子代理的工具和模型都做了收敛。实测账单回到开并行之前的水准某些重复性任务甚至更低。最后再提醒一句别只看模型单价子代理的工具数量、缓存命中率、自动重试次数才是隐藏账单。先把模型分级这个配置补上再谈多 Agent 提效。