Pi Agent Compaction:长任务不爆上下文的关键机制
做 Coding Agent 最怕什么?
不是它不会写代码,而是一个长任务做到一半,前面的背景、约束、文件线索被上下文窗口挤掉。
Pi Agent 的 Compaction 就是为这个问题准备的:把旧对话压成结构化摘要,同时尽量保留最近正在推进的工作。
它不是简单“清空历史”,更像给长任务做一次可继续的工程交接。
先说结论
- 压缩的目标是释放上下文空间,同时保留任务目标、约束、进度、关键决策和文件线索。
- Pi 支持自动压缩,也支持手动执行
/compact [instructions],可以用说明词聚焦摘要重点。 - 默认会预留 16384 tokens 给模型回复,并保留最近约 20000 tokens 不被摘要。
/tree分支切换时还有 Branch Summarization,用来把离开的分支总结到新位置。- 扩展可以拦截压缩事件,取消压缩或提供自定义摘要。
背景:为什么长任务一定会遇到压缩
LLM 有上下文窗口限制。
当一次 Agent 会话越来越长,里面会堆很多内容:用户需求、模型回复、工具调用、命令输出、读过的文件、改过的文件。
如果不处理,后面的模型调用要么塞不进去,要么把很早但很重要的工程背景挤掉。
Pi 的做法不是把旧内容直接丢掉,而是把较早的消息总结成一个 CompactionEntry,后续模型看到的是:
| |
也就是说,旧上下文被浓缩成摘要,最近的工作现场继续保留。
关键点 1:什么时候会触发 Compaction
自动压缩的触发条件可以记成这个公式:
| |
reserveTokens 默认是 16384,意思是给模型接下来的回复留出空间。
如果你不想等自动触发,也可以手动压缩:
| |
还可以加说明,让摘要更偏向你关心的方向:
| |
这个适合在长重构、排障、代码审查中主动“收口”:先让 Agent 把已经发生的事整理清楚,再继续往下做。
关键点 2:它到底压缩了什么
Pi 会从最新消息往回看,累计 token 估算,直到达到 keepRecentTokens。
默认 keepRecentTokens 是 20000,也就是最近约 2 万 tokens 会尽量留下来,不进入摘要。
压缩流程大致是:
- 找到切分点:决定哪些旧消息要总结,哪些近期消息要保留。
- 抽取旧消息:从上一次保留边界或会话开头开始收集。
- 生成结构化摘要:必要时把上一次摘要也作为迭代上下文传入。
- 追加
CompactionEntry:记录摘要、firstKeptEntryId和压缩前 token 数。 - 重新加载会话:后续上下文变成摘要加保留消息。
这里最重要的是 firstKeptEntryId。
它告诉 Pi:从哪条消息开始仍然作为原始消息发送给模型。更早的内容则由摘要接管。
关键点 3:不是随便从中间切一刀
Pi 正常会按 turn 边界切。
一个 turn 从用户消息开始,包含后续 assistant 回复和工具调用,直到下一条用户消息。
这样做是为了避免把“工具调用”和“工具结果”拆散。
Pi 文档里明确提到:有效切分点包括 user message、assistant message、bash execution message、custom message 和 branch summary;不会切在 tool result 上。
如果单个 turn 自己就超过 keepRecentTokens,Pi 会进入 split turn 场景:在这个巨大 turn 的 assistant message 处切分,并分别总结历史上下文和这个 turn 的前半段,再合并摘要。
这对一次性超大任务很关键,例如:
| |
这种情况下,Pi 不是强行等待下一个用户消息,而是有专门的 split turn 处理。
关键点 4:摘要格式是工程交接单
Pi 的 compaction 和 branch summarization 使用同一套结构化摘要格式。
它不是随便写一段“前情提要”,而是会围绕这些信息组织:
- Goal:用户要达成什么目标
- Constraints & Preferences:约束和偏好
- Progress:已完成、进行中、阻塞项
- Key Decisions:关键决策和理由
- Next Steps:下一步怎么做
- Critical Context:继续任务必须知道的信息
- read-files / modified-files:读过和改过的文件
这也是为什么 Compaction 对 Coding Agent 特别重要。
真正有价值的不是“聊天记录还在”,而是下一轮模型还能知道:任务目标是什么、哪些坑已经踩过、哪些文件不能乱动、接下来该做什么。
关键点 5:/tree 切分支时也会总结
Pi Sessions 是树状结构。
当你用 /tree 从一个分支切到另一个分支时,Pi 会询问是否总结你正在离开的分支。
这个机制叫 Branch Summarization。
它会找到旧位置和新位置的共同祖先,收集旧分支上被离开的那些 entries,生成摘要,并把这段上下文注入到切换后的分支语境里。
可以这样理解:
flowchart TD A[共同祖先] --> B[旧分支探索] B --> C[旧分支结果] A --> D[目标分支] C --> E[旧分支摘要]
如果你让 Agent 试了方案 A,后来切回去走方案 B,Branch Summarization 能把方案 A 的关键发现带过去,避免“换分支就失忆”。
可以直接照抄的配置清单
Compaction 可以配置在全局或项目级设置里:
| |
最小配置示例:
| |
几个使用建议:
- 长任务默认保持自动压缩开启,不要等上下文快炸了再处理。
- 关键节点主动用
/compact <instructions>,让摘要偏向文件、风险和下一步。 - 探索分支时配合
/tree,切走前让 Pi 总结离开的分支。 - 如果团队有特殊摘要要求,可以通过扩展监听
session_before_compact或session_before_tree。 - 如果关闭自动压缩,仍然可以手动执行
/compact。
最后总结
Pi Agent 的 Compaction 可以理解成:给长会话做“可继续的上下文整理”。
它保留最近工作现场,把更早内容压成结构化摘要,并记录读过、改过的文件。
对短对话来说,你可能感受不明显;但对重构、排障、长时间代码审查这类任务,它直接决定 Agent 能不能稳定接着做。
如果你已经在用 Pi Agent,建议把 /compact 和 /tree 分支摘要一起学,它们解决的是同一个核心问题:让复杂工程任务不要在上下文里断线。
参考资料
话题标签
#PiAgent #CodingAgent #AI编程 #上下文工程 #程序员效率