Pi Agent 101|06|Context Compaction
Pi 把 compaction 设计成 session tree 上的结构性 checkpoint,而不是简单删除旧消息。
模型的“记忆窗口”有限,长任务迟早装不下。
最粗暴的办法是删掉旧消息。Pi 没这么做。它更像在长篇笔记里夹一张摘要卡:前面的细节还在档案里,但这一轮模型先看摘要和最近发生的事。
长任务一定会遇到上下文上限。最直接的做法是删旧消息,但这会破坏审计历史,也容易切断 tool call / tool result 结构。Pi 的 compaction 更像一次结构性 checkpoint:在 session tree 里追加一条 compaction entry,完整历史保留,当前模型上下文变短。

这张图要表达的是 checkpoint,而不是删除。上下文变长后,runtime 不能简单把旧消息裁掉;它要在安全位置生成摘要,保留关键事实,再让后续上下文从这个 checkpoint 继续。
安全位置很重要。不能留下 tool result 却切掉对应的 tool call,也不能丢掉当前文件工作集、失败测试、已经尝试过的方案和用户明确要求。压缩不是省 token 的小技巧,而是长任务的状态管理。
本文结构
模型的上下文窗口不是无限的。任务越长,历史越多,最后一定会放不下。压缩不是删除历史,而是把早期过程整理成一份能继续工作的摘要,再保留最近最重要的原文。它像把一大摞工作记录整理成“项目进展卡”。
这一篇按机制展开:先看核心问题,再看运行路径、边界、设计取舍,以及它和 OpenClaw 的对应关系。
阅读目标
- 理解 compaction entry 如何改变当前模型视图
- 区分阈值压缩和 overflow 恢复
- 看清为什么压缩不能只按 token 截断
为什么需要压缩
这张图说明:压缩不是优化小技巧,而是长任务继续运行的必要条件。
Pi 的 compaction 包含 summary、firstKeptEntryId、tokensBefore、details、fromHook 等信息。恢复上下文时,SessionManager 会把最新 compaction 转成一条 compactionSummary message,然后从 firstKeptEntryId 开始保留近期消息。
这意味着原始 session 文件没有被删除;只是当前 LLM context 不再包含完整旧历史。
主流 Agent 产品里的 Context Compaction
你用 Claude Code、Codex CLI 或 Cursor 做长任务时,都会遇到上下文压力:文件读多了,测试跑多了,工具输出堆多了,模型窗口迟早不够用。
产品通常不会把所有旧内容永远塞给模型。它们会保留一部分最近上下文,把更早的过程压成摘要。OpenClaw 这类长会话系统也一样:不同 channel 里持续对话,agent 又不断调用工具,最后一定需要 compaction 或类似机制。
修测试时压缩怎么发生
这张图说明:摘要要保留可行动状态,而不是只写聊天大意。
修复失败测试跑久了,很容易把上下文撑满:读过的文件、失败日志、修改记录、重跑结果都在堆。模型下一轮真正需要的,不是从头到尾的每一行输出,而是“改过哪些文件、最近一次失败是什么、哪些假设已经排除”。
Compaction 要做的就是这件事。旧过程还留在 session 里,但给模型看的工作视图变短。尤其是测试命令和结果,不能把 tool call 留下、tool result 切掉;否则模型会看到一段断掉的现场记录。
压缩触发:预防与恢复
这张图说明:压缩既可以提前预防,也可以在上下文溢出后恢复。
Pi 有两类自动压缩。第一类是阈值压缩:当上下文 token 接近窗口上限时,先压缩,避免下一轮失败。第二类是 overflow 恢复:provider 已经报上下文溢出,runtime 压缩后自动 retry,但要有保护,避免无限重试。
这很适合迁移:context overflow 不是普通异常,而是 agent runtime 的控制信号。
Cut point 不能随便选
这张图说明:切点不能破坏工具调用与结果的配对关系。
压缩不能只按 token 砍一刀。tool result 必须跟在对应 tool call 后面;一个 turn 中间被切开时,要生成 turn prefix summary,避免保留的后半段失去上下文。
Compaction summary 通常不是纯规则拼接出来的。Pi 会准备一段待压缩历史,调用模型生成自然语言摘要,同时用规则方式跟踪读过和改过的文件,把 read-files 和 modified-files 一类结构化工作集放进 summary。也就是说,压缩本身也会消耗一次模型调用、token 和时间。
这也是为什么 compaction 不能太频繁。好的策略要在“继续塞原始历史的成本”和“额外做一次 summary 的成本”之间取平衡。对 coding agent 来说,自然语言摘要负责保留推理脉络,结构化文件工作集负责保留可执行状态,两者缺一都容易漂。
如果 summary 生成失败,也不能把 session 带崩。可恢复的策略通常是:保留原始历史不动,记录一次 compaction failure,降低本轮上下文或提示用户手动处理;如果是 overflow recovery,则最多 retry 一次,避免在“溢出 -> 压缩失败 -> 再溢出”的循环里空转。
压缩之后,模型上下文会少掉很多原始细节:旧的完整对话、长命令输出、已经不重要的中间推理、重复的工具结果。保留下来的,是摘要、最近消息、仍然相关的文件工作集,以及不能破坏协议结构的 tool call / tool result 配对。
这最后一点很关键。压缩不能在任意 token 位置切一刀。如果留下一个 tool result,却切掉了对应的 tool call,模型下一轮看到的上下文就是坏的。好的 compaction 要像整理施工记录:可以省略废话,但不能把“谁下的命令”和“命令结果”拆散。
设计边界
如果自己做 harness,compaction 不应该等同于“删掉旧消息”。更好的方式是追加一个 checkpoint:记录摘要、保留哪些关键事实、从哪里继续,以及为什么压缩。这样既能控制上下文长度,也不会破坏审计历史。
压缩摘要应该保留什么
这张图说明:好摘要像项目交接卡,能让模型下一轮继续工作。
对 coding agent 来说,好的摘要不是“前面聊了很多,我们继续”。它应该保留任务目标、当前判断、关键文件、已经执行过的命令、失败原因、用户约束、未完成事项,以及哪些路径已经尝试过。
如果摘要太短,模型下一轮会重复犯错;如果摘要太长,压缩失去意义;如果摘要只保留自然语言判断,不保留文件工作集和工具结果,后续修复会失去抓手。
Compaction 需要可观测
用户通常看不到完整 prompt,但应该能知道系统什么时候压缩过、为什么压缩、压缩后是否继续成功。否则长任务中出现奇怪行为时,用户无法判断是模型变差、工具失败,还是上下文被压缩坏了。
这也是为什么 compaction 和 Observability 有关系。压缩动作本身应该成为 session 里的一个事件,而不是静默发生的内部优化。
设计取舍
历史处理。Pi 的选择是:append compaction entry。可复用的原则是:不要删除审计历史。
触发策略。Pi 的选择是:threshold + overflow。可复用的原则是:预防性和恢复性压缩分开。
Cut point。Pi 的选择是:避免破坏 tool 协议。可复用的原则是:压缩要维护消息结构不变量。
Summary。Pi 的选择是:自然语言 + 文件工作集。可复用的原则是:coding agent 摘要要保留结构化状态。
扩展。Pi 的选择是:session_before_compact hook。可复用的原则是:领域压缩可由扩展接管。
OpenClaw 的对应问题
OpenClaw 里也会遇到类似问题:这一篇对应长会话的 token 压力和 transcript 压缩。OpenClaw 场景里,用户可能通过不同 channel 长时间对话,agent 还会调用工具。不能简单删历史,需要把旧过程压成仍然可用的摘要。
实现里的压缩边界
Pi 的压缩不是把旧消息删掉,而是在当前分支上追加一条 checkpoint。这个 checkpoint 记录旧上下文摘要、压缩前 token 情况、从哪条记录开始保留原文,以及文件读写等关键细节。
后续构造模型上下文时,Pi 会先放入压缩摘要,再放入近期保留的原始消息。旧历史仍然在 session 里,但不再完整进入模型窗口。也就是说,压缩改变的是“模型这一轮看到什么”,不是删除历史。
切点也不能随便选。工具调用和工具结果有协议关系,不能留下 tool result 却切掉对应 tool call。Pi 会从当前路径尾部向前找合适位置,尽量保留近期内容,同时避免破坏消息结构。
压缩摘要不是普通总结
对 coding agent 来说,好的压缩摘要要保留状态,而不仅是聊天大意。它应该告诉模型:目标是什么,用户约束是什么,已经读过哪些文件,修改过哪些文件,测试失败在哪里,尝试过哪些方案,接下来应该从哪里继续。
如果摘要只写“我们正在修 bug”,模型会失去现场;如果摘要保留太多细节,又省不了上下文。Context Compaction 真正考验的是:如何把长任务压缩成下一轮仍然可行动的工作状态。
这也是它和 Session Tree 的关系:树保存完整历史,compaction 改变当前路径的模型视图。
如何判断
第一,压缩发生在任务前、中、后哪个位置。不同位置对应不同风险:任务前可以预防溢出,任务中要小心破坏 tool protocol,任务后要能继续恢复。
第二,摘要保留的是结论还是状态。coding agent 更需要状态:当前文件、失败测试、已尝试方案、未完成目标和用户约束。
第三,压缩动作是否可见。用户不一定要读完整摘要,但应该知道系统压缩过,以及压缩是否改变了后续运行。
一句话总结
压缩不是删历史,而是给模型换一份更短的工作摘要。
小结
Pi 的 Context Compaction 不是“把旧对话总结一下”这么简单。它是 session tree 上的 checkpoint 机制:完整历史继续存在,模型视图被重建,结构化工作集被保留,overflow 可以被恢复。