OpenClaw 的 reserveTokensFloor 到底怎么影响 auto-compaction?
最近我在调 OpenClaw 的 session 行为时,碰到一个非常典型的问题:
我知道模型有 context window,也知道 OpenClaw 会做 auto-compaction。
但 到底什么时候会触发 compact ?
以及,能不能把"危险线"提前一点,比如 75% 就开始保护性压缩?
这个问题看起来像"改个阈值"就结束了,但如果往里拆,会发现它牵涉到 模型窗口、运行时 headroom、上下文保留策略、以及长对话稳定性。
这篇文章就把 reserveTokensFloor 这个配置讲透:
- 它到底是什么
- 它和
reserveTokens是什么关系 - auto-compaction 何时触发
- 为什么不能简单理解成"百分比阈值"
- 如果想把 compaction 提前到大约 75%,该怎么配
先说结论
如果你只想先拿结论,可以直接记住下面这几条:
- OpenClaw / Pi runtime 的 auto-compaction 不是按固定轮数触发,也不是按固定时间触发。
- 它核心看的是:
text
contextTokens > contextWindow - reserveTokens
reserveTokensFloor不是"压缩百分比",而是 给reserveTokens设一个最小下限。- 如果模型窗口是 128k ,想让 compaction 大约在 75% 上下变得更积极,可以把:
json
"reserveTokensFloor": 32000
- 50% 通常太激进,不建议一上来就这么配。
auto-compaction 到底什么时候发生?
根据 OpenClaw 文档,Pi runtime 下 auto-compaction 主要有两种触发方式:
1. Overflow recovery
如果模型已经返回 context overflow 错误,系统会:
- 先 compact
- 再 retry
这个很好理解,它是"已经撞线之后的补救"。
2. Threshold maintenance
更常见的是第二种:在一次 successful turn 之后,运行时发现上下文已经很重了,于是提前触发压缩,避免下一轮请求直接撞上限。
公式就是:
text
contextTokens > contextWindow - reserveTokens
这里有三个变量:
contextTokens:当前会话已经占掉的上下文 tokencontextWindow:模型总窗口reserveTokens:给后续 prompt、system、tool 调用结果、以及下一次模型输出预留的 headroom
所以,本质上不是"上下文用了多少百分比",而是:
在当前上下文基础上,系统还要不要为下一轮保留足够的生存空间。
这比单纯的百分比更工程化,也更接近实际运行条件。
reserveTokensFloor 是什么?
这是最容易误解的地方。
很多人第一次看到 reserveTokensFloor,会以为它就是"compact 触发阈值"。
其实不是。
它更准确的含义是:
给 Pi runtime 的
reserveTokens设一个保底值。
也就是说:
- 真正参与公式的是
reserveTokens - OpenClaw 会确保它不低于
reserveTokensFloor
所以 reserveTokensFloor 更像一个 safety floor,而不是一个 direct threshold。
文档里默认 floor 是 20000 tokens。
这意味着,如果运行时本来给的 reserveTokens 更低,OpenClaw 会把它抬到至少 20000;如果本来更高,就不会压低。
为什么它不能直接理解成"75%"或"50%"?
因为 compaction 逻辑不是这样写的:
- ❌
if usage > 75% then compact - ✅
if contextTokens > contextWindow - reserveTokens then compact
所以如果你说"我想在 75% 左右触发",你实际上是在表达:
我希望预留大约 25% 的窗口当 headroom。
如果模型窗口是 128k,那大致换算是:
| 目标触发点 | 对应预留 headroom | 约等于 reserveTokens |
|---|---|---|
| 50% | 50% | 64000 |
| 60% | 40% | 51200 |
| 70% | 30% | 38400 |
| 75% | 25% | 32000 |
| 80% | 20% | 25600 |
| 85% | 15% | 19200 |
换句话说:
- 想更早压缩 → 提高
reserveTokens - 想更晚压缩 → 降低
reserveTokens
而不是去找一个"百分比字段"。
为什么默认 20000 在 128k 窗口下不算早?
如果窗口是 128000,而 reserveTokensFloor = 20000,那你可以做一个直观估算:
text
128000 - 20000 = 108000
也就是大约在 108k context tokens 附近,系统才会明显进入 compaction 压力区。
换成百分比,大概是:
text
108000 / 128000 ≈ 84.4%
所以默认配置本质上更接近:
"先尽量保留原始上下文,快到 84% 以后再积极压缩。"
这对很多普通对话、短任务、轻量工具调用是合理的。
但如果你的 session 使用模式是:
- 长对话
- 连续 research
- 大段网页内容 / 文件内容注入
- 浏览器工具、tool result 很多
- 希望更早进入保护模式
那么默认 20000 就可能显得偏晚。
为什么 75% 常常比 50% 更合理?
很多人第一反应会说:
那我干脆提早到 50%,不就最稳了吗?
听起来合理,但实际会带来两个副作用:
1. compaction 会变得过于频繁
如果你把 reserveTokens 或 floor 拉到 64k,相当于一半窗口刚用掉就开始压缩。
这会导致:
- 会话更早被 summary 化
- 原始对话细节保留时间缩短
- 长任务中的上下文连续性可能下降
2. 会影响长链任务体验
对于需要逐步积累语境的任务,比如:
- 写长文
- 多轮研究总结
- 一边查资料一边沉淀
- 带工具的复杂分析
过早 compact 往往不是"更安全",而是"更快丢细节"。
所以从实战经验看:
- 50%:通常过于激进
- 75%:更平衡
- 80%-85%:更接近默认保守策略
这也是为什么我更推荐先把 floor 调到 32000,而不是直接冲到 64000。
一个实战例子:把 128k session 调到约 75% 提前保护
如果你当前模型窗口是 128k ,希望在大约 75% 左右就开始更积极地进入 compaction 保护区,可以在 OpenClaw 配置里这样写:
json
{
"agents": {
"defaults": {
"compaction": {
"mode": "safeguard",
"reserveTokensFloor": 32000
}
}
}
}
这个配置的含义是:
- 继续用
safeguard模式处理较长历史 - 把 compaction 的安全预留空间抬到 32000
- 对于 128k 窗口,相当于更接近 75% 附近开始紧张
注意,这依然不是严格的"75% 固定阈值",而是更接近 75% 的 headroom 策略。
reserveTokensFloor 之外,还要注意什么?
1. memoryFlush.softThresholdTokens
OpenClaw 还有一个相关配置:
memoryFlush.softThresholdTokens
它的作用不是触发 compaction,而是:
在 auto-compaction 之前,先运行一个静默的 memory flush turn,把值得长期保存的信息落盘。
这个设计很聪明,因为它承认了一件事:
- compaction 不是无损的
- 所以在 compact 前,最好先把 durable memory 存下来
2. contextPruning
另一个容易和 compaction 混淆的点是 contextPruning。
它主要做的是:
- 先从内存上下文里裁旧的 tool results
- 但不会修改磁盘上的 session history
所以可以粗略理解为:
- compaction:把历史压成摘要,属于 session-level 变化
- contextPruning:裁工具输出,属于 in-memory payload 优化
很多时候,如果你的上下文膨胀主要来自超长 tool result,先看 pruning 也很值。
什么场景应该考虑提高 reserveTokensFloor?
我会建议在下面几类场景里考虑调高:
1. 高频长对话
如果一个 session 不是短问短答,而是长时间持续协作,context 会很快堆起来。
2. Research / 学习 / 知识沉淀型工作流
这类任务很容易把网页内容、文档摘要、代码片段都塞进上下文。
3. 工具调用很多
尤其是:
- 浏览器抓取
- 大段 shell 输出
- 长文写作
- 文件读取与总结
这些都会迅速推高 contextTokens。
4. 你更在意"提前保护"而不是"尽量保留原始历史"
这是一种 trade-off。
如果你希望:
- 更少碰到濒临上限的不确定感
- 更早进入可控压缩
- 更稳地留出后续操作空间
那就可以把 floor 提前一些。
我的配置建议
如果你的主模型也是 128k 窗口,我会这样建议:
方案 A:稳妥平衡(推荐)
json
"reserveTokensFloor": 32000
适合:
- 长对话较多
- 工具调用较多
- 想提前一点,但不想太激进
方案 B:更保守一点
json
"reserveTokensFloor": 38400
适合:
- 非常频繁的 research / multi-tool workflow
- 非常在意上下文安全边际
方案 C:不建议直接上来就用
json
"reserveTokensFloor": 64000
这大致相当于 50% 附近就开始压缩,通常过于激进。
结语
reserveTokensFloor 这个配置看起来很小,但它背后其实体现的是一个很重要的工程思路:
上下文管理不是"快满了再处理",而是要给下一轮推理保留足够 headroom。
所以如果你要记住一件事,那就是:
- 它不是百分比阈值
- 它是 headroom 策略
而当你的 session 开始承载长对话、research、工具链协作时,适当提高 reserveTokensFloor,往往会比等到 84% 以后再救火更舒服。
对于 128k 模型窗口,我目前最推荐的起点仍然是:
json
"reserveTokensFloor": 32000
也就是:
先试 75% 左右,再根据你的真实工作流密度继续微调。