当上下文管理变成“可插拔”:OpenClaw Context Engine 的抽象设计与策略生态
当上下文管理变成“可插拔”:OpenClaw Context Engine 的抽象设计与策略生态
- 1. 引言:为什么要给上下文管理“松绑”?
- 2. 为什么要做这层抽象?—— 三个核心动机
- 2.1 动机一:告别“核心手术式”修改
- 2.2 动机二:让“不同场景”能用“不同策略”
- 2.3 动机三:把 OpenClaw 从“工具”变成“平台”
- 3. 这个设计支持哪些策略?—— Context Engine 的四种插件模式
- 3.1 生命周期四个核心钩子
- 3.2 两种压缩所有权模式
- 4. 真实案例:lossless-claw——“永不丢失上下文”
- 4.1 工作原理
- 4.2 效果对比
- 5. 与 Memory 系统的关系:分工而非替代
- 6. 一张图看懂 ContextEngine 的抽象价值
- 7. 结语:从“黑盒”到“开放平台”
🌺The Begin🌺点点关注,收藏不迷路🌺 ⬇ ⬇ 底部 ⬇ ⬇ |
1. 引言:为什么要给上下文管理“松绑”?
在 AI Agent 工程中,上下文管理一直是最棘手的问题之一。当对话轮次一多,Token 就爆炸;信息一压缩,关键细节就丢——这是几乎所有 Agent 开发者都经历过的痛苦。
在 OpenClaw 的早期版本中,上下文管理逻辑是写死在核心代码里的。对话过长时如何压缩历史、如何拼接上下文、何时丢弃旧信息,全部由系统内部固定实现,插件几乎无法介入。这意味着每次你想优化上下文策略,都得修改核心源码——风险极高,维护成本巨大。
2026 年 3 月 7 日,OpenClaw 发布了 v2026.3.7-beta.1,这是其发展史上的一次分水岭式更新。核心亮点是推出了ContextEngine 插件接口——把上下文管理从“写死在核心”变成了“可自由插拔”。
这层抽象的意义,用 PR 作者 Josh Lehman 的一句话可以概括:
“你其实不需要一个 Agent 记忆系统,你需要的是不会被重置的上下文。”
2. 为什么要做这层抽象?—— 三个核心动机
2.1 动机一:告别“核心手术式”修改
在旧架构中,上下文压缩、组装、修剪的逻辑全部内嵌在 Agent Runner 中。如果你想换一种压缩策略——比如从“简单摘要”换成“DAG 结构化压缩”——你只能去改 OpenClaw 的核心代码。
风险:改一处崩全程。每次升级 OpenClaw 版本,你还得重新合并你的定制代码。
解决:ContextEngine 接口把所有上下文相关的行为抽象为生命周期钩子。开发者只需实现这些钩子,就能完全自定义上下文处理逻辑,无需触碰核心代码。
开发者社区的反馈:项目 Issues 下面,有人评论说等这个接口等了快半年,点赞数秒过百。
2.2 动机二:让“不同场景”能用“不同策略”
不同的使用场景对上下文管理的要求完全不同:
| 场景 | 上下文管理需求 |
|---|---|
| 日常聊天 | 简单摘要即可,成本优先 |
| 代码开发 | 需要完整保留文件修改历史,不能丢失细节 |
| 长周期项目 | 需要跨会话召回关键决策,需要向量检索 |
| 复杂多步骤任务 | 需要 DAG 结构化压缩,保持决策链完整 |
在旧架构中,一套方案应对所有场景——要么牺牲细节换空间,要么撑爆窗口。ContextEngine 抽象让每个场景都能挂载最合适的策略。
2.3 动机三:把 OpenClaw 从“工具”变成“平台”
这个抽象的最大意义在于生态层面。它让 OpenClaw 从一个固定功能的 Agent 框架,变成了一个允许社区贡献上下文管理方案的平台。开发者可以:
- 开发自己的上下文引擎插件并发布到 npm
- 在 OpenClaw 中一键安装、切换
- 不用等官方发版,就能用上最新的上下文管理算法
3. 这个设计支持哪些策略?—— Context Engine 的四种插件模式
ContextEngine 接口提供了完整的生命周期钩子,开发者可以在不同阶段插入自定义逻辑。
3.1 生命周期四个核心钩子
每个钩子的作用:
| 钩子 | 触发时机 | 可以做什么 |
|---|---|---|
| Ingest | 新消息添加到会话时 | 存储消息到自定义数据源、建立索引 |
| Assemble | 每次模型运行前 | 返回适配 Token 预算的消息列表、注入动态系统提示 |
| Compact | 上下文窗口满或用户运行/compact | 执行自定义压缩策略(DAG 摘要、向量检索等) |
| After Turn | 一次运行完成后 | 持久化状态、触发后台压缩、更新索引 |
额外钩子:还支持bootstrap(会话初始化)、prepareSubagentSpawn(子 Agent 生成前准备)、onSubagentEnded(子 Agent 结束后清理)等可选钩子,全面覆盖了上下文管理的全生命周期。
3.2 两种压缩所有权模式
ContextEngine 设计中最精妙的是ownsCompaction标志,它定义了两种不同的策略模式:
| 模式 | ownsCompaction | 行为 |
|---|---|---|
| 拥有模式 | true | 引擎完全拥有压缩行为。OpenClaw 禁用内置自动压缩,引擎的compact()负责/compact、溢出恢复和主动压缩 |
| 委托模式 | false | 引擎的compact()调用delegateCompactionToRuntime(),使用 OpenClaw 内置压缩行为 |
关键约束:对于一个活动的非拥有引擎,
compact()不能是空操作——否则会禁用该引擎槽位的正常/compact和溢出恢复压缩路径。
4. 真实案例:lossless-claw——“永不丢失上下文”
社区第一个爆款的 ContextEngine 插件是lossless-claw,由 Josh Lehman 开发。它展示了一种颠覆性的上下文管理思路。
4.1 工作原理
在传统 Agent 系统中,一旦对话过长,系统通常会直接丢弃旧内容。而 lossless-claw 的做法是:
- 持久化到 SQLite 数据库:所有原始消息按对话组织,完整保存
- 生成摘要并构建 DAG:对旧消息块生成摘要,将摘要压缩为更高层级节点,形成有向无环图
- 每轮组合上下文:将“摘要 + 最近原始消息”组合成模型输入
- 提供回溯工具:Agent 可以通过
lcm_grep、lcm_describe、lcm_expand搜索和展开历史
4.2 效果对比
在OOLONG 基准测试中,使用同一模型时:
| 方案 | 得分 |
|---|---|
| lossless-claw | 74.8 |
| Claude Code | 70.3 |
关键发现:上下文越长,差距越大。在所有测试的上下文长度下,lossless-claw 的得分都高于 Claude Code。
安装方式(体现“可插拔”理念):
openclaw pluginsinstall@martian-engineering/lossless-claw// openclaw.json { plugins: { slots: { contextEngine: "lossless-claw" // 一行配置,切换引擎 }, entries: { "lossless-claw": { enabled: true } } } }5. 与 Memory 系统的关系:分工而非替代
ContextEngine 和 Memory 插件是两个独立的 Slot,各有分工:
| 维度 | Memory 插件 | ContextEngine |
|---|---|---|
| 职责 | 提供搜索/检索能力 | 控制模型“看到”什么 |
| 作用点 | 跨会话的知识召回 | 当前会话的上下文构建 |
| 典型行为 | 从向量库搜索相关记忆片段 | 组装消息、注入系统提示、执行压缩 |
它们可以协同工作:ContextEngine 在assemble()阶段可以通过buildMemorySystemPromptAddition()将 Memory 插件的检索结果注入到系统提示中。
6. 一张图看懂 ContextEngine 的抽象价值
核心洞察:OpenClaw 核心只定义“接口契约”,具体策略由插件实现。用户通过plugins.slots.contextEngine一行配置即可切换整个上下文管理策略。
7. 结语:从“黑盒”到“开放平台”
ContextEngine 抽象的设计价值可以从三个层面理解:
- 工程层面:避免了“改核心代码才能换策略”的高风险操作,让上下文管理变得可配置、可插拔
- 策略层面:支持从“简单摘要”到“DAG 无损压缩”再到“向量检索”的无限策略组合,让不同场景选择最优方案
- 生态层面:把 OpenClaw 从一个固定功能的工具变成了一个允许社区贡献上下文管理方案的开放平台
一句话总结:ContextEngine 抽象把“上下文管理”从 OpenClaw 核心的一个黑盒,变成了一扇可以自由插拔各种策略的开放接口。它回答了 Agent 系统中最根本的问题之一——当上下文窗口成为硬约束时,谁来决定“哪些信息该留下、哪些该归档、如何归档”?
答案是:你说了算,通过插件。
🌺The End🌺点点关注,收藏不迷路🌺 ⬆ ⬆ 顶部 ⬆ ⬆ |
