Context Paging:Compact、外部化、恢复与 Memory 生命周期
长程 Agent 的限制不只来自 context window 大小。窗口里装了什么、旧材料怎样退出、compact 后哪些内容恢复、外部记忆何时失效,同样决定任务能否连续推进。
操作系统用 paging 把有限内存接到更大的外部存储。Agent 的上下文管理也在形成类似结构:当前窗口是工作集,文件、索引和 memory 是外部状态,compact 负责压缩历史,检索和恢复机制负责按需换入。Prompt cache 则位于另一条轴上,影响相同前缀的成本和延迟,却不减少它占用的 context window。
Context Paging 管理的是工作集
长窗口解决“能否放入”,没有保证“能否稳定使用”。《Lost in the Middle》显示,模型利用长上下文中的信息时会受到位置影响。Coding 会话还会积累失败命令、过时文件内容、被否决方案和大段日志。即使它们仍在窗口内,也未必属于当前任务需要的工作集。
Context paging 的目标不是保存所有历史,而是在每次推理前组织一个可执行工作集:
- 当前目标与完成条件;
- 仍然有效的约束;
- 关键证据及其来源;
- 修改状态与未通过的验证;
- 下一步动作和恢复入口。
已完成且可从外部复现的轨迹可以退出窗口。尚未完成、无法轻易重建或会影响安全边界的信息需要保留。
组件视角:换入换出的职责分工
Context paging 不是一个 compact() 函数,而是一组相互独立的组件。
flowchart LR
I["Context Assembler<br/>system / tools / rules / skill listing"] --> W["Working Context"]
H["Message Store<br/>user / assistant / tool history"] --> W
S["External State<br/>repo / spec / logs / memory / index"] --> R["Selector / Retriever"]
R --> W
W --> C["Compactor"]
C --> H
C --> S
S --> G["Rehydrator"]
G --> W
P["Prompt Cache"] -. "复用相同前缀,不缩小窗口" .-> W
Context Assembler 负责启动时的 system、工具目录、项目规则和 Skill 目录。Message Store 保存会话轨迹。External State 保存可跨轮次或跨会话访问的材料。Selector 筛选本轮换入项。Compactor 把历史变成更短的状态。Rehydrator 在 compact 或恢复会话后重新注入必要材料。Prompt Cache 优化重复前缀的处理成本。
把“compact 后又加载了规则”笼统归因于摘要器,会掩盖实际的体积来源;把“命中 cache”理解成“这些 token 不在窗口里”,则会误判剩余容量。
运行时视角:一次 page in / page out
flowchart TB
A["外部世界:repo / docs / logs / memory"] --> B["选择 Select"]
B --> C["工作集:当前上下文窗口"]
C --> D["模型推理与工具调用"]
D --> E["结果 / 观察 / 失败"]
E --> F["写回 Write"]
F --> A
E --> G["压缩 Compress"]
G --> A
H["隔离 Isolate:子 Agent / 新会话"] --> C
Anthropic 在 context engineering 资料中使用 write、select、compress、isolate 四类动作。用 paging 术语翻译:
write:把状态 page out 到外部;select:从外部确定候选工作集;compress:把高体积轨迹转成低体积状态;isolate:让高噪声工作在独立窗口中完成,只返回结果。
这套循环还需要索引。常驻上下文只保存小目录、路径和语义钩子,完整内容留在文件或知识节点中。目录过大同样会挤占窗口;目录过小则可能让检索入口无法触发。Skill listing、工具命名空间和 repo map 都属于这一层的不同实现。
人的 context switching 是另一种成本
人的任务切换和模型的 token refill 不是同一机制,但存在相似的工程后果。APA 对 multitasking 的综述把切换引起的额外时间称为 switching costs。工程任务切换后,需要重新建立目标、进度、约束和下一步动作;交接材料质量会直接影响恢复时间。
因此,Agent 的 handoff artifact 同时服务两类消费者:下一次模型调用和下一位工程参与者。只保留聊天摘要不够,状态还应落到可验证的仓库事实、测试输出、issue、spec 或 commit 中。
Compact 会重写历史并保留工作状态
Compact 通常以摘要替换一段 message history,并保留或恢复由系统配置标记为必需的材料。它和 /clear 的语义不同:compact 继续当前任务,clear 清空 active context;旧 session 是否仍可恢复取决于产品的持久化机制。工作阶段与产品会话的边界不能只由这两个命令推断,详见《Agent 会话边界设计》。
一个可用的 compact 输出至少应包含:
- 未完成目标;
- 已修改文件;
- 关键约束和已否决路径;
- 尚未通过的测试;
- 下一步动作与验证命令;
- 必须回到外部读取的证据位置。
Compact 后的百分比不是压缩质量的单一指标。状态栏可能显示已用比例,也可能显示剩余比例;不同版本和工具的口径不能混用。Claude Code 可以通过 /context 查看当前分类占用,比凭百分比猜测更可靠。
压缩后的占用可以拆成:
1 | |
未完成任务越复杂,摘要下限越高。项目规则、Skill 和工具目录越大,固定或恢复基线越高。追求一个固定的“compact 后应降到 0%”没有通用意义。
Claude Code 当前公开的恢复契约
以下内容来自 2026 年 7 月 17 日访问的 Claude Code 公开文档。它描述的是当时的产品合同,不代表更早版本,也不应外推到其他 coding agent。
| 机制 | Compact 后行为 |
|---|---|
| System prompt 与 output style | 不属于 message history,保持不变 |
项目根 CLAUDE.md 与 unscoped rules |
从磁盘重新注入 |
| Auto memory | 从磁盘重新注入 |
带 paths: frontmatter 的规则 |
暂时丢失,直到再次读取匹配文件 |
子目录中的嵌套 CLAUDE.md |
暂时丢失,直到再次读取该目录下文件 |
| 已调用的 Skill body | 重新注入;每个 Skill 最多保留前 5,000 token |
| 所有恢复的 Skill body | 合计预算 25,000 token;优先最近调用,较旧 Skill 可整体丢弃 |
| Hooks | 以代码形式在生命周期事件运行,本身不是常驻上下文 |
5,000 / 25,000 是当前 Claude Code 公布的具体预算。公开 changelog 没有给出这份合同首次出现的明确版本,因此只能写“当前公开行为”,不能把它标成某个未经证实的历史版本新增能力。
文档还说明,Skill 截断保留文件开头。高优先级指令应位于 SKILL.md 前部。多个大 Skill 在同一会话中使用后,较旧 Skill 可能在 compact 后完全不再附着;需要完整正文时应重新调用。
其他工具的恢复预算:公开信息不足就标 unknown
各类 coding agent 普遍具备 session persistence、规则文件、摘要或 memory,但公开文档的粒度差异很大。以下项目若没有官方合同,就不应根据界面现象或类比补齐:
| 问题 | Claude Code 当前公开状态 | 其他产品的默认结论 |
|---|---|---|
| 单个 Skill compact 后恢复上限 | 5,000 token | unknown |
| 所有 Skill 合计恢复上限 | 25,000 token | unknown |
| Skill 淘汰顺序 | 最近调用优先,较旧先丢弃 | unknown |
| 项目规则是否从磁盘自动重注入 | 根级与 unscoped rules 会 | 逐产品查证 |
| path-scoped 规则何时重新加载 | 再次读取匹配文件时 | 逐产品查证 |
| hooks 是否直接构成常驻上下文 | 否;hooks 是代码 | 逐产品查证 |
“unknown”不是“没有能力”。它只表示缺少可引用的公开合同或本地 trace。要做横向比较,需要固定版本并采集 compact 前后的实际 context 分类、请求结构和恢复日志。
Prompt Cache 与窗口占用是两条轴
无状态 API 或 agent harness 通常会在新请求中携带有效上下文。逻辑上重复携带,不等于每次都按普通输入价格结算。
以 Anthropic prompt caching 为例,相同前缀在 TTL 和断点条件满足时可以进入 cache read;新增或变化部分进入 cache write 或未缓存输入。当前公开乘数是 5 分钟 cache write 为基础输入价的 1.25 倍、1 小时 cache write 为 2 倍、cache read 为 0.1 倍。具体账单应以响应 usage 为准。
缓存命中只改变处理成本与延迟,不改变以下事实:
- 旧内容仍占 context window;
- 模型仍能访问该内容;
- 噪声、过期假设和位置效应仍存在;
- compact、prune 或外化仍可能有必要。
因此,缓存优化和 context paging 不能互相替代。前者关心相同前缀怎样复用,后者关心哪些信息应该存在于工作集。
自定义恢复包可能让 Compact 后仍很满
公开 hooks 合同只说明事件和输入输出边界,不会自动产生“hot paths 恢复包”。PreCompact、PostCompact 可以被插件或自定义 harness 用来记录状态、更新外部文件或注入额外上下文;注入什么、注入多少属于具体实现。
如果某套自定义恢复逻辑在 compact 后重新读取状态文件、plan、长日志和多个 Skill,窗口可能迅速回升。此时不能把问题归因于 Claude Code 默认 compact。应把日志拆成几类:
1 | |
治理重点在恢复层:
- 保留指针和摘要,不自动注入大段原文;
- 对重复回灌做幂等和去重;
- 为自动恢复设置 token 预算;
- 对状态文件和日志设置热度衰减或排除规则;
- 避免在恢复阶段读取含密钥的环境文件;
- 任务完成后切换新会话,不用连续 compact 维持旧任务。
图中的“回灌型 compact”是自定义 harness 场景,不是 Claude Code 默认行为的产品承诺。
Externalize 之后还需要 Memory 生命周期
把内容写到文件、向量库或数据库,只完成了 page out。可用的 memory 还需要完整生命周期:
stateDiagram-v2
[*] --> Capture: 生成候选记忆
Capture --> Index: 绑定来源、时间、作用域与检索键
Index --> Select: 按当前任务选择
Select --> PageIn: 注入工作集
PageIn --> Validate: 与 repo、测试或外部事实核验
Validate --> Refresh: 仍有效
Validate --> Demote: 过期、冲突或低价值
Refresh --> Index
Demote --> Archive
Archive --> [*]
每个阶段都解决不同风险:
- Capture 防止关键决策只留在易失会话中;
- Index 让后续任务能够找到它;
- Select 控制本轮 token 预算;
- Page In 保留来源和版本信息;
- Validate 防止旧记忆覆盖当前事实;
- Refresh 更新仍有效的内容;
- Demote / Archive 避免错误和过期结论长期常驻。
Memory 不是事实豁免区。源码、测试结果和生产状态发生变化后,旧 memory 必须降级为线索,不能继续作为当前结论。
四层记忆与能力演变
按信息来源,可以把 Agent 记忆分为训练数据、会话内数据、跨会话数据和外部世界数据。按系统成熟度,这些机制对应一条能力演变路径:
1 | |
前半段解决“能否接着运行”,后半段解决“恢复的内容是否仍正确、是否值得占用窗口”。能力越靠后,越依赖 Context Assembler、Selector、Compactor、Rehydrator 和验证机制之间的明确接口。
CoALA 将 language agent 描述为 LLM、memory、action space 和 decision-making procedure 的组合。这个视角能解释为什么单独增加 context window 不足以完成长程 scaling:窗口只是工作内存,选择、写回和验证策略决定了工作集质量。
实践规则
长任务可以按以下顺序治理:
- 限制单次工具结果,避免一个日志占满窗口。
- 把 spec、测试报告和阶段状态写到外部事实源。
- 在常驻上下文中只保留小目录、路径和关键约束。
- Compact 时明确未完成目标、修改文件、失败测试和验证命令。
- Compact 后检查实际 context 分类,不根据百分比猜测。
- 对自动恢复包设置预算、去重和过期策略。
- 检索到的 memory 先核验,再提升为当前约束。
- 新任务与旧任务无关时清空会话,从外部状态重新 page in。
下一阶段的 scaling 不只发生在模型参数和窗口长度上,也发生在工作集的选择、压缩、恢复和验证上。有限窗口能够连接更长的任务边界,前提是外部状态可检索、恢复合同可观测,并且 memory 具备时效与淘汰规则。
相关文章
- AI Coding Agent 的上下文操作系统:组件、生命周期与阅读地图
- AI Coding Agent 的上下文栈:组件边界与装配顺序
- AI Coding Agent 的 Skill 加载机制深度解析
- 一次 AI Coding Agent Turn 的上下文生命周期
- Agent 会话边界设计:Session、Context Window 与工作状态转移
- Messages 数组与 Prompt Cache:六种操纵策略
- 2026 Coding Harness 实现图谱
- 谁在记住你:Hermes、OpenClaw、Claude Code 等主流智能体的记忆架构深度横评
- 智能体记忆全景综述:从短时长时之分到向量库回归文件系统
参考资料
- APA: Multitasking: Switching costs
- Liu et al.: Lost in the Middle: How Language Models Use Long Contexts
- Anthropic: Effective context engineering for AI agents
- Claude Code Docs: Explore the context window
- Claude Code Docs: Extend Claude with skills
- Claude Code Docs: Hooks reference
- Claude Platform Docs: Prompt caching
- Sumers et al.: Cognitive Architectures for Language Agents
- Shinn et al.: Reflexion: Language Agents with Verbal Reinforcement Learning

