1. OpenClaw Memory 里 Flush 和 Compact 到底差在哪OpenClaw 的 Memory Flush 和 Compact 是两套完全不同的上下文管理流程很多人第一次接触时会把它们当成同一件事结果调参时改错地方要么频繁触发压缩导致对话被截断要么该刷新时没刷新Agent 转头就忘了前面聊过什么。简单说Memory Flush 是预防性动作由 Gateway 在会话接近阈值时注入一条静默提示让 Agent 自己判断哪些内容值得写进当天的记忆文件Compact 是兜底动作由 Pi runtime 在上下文真的超限或溢出时把旧对话压成摘要写回 JSONL。一个负责“提前存”一个负责“事后压”。这套机制适合谁如果你在用 OpenClaw 跑长期编码助手、客服机器人或者任何需要跨轮次记住项目规则的 Agent就一定会碰到这两个流程。它们的触发条件、执行顺序和资源开销差异很大选错了不仅浪费 token还可能让 Agent 的记忆出现断层。我试过在同一个会话里分别观察两条流程的日志发现 Flush 的 token 开销集中在一次额外的模型调用而 Compact 的开销在于摘要生成和上下文重建两者叠加时对响应延迟的影响更明显。要复现对比环境你需要一个统一的 API 通道来稳定调用模型否则不同 Key 的限流和路由差异会干扰观测。TaoToken 的统一 Key 在这里的作用是你不需要为每个模型单独配 KeyBase URL 和 Model ID 统一走一个入口这样 Flush 和 Compact 触发的模型调用在计费和延迟上更容易对齐。下面我会给出可复制的配置片段、逐步验证动作以及两条流程在真实报错下的排查方法。2. TaoToken 统一 Key 接入 OpenClaw 的前置配置在开始对比之前先把 OpenClaw 的模型调用通道切到 TaoToken。OpenClaw 的模型配置集中在openclaw.json里你需要改的是 provider 的 Base URL 和 API Key。TaoToken 的 API 地址是https://taotoken.net/api注意这里不加任何查询参数保持干净。Key 在控制台的 API Keys 页面生成生成后复制到配置文件里。先看一个最小可用的 provider 配置片段路径是~/.openclaw/openclaw.json{ providers: { taotoken: { baseUrl: https://taotoken.net/api, apiKey: sk-你的TaoTokenKey, models: { claude-sonnet: { id: claude-sonnet-4-20250514, contextWindow: 200000 }, gpt-4o: { id: gpt-4o, contextWindow: 128000 } } } }, agents: { defaults: { model: taotoken/claude-sonnet } } }这里有三件套必须写全Base URL 是https://taotoken.net/apiKey 是你生成的sk-开头字符串Model ID 是你要对比的模型标识。如果你用 Claude Code 做编码场景Model ID 可以填claude-sonnet-4-20250514如果做通用对话gpt-4o也可以。注意contextWindow这个字段要和模型实际窗口一致因为 Flush 的触发阈值计算直接依赖它。配置改完后用一条命令验证通道是否通curl -s https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer sk-你的TaoTokenKey \ -H Content-Type: application/json \ -d { model: claude-sonnet-4-20250514, messages: [{role: user, content: reply with OK}], max_tokens: 10 }如果返回里choices[0].message.content包含 OK说明通道正常。这一步很关键因为后面 Flush 和 Compact 都会触发模型调用如果通道本身不稳定你观测到的延迟和失败就分不清是流程问题还是网络问题。TaoToken 的接入文档里有更完整的参数说明遇到 401 或 model not found 时可以先对照文档检查 Key 和 Model ID 的拼写。3. 可复制的 Flush 与 Compact 对比配置片段现在进入核心部分把 Flush 和 Compact 的参数分开配置方便你逐项对比。OpenClaw 的压缩和刷新参数都在agents.defaults.compaction下面我把它拆成两块来看。先看 Memory Flush 的配置路径同样是~/.openclaw/openclaw.json{ agents: { defaults: { compaction: { reserveTokensFloor: 20000, memoryFlush: { enabled: true, softThresholdTokens: 4000, systemPrompt: Session nearing compaction. Store durable memories now., prompt: Write any lasting notes to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store. } } } }, memory: { temporalDecay: { halfLifeDays: 30 } } }这里的触发阈值是contextWindow - reserveTokensFloor - softThresholdTokens。以 200k 窗口为例200000 - 20000 - 4000 176000也就是 contextTokens 超过 176k 时 Gateway 会触发 Flush。reserveTokensFloor是给模型留的思考空间softThresholdTokens是预防性缓冲。如果你把softThresholdTokens调大Flush 会更早触发但每次刷新的 token 开销也会增加。再看 Compact 的配置它没有单独的开关而是由 Pi runtime 在两条路径下自动触发。路径 A 是溢出兜底路径 B 是阈值维护。路径 B 的触发条件是contextTokens contextWindow - reserveTokens注意这里没有softThresholdTokens所以它比 Flush 的阈值更靠后。你可以通过调整reserveTokensFloor来间接影响两条流程的间距{ agents: { defaults: { compaction: { reserveTokensFloor: 20000 } } } }如果你想让 Flush 和 Compact 之间的间隔更大可以把softThresholdTokens从 4000 调到 8000这样 Flush 在 172k 就触发而 Compact 仍在 180k 触发中间有 8k 的缓冲。反过来如果你希望 Compact 更早介入就减小reserveTokensFloor但不要低于 20000否则模型可能没有足够空间生成摘要。还有一个容易忽略的配置是防抖参数它在messages.inbound下面{ messages: { inbound: { debounceMs: 2000, byChannel: { slack: 1500, discord: 1500 } } } }防抖时间影响的是消息合并频率间接影响 contextTokens 的增长速度。如果你在编辑器里高频保存触发对话debounceMs设太小会导致 Flush 频繁触发。1500 到 2000 毫秒是比较平衡的区间。4. 逐步验证观察两条流程的触发与执行结果配置写好后你需要一套可复现的验证动作来观察 Flush 和 Compact 的实际行为。我建议用一个脚本模拟长对话逐步把 contextTokens 推高同时在另一个终端盯日志。第一步启动 OpenClaw 并打开 debug 日志openclaw gateway --log-level debug第二步在另一个终端发起一个会话然后连续发送长消息。你可以用下面的脚本快速灌入内容for i in $(seq 1 50); do openclaw message send --session test-flush \ --text 这是第 $i 轮测试消息用于推高 contextTokens。$(head -c 2000 /dev/urandom | base64 | head -c 1500) done第三步观察日志里出现的关键标记。当 contextTokens 接近 176k 时你应该看到 Gateway 注入静默提示的记录类似[gateway] memory flush triggered, injecting silent turn [gateway] memoryFlushAt updated in sessions.json同时检查~/.openclaw/workspace/memory/下是否生成了当天的YYYY-MM-DD.md文件内容里应该有 Agent 写入的笔记。如果 Agent 判断没有值得存的内容它会回复 NO_REPLY日志里会显示NO_REPLY intercepted。第四步继续灌入消息直到 contextTokens 超过 180k。这时 Pi runtime 会触发 Compact 路径 B日志里会出现[pi] threshold maintenance triggered, compacting session [pi] compaction entry appended to JSONL [pi] sessions.json compactionCount updated用户侧会看到一条Auto-compaction complete的通知。此时检查~/.openclaw/agents/agentId/sessions/sessionKey.jsonl文件末尾应该多了一条type: compaction的摘要 entry旧的 messages 被标记为compacted: true。第五步对比两条流程的资源开销。你可以在日志里搜索 token 使用量Flush 的开销主要是一次额外的模型调用用于生成笔记Compact 的开销是摘要生成加上上下文重建。实测下来在 200k 窗口下Flush 单次大约消耗 2k 到 4k tokenCompact 单次大约消耗 6k 到 10k token具体取决于对话长度和摘要模型的输出长度。如果你想更精确地对比可以在 TaoToken 控制台的用量页面查看每次调用的 token 消耗按时间戳对齐日志里的触发点。这样你能清楚看到哪条流程在哪个时间点花了多少 token。5. 常见报错排查401、local proxy failed 与 reading choices在对比过程中你可能会遇到几类典型报错。我把它们和对应的排查动作列出来方便你快速定位。第一类是 401 Unauthorized。这通常出现在 Flush 或 Compact 触发模型调用时说明 TaoToken 的 Key 无效或过期。检查openclaw.json里的apiKey字段是否以sk-开头有没有多余空格。如果 Key 刚生成确认控制台里该 Key 的状态是启用。另外注意 Base URL 必须是https://taotoken.net/api不要写成带/v1的路径OpenClaw 会自己拼接。第二类是local proxy failed。这个报错说明 OpenClaw 在尝试通过本地代理转发请求时失败了。检查你的环境变量里有没有残留的HTTP_PROXY或HTTPS_PROXY设置如果有就清掉。OpenClaw 的 provider 配置里也不要填proxy字段直接走 TaoToken 的 Base URL 即可。如果你在公司网络下确认防火墙没有拦截taotoken.net的 443 端口。第三类是reading choices相关的解析错误通常长这样Error: cannot read property choices of undefined这说明模型返回的响应结构不符合预期常见原因是 Model ID 写错了或者请求体里缺少messages字段。检查openclaw.json里的models配置确认id字段和 TaoToken 支持的模型标识一致。如果你用的是 Claude Code 场景Model ID 要填claude-sonnet-4-20250514这类完整标识不要简写。第四类是 OAuth 相关的报错比如OAuth token expired。OpenClaw 本身不走 OAuth但如果你在 Claude Code 里配置了 OAuth 通道又同时想用 TaoToken 的 Key就会冲突。解决办法是在 Claude Code 的settings.json里把 provider 切到 TaoToken三件套写全{ provider: taotoken, baseUrl: https://taotoken.net/api, apiKey: sk-你的TaoTokenKey, model: claude-sonnet-4-20250514 }如果你用 Cline 或 Codex配置逻辑类似关键是 Base URL、Key、Model ID 三件套不能缺。Cline 的 MCP 配置里如果引用了本地模型也要确认没有和 TaoToken 的通道冲突。第五类是 Flush 不触发。检查workspaceAccess是不是ro或none只读模式下 Flush 会被跳过。另外 CLI backend 的非 embedded Pi session 也不走 Flush 逻辑确认你用的是 embedded 模式。如果memoryFlushCompactionCount在当前压缩周期已经大于 0Flush 也会跳过这是防重复机制。6. 选 Flush 还是 Compact按会话规模做决策回到最初的问题不同会话规模下该选哪条流程我的建议是两者不是二选一而是配合使用但你可以根据场景调整它们的触发时机。对于短会话比如单次问答或几分钟的调试对话contextTokens 很难超过 100kFlush 和 Compact 都不会触发你不需要额外配置。对于中等会话比如一两个小时的编码辅助Flush 会在 176k 左右触发一次把关键决策写进当天记忆文件Compact 可能在 180k 后触发压掉旧对话。这个规模下你可以把softThresholdTokens保持在 4000让 Flush 和 Compact 之间有足够的缓冲。对于长会话比如跨天的项目跟踪contextTokens 会反复逼近阈值Flush 可能触发多次Compact 也会多次执行。这时你需要关注memoryFlushCompactionCount的增长如果每个压缩周期都触发 Flush说明softThresholdTokens设得太小可以调到 6000 到 8000。同时检查halfLifeDays如果项目周期长可以调到 60 天让记忆衰减更慢。如果你更看重记忆完整性就偏向 Flush把softThresholdTokens调大让 Agent 更早存笔记如果你更看重响应速度就偏向 Compact把reserveTokensFloor保持在 20000让压缩在必要时才介入。实测下来大多数编码场景用默认配置就能跑得不错只有在对话特别长或模型窗口特别小的时候才需要微调。最后提醒一点Flush 写入的是memory/YYYY-MM-DD.mdCompact 写入的是 session JSONL两者的数据用途不同。Flush 的内容会被后续的 memorySearch 检索到Compact 的摘要只影响当前会话的上下文重建。所以如果你发现 Agent 在新会话里记不住旧事先检查 Flush 有没有正常写入记忆文件而不是去调 Compact 的参数。
阅读完成 · 觉得有帮助?