← 返回目录
第 7 章

上下文经济学:Token 就是预算

四道压缩机制、Reactive Compact、Token Budget、按需注入——Claude Code 怎么在有限的上下文窗口里装最多有用的信息。

上下文窗口是有限资源。每个 token 都有成本,窗口装满之后模型开始遗忘,或者 API 直接返回 413。Claude Code 在这个约束下做了一套完整的预算管理体系——不是”尽量少用 token”,而是”在有限空间里装最有价值的信息”。

四道压缩机制

压缩不是一刀切的全量摘要,而是按轻重程度分四道,优先做代价小的。

最轻的是 Snip Compact:不动消息结构,只截内容——工具返回了 5000 行日志,保留头尾,中间替换成占位符,信息损失最小。再重一档是 Micro Compact,基于 tool_use_id 做缓存编辑,专门针对”某次工具调用输出特别大”的场景,精准压缩而不是按时间顺序粗暴截取。

往上走是 Context Collapse:把不活跃的上下文区域折叠成摘要。早期对话轮次、已完成的子任务,折叠后只保留关键结论,过程细节丢弃。最后兜底的是 Auto Compact——总 token 数逼近阈值时触发全量压缩,把整个对话历史压成一个摘要重新起跑。代价最大,但也最彻底。

四道可以叠加,轻量的够了就停,不够再升级。不是每次都直接跑 Auto Compact,那样丢掉太多有价值的中间状态。

Reactive Compact:API 413 的兜底

正常流程里四道压缩是主动触发的。但有时候时机没掌握好,或者单个消息本身就超大,API 直接返回 413(prompt too long)。

这时候触发 Reactive Compact:收到 413 → 紧急执行压缩 → 重试请求。hasAttemptedReactiveCompact 标记确保每个 turn 只尝试一次,不会陷入死循环(压完还是 413 → 再压 → 还是 413……)。

一次尝试失败的话,错误会冒出来给用户处理,而不是静默重试到资源耗尽。

Token Budget 系统

query/tokenBudget.ts 处理另一类需求:用户想控制总花费。

用户指定一个 token 目标(比如”+500k”),系统追踪每个 turn 的输出 token 累计量。接近目标时,往对话里注入一条 nudge message,告诉模型”预算快到了,注意控制输出长度,能简则简”。

这不是硬截断——硬截断会导致模型在任务中途停下来产出半成品。nudge 是软引导,让模型自己调整策略:能用短答案解决的不展开,能引用已有结论的不重复推导。

按需注入:上下文预算的主动管理

除了压缩,上下文管理的另一半是”不往里塞不必要的东西”。

Skill 按需注入——任务匹配到某个 skill 才把那个 skill 的说明注入进来,启动时不把 17 个 skill 的全部说明都预加载进 system prompt。一个 skill 说明大约几百 token,17 个全塞进去就是几千 token 的固定开销,而大多数会话根本用不到其中 14 个。

MCP instructions 按连接状态注入,没连上的 server 的说明不占空间。这个设计顺便解决了一个实际问题:用户配置了十个 MCP server 但只启动了三个,另外七个的说明不应该污染 prompt。

Memory 和 Skill discovery 都支持 prefetch——模型流式输出的同时,后台预取相关 memory 和 skill,等到模型真正需要时直接可用,不需要等一个完整的 round-trip。

工具结果太大时,内容持久化到磁盘,上下文里只保留摘要和引用。模型需要细节时可以通过工具再取,不需要时不占窗口空间。

这套体系的核心逻辑

把上面几个机制放在一起看,背后是同一个判断:上下文里的信息应该按相关性密度排列,不是按时间顺序堆积

时间最近的内容不一定最相关。三十轮之前的一个关键决策,可能比刚才一次工具调用的完整日志更值得保留。四道压缩 + 按需注入,本质上是在持续做这个筛选:把高相关性的信息留下来,低相关性的压缩或移出窗口。

Auto Compact 触发时会 fork 一个子 agent 做摘要,这个过程本身有成本。所以 CLAUDE.md 里建议手动 /compact——主动在阶段边界做压缩,质量更可控,也保留了缓存前缀,比等系统自动触发便宜。这是”理解了机制之后的用法”,而不是绕过机制。


参考来源: 本文内容参考 Xiao Tan(@tvytlx)的《Claude Code 源码架构深度解析 V2.0》,基于原报告的分析框架和研究成果整理。