常驻上下文开销
会话发送的每个请求都会在任何对话内容之前携带相同的前缀:系统提示词、所有已声明工具的 schema、你的上下文(QWEN.md)文件,以及 skill 列表。你在每个轮次都要为这个前缀付费,包括那些仅仅回答问题的轮次。本页介绍如何衡量并削减它。
Token 缓存 降低前缀的_价格_。本页降低_前缀本身_。两者可以叠加——更小的前缀在缓存后也更便宜。
查看你在为什么付费
/context detail/context 按类别打印明细;detail 会额外列出逐行条目——每个内置工具、每个 MCP 工具、每个上下文文件、每个列出的 skill——让你看到哪一项是开销最大的。在会话的第一个轮次阅读它,此时对话仍为空,你看到的全部内容都是前缀。
这些类别是 /context 报告的内容,再加上两个记账行:startupContext(作为第一个用户轮次发送的环境块)以及一个显式的残差项,用于归集类别未能归属的部分,因此各部分之和始终等于总量。
使用空闲开销,而非窗口百分比
上下文窗口的百分比不是一个你能守住的指标,因为分母是任意的。同一份配置在 1M 上下文模型上读起来是 6.5%,在 128k 模型上则是 37%——相同的文本,相同的开销,数字却天差地别。请改用:
空闲开销 —— 一个只问了一个问题且未调用任何工具的会话的输入 token 数。
它与模型和窗口无关,你也无法通过将文本从工具 schema 移到上下文文件来让它好看。另一个有用的读数是对话需要多少轮才能超过前缀:一个需要 20 轮才能摊薄的前缀,在 5 轮的会话中永远摊薄不了。
调节手段,按收益排序
1. 关闭你不使用的功能
每个注册了工具的功能都要在每个请求中为该工具的 schema 付费。最大的单项内置条目属于可选功能,因此不使用 workflow、goal、定时任务或 review 工具的部署,关闭这些功能比任何提示词编辑都能节省更多。这也会从子代理中移除该工具,而下一个手段不一定能做到这一点。
2. 将 eager 工具集保持在真正使用的范围内
tools.eager 是一个允许列表,列出的内置工具的 schema 会保留在初始请求中。其余工具变为延迟加载:仍然注册、仍然列在 /tools 中、仍然可调用——模型在确实需要时通过 tool_search 加载它。
{
"tools": {
"eager": [
"read_file",
"write_file",
"edit",
"glob",
"grep_search",
"run_shell_command",
"skill",
],
},
}使用之前需要了解四件事:
- 它不是禁用。 被降级的工具仍然可以访问。如果你的目的是移除一个工具,请使用整工具级别的
permissions.deny规则或tools.disabled。 - 某些工具不受影响,无论列表如何设置都保持正常的加载行为:
tool_search、structured_output、plan 模式生命周期工具(enter_plan_mode、exit_plan_mode、ask_user_question)、task_stop、MCP 工具(mcp__*)以及 Computer Use 工具(computer_use__*)。task_stop和 Computer Use 系列默认就是按需加载的,因此对它们做门控不会节省任何东西;MCP 工具由tools.toolSearch.*以及每个服务器的includeTools/excludeTools过滤器管理,而前三个工具唯一能移除它们的方式是permissions.deny。 permissions.allow不会节省任何东西。 它纯粹是自动审批:它从不降级、隐藏或移除工具。审批模式也不会。- 它需要
tool_search保持开启。 如果 ToolSearch 未注册——tools.toolSearch.enabled: false、一条tool_search的 deny 规则,或者 DeepSeek 模型的自动退出——允许列表仍然会扣留 schema,但没有任何东西能把它们加载回来,被降级的工具在该会话中将无法访问。
tools.visible 是一个逃生舱口,用于你希望某个工具即使默认延迟加载也要在开始时声明的情况。
3. 将场景指导从上下文文件移到 skill 中
上下文文件会被拼接到它适用的每个会话的每个请求中,没有相关性门控。skill 只按名称和描述列出——在一个实测样本中,84 个 skill 平均每个约 55 个 token——在被调用时才加载其正文,而一个基于 paths: 门控的 skill 在匹配的文件被触及之前甚至不会被列出。
上下文文件中只保留始终为真的内容——身份、词汇表、硬性约束——将”做 X 时,执行 Y”放在 skill 或 paths: 门控规则 中。/context detail 会列出每个上下文文件的名称,对于扩展的文件,它会列出拥有该文件的扩展。
4. 系统提示词,最后考虑
基础提示词已经是常驻类别中最小的,其中大约三分之一是不能编辑的安全和权限文本。它现在也只描述会话实际声明的工具,因此裁剪工具集也会让它稍微缩小一些。用 --system-prompt 整体替换它是可行的,也是本页风险最高的变更;如果你这样做,请在每次升级时 diff 上游提示词。
陷阱
- 子代理也会获得延迟工具。 没有声明显式工具列表的子代理会接收所有已注册工具的 schema,包括延迟工具,并且不经过 ToolSearch。
tools.eager和permissions.deny是唯一能影响它的调节手段;预加载阈值对它无效。 - 后台 memory 代理需要六个工具(
read_file、grep_search、glob、run_shell_command、write_file、edit)。拒绝其中任何一个都会让它静默降级,而不是报错。 - Token 可能只是移动而非消失。 拿走
grep_search和glob,模型可能会通过 shell 使用grep和find,其输出会进入对话。新输出在首次发送时会增加输入 token;包含它的未变更历史在后续请求中可能会命中提供商的前缀缓存。通过每个任务的总输入 token、提供商报告的缓存和未缓存输入以及实际账单来评判变更,而不是仅看前缀。 - 恢复的会话会重新发送所需内容。 出现在恢复会话历史中的被降级工具会自动恢复其 schema;被拒绝的工具则不会。
- 在会话中途揭示的延迟工具会使前缀缓存失效。 函数声明位于前缀的最前面,因此一次揭示就会重写它,整个提示词在该轮次都要重新计算。预加载延迟集(
tools.toolSearch.threshold)可以避免这种情况,代价是每个轮次都要携带这些 schema;threshold: 0只有在会话确实从不需要它们时才划算。 - 前缀缓存模型会反转权衡。 对于折扣依赖于稳定前缀的模型,保持前缀不变比让它更小更有价值;DeepSeek 模型因此自动退出 ToolSearch。
- 作用域会泄漏。 设置适用于读取它们的每个客户端(CLI、Web Shell、serve),因此按部署划分的工具集需要自己的设置作用域。
验证节省效果
- 记录变更前的空闲开销:一个全新会话,一个简单问题,在第一个轮次执行
/context。 - 每次应用一个调节手段并重复,重启会话——这些设置中的大多数在启动时读取。
- 在你自己的任务集上确认能力仍然存在:工具调用成功率、
tool_search被调用的频率,以及任务结果。一个模型从未想到要查找的被降级工具不会大声报错;它只是不再被使用。 - 检查账单,而不仅是前缀——参见关于 token 移入对话的陷阱。