LLM 的上下文窗口是硬性上限,长对话一旦逼近该限制,Agent 会面临记忆丢失、推理质量下降和成本飙升三重风险。OpenClaw 通过分层策略应对:短期用会话修剪(Pruning)削减旧工具结果,中期用压缩(Compaction)将早期对话摘要化,长期用 Memory 文件和向量检索跨会话持久化关键信息。三者各司其职,组合使用才能让 Agent 在数百轮对话后仍保持连贯。
一、长对话为什么会出问题
Context Window 通常包含三部分:系统提示词、对话历史(含工具调用结果)、Skills 提示词。系统提示词和 Skills 是固定内容,真正会膨胀的是对话历史。
| 问题 | 表现 | 根因 |
|---|---|---|
| Token 超限 | 报错 context length exceeded |
对话历史累积超过模型窗口 |
| 记忆漂移 | 早期偏好被遗忘、决策被忽略 | 旧消息被新消息挤出上下文 |
| 性能下降 | 延迟增加、成本飙升 | 每次请求发送超长上下文 |
| 推理走神 | 抓不住重点、产生幻觉 | 无关信息占比过高,干扰模型注意力 |
研究表明,当 Prompt 中无关信息占比超过 70% 时,LLM 的准确率可能下降 30% 以上。
二、OpenClaw 的分层上下文管理策略
OpenClaw 将上下文管理拆为三个层次,从轻到重依次介入。
2.1 第一层:会话修剪(Session Pruning)
修剪是最轻量的手段,在每次调用 LLM 之前从上下文中移除旧的工具结果,不改写正常对话文本。它以 cache-ttl 模式运行,受时间检查和上下文大小双重控制:
- 等待缓存 TTL 过期(默认 5 分钟),到期前完全跳过以复用提示缓存;
- TTL 到期后估算上下文总大小占比,低于
softTrimRatio(默认 0.3)则跳过; - 对超大工具结果做软修剪:保留开头和结尾各 1500 字符,中间插入省略号;
- 若仍超过
hardClearRatio(默认 0.5),将旧工具结果替换为占位符[Old tool result content cleared]。
修剪仅在内存中进行,不修改磁盘上的会话记录,完整历史始终保留。最近 3 个助手轮次和会话首条用户消息之前的内容绝不会被修剪。
2.2 第二层:压缩(Compaction)
当修剪不足以缓解压力,或对话接近上下文窗口上限时,Compaction 介入。它将较早的对话轮次汇总为一个精简条目,保存到会话转录中,近期消息保持完整。
{
"agents": {
"defaults": {
"compaction": {
"enabled": true,
"mode": "safeguard",
"keepRecentTokens": 20000,
"identifierPolicy": "strict"
}
}
}
}
Compaction 的关键设计是工具调用配对保留:选择拆分点时,如果落在工具块内部,OpenClaw 会移动边界,确保助手工具调用与其对应的 toolResult 保持在一起。完整对话历史仍保存在磁盘上,压缩只改变模型在下一轮看到的内容。
2.3 第三层:跨会话记忆(Memory)
当对话实在太长、压缩也不够用时,跨会话记忆系统接管。OpenClaw 的多层记忆架构如下:
| 记忆层 | 存储位置 | 生命周期 | 典型内容 |
|---|---|---|---|
| 短期记忆 | 内存(RAM) | 当前会话 | 系统提示词、近期消息、工具结果 |
| 中期记忆 | 磁盘(SQLite / Redis) | 跨会话 | 每日笔记、用户偏好、事实摘要 |
| 长期记忆 | Memory-Wiki + 向量索引 | 永久 | 项目文档、架构决策、知识库 |
压缩前,OpenClaw 会自动提醒 Agent 将重要笔记保存到记忆文件。MEMORY.md 作为策展的长期记忆,在每次新会话启动时加载。每日笔记(memory/YYYY-MM-DD.md)可按需检索,/new 或 /reset 后会重新注入最近笔记。
三、配置与实践
3.1 上下文窗口配置
{
"agents": {
"my-agent": {
"context_window": 8192,
"max_turns": 50,
"summary_after": 20
}
}
}
当对话超过 max_turns 时,OpenClaw 要么截断最旧消息,要么在设置了 summary_after 时将较早的轮次摘要化。摘要使用 Agent 自身模型完成,保留关键信息。
3.2 自动压缩触发
session:
compact:
autoTrigger:
enabled: true
tokenThreshold: 100000 # 超过 100K Token 自动压缩
turnThreshold: 50 # 或超过 50 轮
strategy: "balanced" # aggressive | balanced | conservative
preserveRecent: 5 # 保留最近 5 轮原文
系统实时监控 Token 用量,设定水位线(如总窗口 20 万、预留 2 万缓冲,超过 18 万即触发)。一旦触及水位线,系统自动对早期对话历史做摘要提取,生成高信息密度的 Summary。
3.3 溢出错误自动恢复
OpenClaw 匹配数十种提供商特定的溢出错误字符串,识别后自动压缩并重试:
| 提供商 | 常见溢出错误模式 |
|---|---|
| Anthropic | request_too_large |
| OpenAI | context length exceeded |
| Bedrock | input token count exceeds the maximum number of input tokens |
| Gemini | input is too long for the model |
| Ollama | ollama error: context length exceeded |
模型返回溢出错误后,OpenClaw 先压缩历史再重试该轮请求,用户无感知。
四、修剪与压缩的分工
两者面向不同场景,相辅相成:
| 维度 | 会话修剪(Pruning) | 压缩(Compaction) |
|---|---|---|
| 作用对象 | 旧工具结果 | 整个对话历史 |
| 持久化 | 否(仅内存,按请求执行) | 是(保存到会话转录) |
| 触发方式 | 缓存 TTL 过期 + 上下文占比 | 接近窗口上限或溢出错误 |
| 信息损失 | 低(只清工具输出) | 中(摘要压缩对话文本) |
修剪在各次压缩周期之间保持工具输出精简,减少压缩频率。压缩则在修剪不够用时做更深度的瘦身。如果两者都不够,就该考虑 /new 开新会话或将关键信息写入 Memory-Wiki 了。
五、长会话优化的最佳实践
将三层策略组合使用效果最佳:
- 启用自动修剪,减少旧工具结果的缓存开销(尤其配合 Anthropic 提示缓存时);
- 设置合理的自动压缩阈值,在 Token 用量到达 80%–90% 时触发;
- 关键决策节点用
/checkpoint创建检查点,方便回溯; - 重要信息主动写入 Memory-Wiki 或每日笔记,不依赖对话上下文记忆;
- 对话过长时用
/compact手动压缩,并可附加指令引导摘要重点。
# 查看会话健康度
openclaw session health <session-id>
# 输出示例:
# Token usage: 180K / 200K (90%) — 建议 /compact
常见问题(FAQ)
Q1:修剪和压缩有什么区别?
修剪只裁剪旧工具结果且不持久化;压缩摘要整段对话并保存到转录。
Q2:自动压缩会丢失重要信息吗?
压缩前会提醒 Agent 保存笔记到记忆文件,标识符默认严格保留。
Q3:对话超长压缩也不够用怎么办?
用 /new 开新会话,关键信息提前写入 Memory-Wiki 持久化。