2026 年 Agent 上下文管理:源码实证与架构建议
- 结论先行(TL;DR)
- 把“省 token”当目标会南辕北辙;目标应是“在长任务中少犯错”,token 节省只是副产品。
- 现成方案最易落地的组合是“语义组装 + 算法压缩”:先用 LCM(lossless-claw)挑对上下文,再用 Headroom 压冗余工具输出。但要把可逆取回(CCR)与结构化任务状态贯穿,否则准确率会掉。
- OpenClaw 默认 Legacy 引擎确实是“壳”,但内置了一套守护与补救机制;生态里已有 Headroom、context‑mode、LCM 的插件化路径,无需 fork 重写。
- Hermes 的压缩不是“固定 13.9k + 双调用”,而是一次结构化摘要,预算随上下文规模动态调整。
问题刻画
- 约束:模型上下文上限;工具输出与检索回流导致会话爆炸;跨会话/跨子任务串联要求“记得住状态而不是记得住过程”。
- 错位:把“最高压缩比/最少 token”当 KPI 会牺牲可用性(缺关键行、断工具结果配对、遗漏标识符等),更好的目标是“正确率、重试次数、任务完成率、返工率”。
生态速写(源代码为证)
- OpenClaw(默认)
- Legacy 引擎是“兼容壳”:
- openclaw/src/context-engine/legacy.ts:28 ingest() 返回 { ingested: false }
- openclaw/src/context-engine/legacy.ts:38 assemble() 原样透传、estimatedTokens: 0
- openclaw/src/context-engine/legacy.ts:79 compact() 委托给运行时 delegateCompactionToRuntime
- 压缩“固定比例 + 护栏”并存:
- openclaw/src/agents/compaction.ts:16 BASE_CHUNK_RATIO=0.4
- openclaw/src/agents/compaction.ts:17 MIN_CHUNK_RATIO=0.15
- openclaw/src/agents/compaction.ts:18 SAFETY_MARGIN=1.2
- 同文件包含“按 token 份额切块、成对保留 tool 调用/结果、摘要开销预算”等逻辑与重试补救
- 插件“排他 slot”:
- openclaw/src/plugins/slots.ts:12 kind→slot 映射(memory / context-engine)
- openclaw/src/plugins/slots.ts:76 applyExclusiveSlotSelection(…) 切换 slot 并禁用同类插件
- 任务状态不是“纯内存”:
- 运行时 Map:openclaw/src/tasks/task-registry.ts:50
- 可插拔持久化(默认 SQLite):openclaw/src/tasks/task-registry.store.ts:31
- Legacy 引擎是“兼容壳”:
- lossless‑claw(LCM)
- 架构解耦(SQLite/FTS5 存储 + 语义组装 + 可扩展摘要),通过插件契约接入 OpenClaw:
- lossless-claw/src/engine.ts:1199 LcmContextEngine implements ContextEngine
- 依赖的是 openclaw/plugin-sdk 契约而非零依赖:lossless-claw/src/engine.ts:19
- 会话存储:lossless-claw/src/store/conversation-store.ts:263
- 语义检索:lossless-claw/src/retrieval.ts:124
- 架构解耦(SQLite/FTS5 存储 + 语义组装 + 可扩展摘要),通过插件契约接入 OpenClaw:
- Headroom
- JSON 工具输出智能压缩(SmartCrusher)、文本压缩(Kompress,可选 ML)、可逆取回(CCR):
- 非 JSON 直通(不压):headroom/tests/test_text_compressors.py:289
- CCR 工具名:headroom/headroom/ccr/mcp_server.py:64
- 已有 OpenClaw 引擎插件(零 LLM、调用 compress()):
- headroom/plugins/openclaw/src/engine.ts:1
- JSON 工具输出智能压缩(SmartCrusher)、文本压缩(Kompress,可选 ML)、可逆取回(CCR):
- Hermes Agent
- 压缩预算动态,不是“固定 13.9k + 双调用”:
- 下限/比例/上限:hermes-agent/agent/context_compressor.py:39, :41, :43
- 预算计算与上限约束:hermes-agent/agent/context_compressor.py:220–:225
- 唯一 LLM 调用(结构化摘要,支持迭代更新):hermes-agent/agent/context_compressor.py:404, :287
- 低成本预处理(裁剪旧工具输出):hermes-agent/agent/context_compressor.py:155
- 记忆 provider 可插拔,但“是否调用 LLM”取决于 provider 实现:
- hermes-agent/agent/memory_provider.py:164
- 压缩预算动态,不是“固定 13.9k + 双调用”:
- context‑mode
- 以“会话简历”跨压缩注入、计数与可观测:
- 计数:context-mode/src/session/db.ts:84, :194
- before/after_compaction 钩子 + resume 注入:context-mode/src/pi-extension.ts:297, :307, :265
- 以“会话简历”跨压缩注入、计数与可观测:
发现与补正
- “OpenClaw 等于‘塞满再摘要’”并不全面
- 确有固定比例与 Legacy 默认,但生产路径包含分块、工具配对修复、摘要质量守卫、标识符保护、重试/超时治理与“预压缩记忆冲洗”等演进;判词宜改为“默认策略偏朴素,但配备成体系护栏,可通过插件替换/接管”。
- “任务状态在内存 Map,测试强耦合”偏颇
- TaskRegistry 提供持久化与 Observer 注入点,可替换为轻量 store,隔离测试(见上)。
- “Headroom 压不动自然语言摘要”要加限定
- SmartCrusher 针对 JSON,文本默认直通;但 Kompress 可对文本压缩(需 [ml] 额外依赖)。并且 CCR 让“可逆检索”成为安全阀。
- “LCM 零 OpenClaw 依赖”应更严谨
- 是“契约依赖、实现解耦”,能在 OpenClaw 外独立复用,但仍以 plugin-sdk 类型做编译时契约绑定。
组合方案:Meta‑Engine 编排(LCM → Headroom)
- 目标:既保留语义相关性(由 LCM 负责),又显著压掉冗长工具输出等结构化内容(由 Headroom 负责);对纯对话场景自动旁路,避免过度压缩。
- 编排要点
- 接口所有权:实现一个 ContextEngine,占住 context-engine slot。
- 生命周期
- assemble():先调用 LCM assemble(),对输出消息做“工具输出占比估算”;若工具占比>阈值(如 ≥50%),调用 Headroom compress();否则直通 LCM 输出。
- compact():传入 token 预算给 Headroom(RollingWindow + CCR),并透传/保留 LCM 的摘要(避免对摘要再压缩)。
- 格式桥接
- LCM/Headroom 使用的消息格式(Agent/OpenAI)互转:参考 headroom/plugins/openclaw/src/engine.ts:11 转换器思路。
- 对“工具结果成对”保持:遵循 OpenClaw 分块配对逻辑避免“孤儿调用/结果”(见 openclaw/src/agents/compaction.ts:117)。
- 可逆性/取回
- 同步注入 CCR 工具使用说明,或在 system prompt 添加“若需要更多细节,调用 headroom_retrieve”提示,见 headroom/headroom/ccr/mcp_server.py:64。
- 旁路策略
- 统计最近 N 条消息文本 token 比例、工具输出 token 比例与 JSON 可压缩度评分(可用样本规则先行),不满足门槛直接返回 LCM 结果。
- 风险与对策
- “摘要+压缩”双重丢失风险:禁止对摘要文本做 lossy 压缩;CCR 仅覆盖被压缩的原文,不覆盖摘要。
- 桥接一致性:保持 tool_call_id/tool_result 成对与顺序稳定,避免模型拒绝或工具注入失配。
- 观测:记录 tokens_before/after/saved、错配修复次数、CCR 取回次数等,作为回归指标。
评价指标(建议用例)
- 基础:token 节省(prompt_tokens)、压缩前后 API 错误率、继续对话“重复工作”比率。
- 任务正确性代理:修 bug 类用例中“首次定位关键错误行”的命中率;代码生成用例中的“路径/标识符保真率”。
- 稳定性:工具调用-结果配对完整率,CCR 取回命中率与延迟。
我会怎么实现(最小工作量)
- 新建一个 context-engine 插件(占 slot)
- 复用 lossless-claw 作为子引擎生产 assemble 结果
- 条件触发 headroom compress()(沿用 headroom/plugins/openclaw/src/engine.ts:1 里的 compress() 调用方式)
- 旁路或失败一律回退到 LCM 输出;compact() 仅分发预算与记录观测
- 工期估计:~300–500 行 TypeScript(含桥接与指标),不改三方仓库
证据清单(可点开核查)
- OpenClaw
- openclaw/src/context-engine/legacy.ts:28, openclaw/src/context-engine/legacy.ts:38, openclaw/src/context-engine/legacy.ts:79
- openclaw/src/agents/compaction.ts:16, openclaw/src/agents/compaction.ts:17, openclaw/src/agents/compaction.ts:18, openclaw/src/agents/compaction.ts:117, openclaw/src/agents/compaction.ts:211
- openclaw/src/plugins/slots.ts:12, openclaw/src/plugins/slots.ts:76
- openclaw/src/tasks/task-registry.ts:50, openclaw/src/tasks/task-registry.store.ts:31
- lossless‑claw
- lossless-claw/src/engine.ts:1199, lossless-claw/src/engine.ts:19
- lossless-claw/src/store/conversation-store.ts:263, lossless-claw/src/retrieval.ts:124
- Headroom
- headroom/tests/test_text_compressors.py:289
- headroom/headroom/ccr/mcp_server.py:64
- headroom/plugins/openclaw/src/engine.ts:1
- Hermes Agent
- hermes-agent/agent/context_compressor.py:39, hermes-agent/agent/context_compressor.py:41, hermes-agent/agent/context_compressor.py:43
- hermes-agent/agent/context_compressor.py:220, hermes-agent/agent/context_compressor.py:225
- hermes-agent/agent/context_compressor.py:404, hermes-agent/agent/context_compressor.py:287, hermes-agent/agent/context_compressor.py:155
- hermes-agent/agent/memory_provider.py:164
- context‑mode
- context-mode/src/session/db.ts:84, context-mode/src/session/db.ts:194
- context-mode/src/pi-extension.ts:297, context-mode/src/pi-extension.ts:307, context-mode/src/pi-extension.ts:265