乐于分享
好东西不私藏

[龙虾进化论] OpenClaw 记忆系统修复:compaction 参数逐一拆解,不是调参玄学

[龙虾进化论] OpenClaw 记忆系统修复:compaction 参数逐一拆解,不是调参玄学

AGENT-005 · Day 2 副文 A


网上流传着很多「OpenClaw 最佳配置」,直接复制粘贴,一行解释都没有。

这种配置用起来可能有效,但你不知道为什么有效,也不知道什么情况下它会失效,更不知道自己的使用场景是不是真的适合这套数字。

今天把 compaction 相关的参数逐一拆开,不只说建议值,说每个数字背后的逻辑——以及调大调小各自会发生什么。


先理解:compaction 在保护什么

Compaction 要解决一个根本矛盾:上下文有限,但对话无限。

它的任务是:在上下文快满的时候,把旧内容压缩成摘要,为新内容腾出空间。但「压缩」这件事本身有代价——细节会丢失,复杂的约束会被简化,语气和强调会消失。

所以 compaction 的参数设置,本质上是在回答一个问题:你愿意用多少上下文空间,换来多少近期内容的完整保留?

没有绝对的最优解,只有适合你使用模式的合理权衡。


参数一:mode

两个选项"default" 和 "safeguard"

"default" 是激进模式:上下文快满时,大刀阔斧地压缩,优先腾出空间,不太在乎近期内容的完整性。

"safeguard" 是保守模式:压缩时会主动保护近期内容,宁愿压缩得少一点、多触发几次,也要保证你最近说的话不被摘要掉。

**为什么建议用 "safeguard"**:对大多数工作场景来说,你最近说的话是最重要的。你刚刚给出的纠正、刚刚确认的方向、刚刚提到的约束——这些比三小时前的背景介绍要紧得多。"default" 模式下,这些近期内容和旧内容同等对待,有可能在压缩中一起被摘要掉。

**什么时候用 "default"**:如果你主要用 OpenClaw 做长时间运行的批处理任务,对话本身不重要,重要的是输出结果,那么激进压缩是合理的——不需要保护对话细节,需要的是尽可能长的运行时间。


参数二:keepRecentTokens

建议值20000

它控制什么:从当前位置往回数,保护最近这么多 token 的内容不被压缩。设置为 20000,意味着最近约 2 万个 token 的对话内容,即使触发了 compaction,也会被完整保留,不做任何摘要处理。

默认值的问题:默认值非常低,保护的范围很小。你刚说的内容,可能已经在保护范围之外了。

代价是什么:这个数字越大,能用来装「其他内容」的空间就越少。20000 token 的保护区,大约是 15000-16000 个中文字,相当于一篇中等长度的技术文档。这部分空间是专门「锁起来」给近期对话用的,不能被工具调用结果或其他文件占用。

调大的后果:保护更多近期内容,但能用于长文档处理或复杂工具调用的空间变少,可能导致某些任务无法在一次对话里完成。

调小的后果:近期对话保护减少,AI 开始「忘记」你最近说的事,会话内失忆问题出现。


参数三:recentTurnsPreserve

建议值4

它控制什么:保留最近完整的 N 轮对话(一问一答算一轮),这些轮次完全不做摘要,原文保留。

和 keepRecentTokens 的区别keepRecentTokens 是按 token 数量保护,recentTurnsPreserve 是按对话轮次保护。两者同时生效,取保护范围更大的那个。

为什么需要两个?因为 token 数量和轮次是两个维度的度量。一个很简短的对话可能有 10 轮,但 token 很少;一个很深入的单次回复可能消耗大量 token,但只算 1 轮。两个参数配合,能更精确地描述「你想保留的近期内容」。

设置为 4 的逻辑:4 轮对话通常足以覆盖一个完整的工作单元——你提问、AI 回答、你纠正、AI 修正。保留这 4 轮,基本能保证当前工作的连贯性。

设置更高:适合长篇创作或复杂分析场景,需要 AI 在写作过程中始终记得早期确定的方向。但会进一步压缩其他内容的空间。


参数四:maxHistoryShare

建议值0.7

它控制什么:历史内容(被压缩后的摘要)最多能占整个上下文窗口的多少比例。设置为 0.7,意味着历史内容最多占 70%,剩余 30% 留给当前对话、工具调用结果和模型回复。

为什么不能设到 0.9 或 1.0:如果历史摘要占满了 90% 的空间,留给当前对话的空间只有 10%。这时 AI 一个复杂的工具调用结果可能就把剩余空间填满,导致无法正常回复,甚至触发新的压缩——陷入连锁反应。

0.7 是一个经验值:给历史内容足够的空间,让 AI 有长期记忆;也给当前操作留出足够的余量,不会在关键时刻「卡住」。

设置更低(比如 0.5):对话的有效历史更短,AI 更快忘记早期内容,但每次交互的空间更宽裕,适合需要大量工具调用或处理长文档的场景。


参数五:reserveTokens

建议值30000

它控制什么:预留给模型输出的最小空间。无论上下文有多满,这部分空间不会被占用,专门留给 AI 生成回复。

太低会怎样:如果 reserveTokens 设得很小,当上下文接近上限时,AI 可能只剩几百个 token 用来回复——它会开始截断回答,或者说「因为上下文限制,我无法完整回答」。这在工具调用返回大量数据的时候尤其容易发生。

为什么是 30000:足够 AI 生成一份完整的分析报告或多步骤工作流的结果。如果你的任务主要是短对话,可以适当调低;如果你常常让 AI 生成长文档,可以调高到 40000-50000。


context pruning:工具调用的隐形杀手

Compaction 参数调好了,还有一个容易被忽略的问题:工具调用的输出。

每次 AI 用 web_fetch 抓了一个网页,或者读了一个大文件,那个原始输出就留在上下文里——不是对话,但占用大量 token。一次抓取可能消耗 5000-10000 token,十几次之后,有用的对话内容就被挤出去了。

这是会话内失忆的另一个来源,和 compaction 完全无关,但同样破坏性。

解决方案是开启 context pruning:

agents.defaults.contextPruning:  mode: "cache-ttl"  ttl: "2h"  keepLastAssistants: 10  minPrunableToolChars: 2000

cache-ttl 模式:工具调用的原始输出在超过 TTL 时间后自动从上下文移除。2 小时是一个合理的值——足够在同一个工作会话里用到,但不会无限期占用空间。

minPrunableToolChars: 2000:只清理超过 2000 字符的工具输出。短的工具结果(比如查一个日期)通常没必要清理;占大量空间的长输出(爬取的网页、读取的文档)才是清理目标。


postCompactionSections:压缩后为什么规则会漂移

最后一个容易被忽略的问题:compaction 发生之后,AGENTS.md 里的规则还在不在?

理论上在——因为 AGENTS.md 是系统提示的一部分,不会被 compaction 压缩。但实际使用中,很多人发现长会话之后 AI 开始「忘记」早期确认的行为规则。

原因是:compaction 会产生一段新的摘要,这段摘要被插入上下文,覆盖了一部分原来的内容。如果摘要和 AGENTS.md 的某些指令有隐性冲突,模型会在两个「信号」之间做权衡,早期的规则可能在权衡中被降权。

修复方式是配置 postCompactionSections:在 compaction 触发之后,自动把 AGENTS.md 里的关键规则重新注入一次,相当于在每次压缩后「提醒」模型你的核心约束:

发给 Agent 执行:更新 OpenClaw 配置,在 agents.defaults.compaction.postCompactionSections里添加我 AGENTS.md 里「不变的底线」和「判断优先级」这两个章节,在每次 compaction 后重新注入。

根据你的使用模式选参数

没有通用的最优配置,只有适合你场景的配置:

短会话为主(每次对话 30 分钟以内):compaction 很少触发,重点在于开启 context pruning 清理工具输出,以及配置好手动存档的习惯。参数调整收益有限。

长会话为主(同一对话持续几个小时):所有参数都值得认真设置。keepRecentTokens 调到 25000-30000,recentTurnsPreserve 调到 6,reserveTokens 根据你的任务类型调整。

长期运行的定时任务(cron job 类型):mode 可以用 "default",优先运行时间而不是对话细节的保留。重点是配置好 postCompactionSections,确保规则在多次压缩后依然生效。


配置模板(直接发给 Agent 执行):

更新我的 OpenClaw compaction 配置(agents.defaults.compaction):- mode: "safeguard"- keepRecentTokens: 20000- recentTurnsPreserve: 4- maxHistoryShare: 0.7- reserveTokens: 30000同时更新 context pruning 设置(agents.defaults.contextPruning):- mode: "cache-ttl"- ttl: "2h"- keepLastAssistants: 10- minPrunableToolChars: 2000