1. 长会话为什么总会“变笨”:从上下文窗口说起
如果你用 OpenClaw 跑过稍微长一点的任务,比如让它连续改十几个文件、反复调试一个报错,大概率会遇到这种情况:前几轮它还记得你的项目结构,聊到后面突然开始“失忆”,甚至把之前已经确认过的方案又推翻重来。这不是模型变笨了,而是上下文窗口被塞满了。
上下文窗口可以理解成模型的“工作台面”。每个模型能同时处理的令牌数是有上限的,比如 8K、32K、128K 不等。你在 OpenClaw 里每发一条消息、每调用一次工具、每返回一段命令输出,都会往这个台面上堆东西。台面堆满之后,要么报错,要么系统自动把最早的内容挤掉——而挤掉的方式,就是压缩(compaction)。
OpenClaw 的 Agrnt(Agent)机制里,压缩不是简单删除,而是把较早的对话内容汇总成一条紧凑的摘要,保留最近的消息,然后把摘要写回会话历史。这样后续请求实际使用的是“压缩摘要 + 压缩点之后的最近消息”。摘要会持久化到会话的 JSONL 历史文件里,所以下次打开会话还能接着用。
这篇就聚焦一件事:怎么在 OpenClaw 里把上下文窗口和压缩策略配明白,让长会话、多轮任务不至于中途崩掉。我会给出可复制的openclaw.json骨架、关键字段说明、压缩触发阈值的验证动作,以及几个我实际踩过的坑。适合已经在本地跑通 OpenClaw、想进一步调优长任务稳定性的同学。
2. 前置准备:TaoToken 接入与 OpenClaw 环境确认
在动压缩配置之前,得先保证模型调用这条链路是通的。OpenClaw 本身是客户端,真正干活的是背后的模型提供方。我这边习惯用 TaoToken 做统一接入,原因是它的 provider/model-id 格式和 OpenClaw 的配置能直接对上,切换模型时不用改一堆代码。
TaoToken 的官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 基址是 https://taotoken.net/api 。注意 API 地址后面不加 UTM 参数,配置里填干净的就行。
你需要先拿到 API Key。进控制台创建:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,然后在 API Keys 页面生成:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。生成后复制那串sk-开头的字符串,后面配置要用。
环境确认这块,先跑一条命令看 OpenClaw 版本和当前 provider 列表:
openclaw --version openclaw providers list如果providers list里能看到你配置的 TaoToken 条目,说明基础接入没问题。看不到的话,检查一下配置文件路径,通常是~/.config/openclaw/openclaw.json或者项目根目录下的openclaw.json。
提示:压缩配置写在
agents.defaults.compaction下面,属于 Agent 默认行为,不是 provider 级别。所以 provider 配好之后,压缩这块是独立调优的。
3. 可复制配置:openclaw.json 压缩骨架与字段详解
OpenClaw 的压缩配置集中在agents.defaults.compaction。下面这份骨架可以直接抄,改掉模型 id 就能用:
{ "agents": { "defaults": { "compaction": { "enabled": true, "mode": "auto", "targetTokens": 24000, "threshold": 0.85, "identifierPolicy": "strict", "model": "taotoken/anthropic/claude-sonnet-4-5" } } } }逐字段说一下,这些是我实测下来最影响行为的几个:
enabled控制自动压缩总开关,默认就是true。如果你在调试压缩逻辑,可以临时关掉观察原始上下文增长。
mode有两个常用值:auto和manual。auto是接近窗口上限时自动触发,manual只在你敲/compact时才压缩。长任务建议保持auto。
targetTokens是压缩后希望达到的目标令牌数。这个值不是越小越好——压得太狠,摘要会丢掉关键决策;压得太松,等于没压。我一般设成模型窗口的 20% 到 30%。比如 128K 窗口,设 24000 到 32000 比较稳。
threshold是触发阈值,取值 0 到 1,表示上下文占用达到窗口的百分比时启动压缩。0.85 意味着用到 85% 就开始压。设太高容易在压缩前就撞墙,设太低会频繁压缩、增加延迟。0.8 到 0.9 是甜区。
identifierPolicy默认strict,会保留不透明的标识符(比如文件哈希、工具调用 ID)。如果你发现摘要里出现一堆看不懂的 ID 占地方,可以设成off;想自定义就设custom并配identifierInstructions。
model是压缩摘要用哪个模型生成。这个字段很关键:当你的主模型是本地小模型时,可以让一个更强的模型专门做摘要。格式是provider/model-id。比如用 TaoToken 接 Claude:
{ "agents": { "defaults": { "compaction": { "model": "taotoken/anthropic/claude-sonnet-4-5" } } } }本地模型也行,比如专门跑一个 Ollama 做摘要:
{ "agents": { "defaults": { "compaction": { "model": "ollama/llama3.1:8b" } } } }不设这个字段的话,压缩就用 Agent 的主模型。主模型如果是本地 7B,摘要质量可能一般,长任务里会明显感觉“越压越糊”。
4. 验证压缩是否生效:从 /status 到 JSONL 文件
配完不等于生效,得验证。OpenClaw 提供了几个观察点。
第一个是详细模式下的状态输出。启动会话时开 verbose,压缩完成会打印:
🧹 Auto-compaction complete如果只看到🧹 Compactions:后面跟着数字,说明压缩发生过,但没打印完整状态。这个在/status命令里也能看到,会显示累计压缩次数。
第二个是手动触发验证。在会话里直接敲:
/compact 关注决策和未解决的问题/compact后面可以跟指令,告诉摘要模型重点保留什么。这条命令会强制压缩一次,不管当前占用多少。适合在会话感觉“陈旧”或上下文臃肿时手动清一次。
第三个是查 JSONL 历史文件。压缩摘要会持久化到会话的 JSONL 里,路径一般在~/.config/openclaw/sessions/下面,文件名带会话 ID。用tail看最后几条:
tail -n 5 ~/.config/openclaw/sessions/<session-id>.jsonl你会看到一条类型为compaction或summary的记录,里面就是压缩后的摘要内容。如果这条记录不存在,说明压缩没真正落盘。
第四个是观察令牌占用变化。压缩前后各跑一次/status,对比上下文占用数字。正常情况下压缩后占用会明显下降,然后随着新消息继续增长,到阈值再压。这个“锯齿形”曲线是健康的。
注意:压缩和修剪(session pruning)是两回事。压缩是摘要并持久化到 JSONL;修剪只裁掉旧的工具结果,在内存里操作,每次请求重新算。大型工具输出已经被截断过,修剪能进一步减少工具结果的累积。两者可以同时开。
5. 常见报错与排查:压缩不触发、摘要丢关键信息
问题一:配了 threshold 但压缩从不触发。先确认enabled是true,再看mode是不是被设成了manual。还有一个容易忽略的点:上下文窗口大小是模型特定的,OpenClaw 从 provider 目录里的模型定义读取限制。如果你用的模型 id 在目录里没有对应定义,窗口大小可能取默认值,导致 threshold 算出来的触发点不对。检查openclaw providers list里该模型的contextWindow字段。
问题二:压缩后摘要丢关键信息。这通常是targetTokens设太小,或者摘要模型能力不够。两个方向调:把targetTokens往上提,或者给compaction.model单独指定一个更强的模型。另外identifierPolicy设成off时,一些工具调用 ID 会被丢掉,如果后续任务依赖这些 ID 做关联,就会出问题,这种情况保持strict。
问题三:压缩后请求报错或重试。自动压缩触发时,OpenClaw 可能用压缩后的上下文重试原始请求。如果重试还失败,多半是压缩后的上下文仍然超限,说明targetTokens相对窗口还是太大。把targetTokens降到窗口的 20% 以下试试。
问题四:会话感觉没救,想彻底重来。用/new或/reset启动一个新会话 ID。这两个命令会开新会话,旧会话的 JSONL 还在,但不再参与当前上下文。适合任务方向已经跑偏、压缩也救不回来的情况。
问题五:OpenAI 服务端压缩和本地压缩冲突。OpenClaw 支持兼容 OpenAI 的模型使用服务端压缩提示,这跟本地压缩是分开的,可以同时跑。本地压缩是 OpenClaw 生成摘要写 JSONL;服务端压缩是 OpenAI 在提供者一侧压。如果你发现压缩行为不符合预期,检查一下是不是两边都在动。服务端压缩需要启用store和context_management,具体看 provider 配置。
6. 长任务稳定运行的建议与接入入口
把压缩配好之后,长会话的稳定性会有明显提升。我的习惯是:主模型用能力强的,压缩摘要模型单独指定一个同级别或更强的,threshold设 0.85,targetTokens设窗口的 25% 左右。跑长任务时偶尔敲一次/compact手动清一下,比等自动触发更可控。
如果你还没接好模型,可以从 TaoToken 的模型对话页先试一下目标模型的表现:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。确认模型能力符合预期后,再去 API Keys 页面生成 Key 填进 OpenClaw:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,里面有 provider/model-id 的完整格式说明。
长期跑编码类 Agent 任务的话,Coding Plan 会更省心,额度模型和压缩策略的配合也更顺:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。Claude Code 相关的接入配置可以参考 https://taotoken.net/claudecode-anthropic?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,里面有针对 Anthropic 系模型的参数覆盖说明。
最后留一个我常用的检查动作:每次改完压缩配置,先跑一个短会话手动/compact一次,确认摘要能正常生成并落盘,再上长任务。这样能把配置问题挡在真正干活之前。