OpenClaw 3.7 最重磅更新ContextEngine 插件接口源码级拆解 —— AI Agent 上下文管理从此告别硬编码本文出自 AI Agent 记忆系统逆向工程 项目—— 我们逆向拆解了 OpenClaw、nanobot、NullClaw、OpenFang 4 个开源 AI Agent 框架的记忆系统源码级记录每一个设计细节。30 篇文档、全架构图全部开源。如果觉得有价值欢迎 ⭐ Star 支持。导读OpenClaw 3.7 beta 更新了 89 项代码提交其中最重磅的一条是 ContextEngine 插件接口上线。社区有人评论等这个接口等了快半年点赞数秒过百。这篇文章不讲概念直接拆源码带你看清楚这个接口到底解决了什么问题、怎么解决的、以及你能从中学到什么。一、先搞清楚AI Agent 的上下文管理为什么是最头疼的问题你跟 AI 对话每一轮历史消息都作为上下文送给模型。模型需要看到之前聊了什么才知道你现在在问什么。问题出在这里模型的上下文窗口有大小限制。128K token 的窗口你聊了 200 轮加上工具调用的返回值token 早就爆了。这时候系统得做决策——哪些消息留下最近的肯定要但最近的边界在哪旧消息怎么处理直接砍掉还是压缩成摘要送给模型时怎么排列系统提示 历史 工具 schema顺序和内容怎么组装这就是上下文管理Context Management。每个实用的 AI Agent 框架都绕不开。关键在于这些处理逻辑一旦写死在核心代码里日后每次调整都是高风险手术。二、旧架构有多痛读完源码你就懂了我们逆向了 OpenClaw v2026.3.7 之前的源码旧的上下文管理是一条完全硬编码的流水线散布在 5 个文件里没有任何抽象层用户消息进来 → SessionManager 写入 JSONL → 加载全部历史消息 → sanitize清洗约 10 个步骤 → validate按 provider 校验 → limit暴力截断 → repair修复孤儿消息 → 送给模型2.1 sanitize 有多复杂这个函数叫sanitizeSessionHistory()名字平平无奇里面塞了大约10 个处理步骤标注跨会话用户消息清理/缩放图片不同模型有不同图片限制删除thinking块规范化工具调用的名称和 ID修复孤立的 tool_use → tool_result 配对删除工具返回值中的冗余字段清理过期的 assistant usage 快照记录模型快照元数据降级 OpenAI 推理格式仅 OpenAI Responses API修复 Google/vLLM 的轮次顺序约束仅 Google provider2.2 压缩逻辑是最大的坑当 token 快要超限时系统有个压缩机制——把旧对话总结成摘要删掉原始消息。这个逻辑在compact.ts约 763 行是最大的痛点。为什么因为压缩需要调模型来生成摘要而调模型需要完整的上下文环境于是compact.ts把attempt.ts里大量环境构建代码复制了一遍compact.ts 独立重复的逻辑 ├── resolveModel() — 模型解析attempt.ts 也有一份 ├── resolveModelAuthMode() — 认证模式attempt.ts 也有一份 ├── resolveSandboxContext() — 沙箱配置attempt.ts 也有一份 ├── resolveChannelCapabilities() — 频道能力attempt.ts 也有一份 ├── sanitize→validate→limit→repair — 完整管线attempt.ts 也有一份 └── ...还有更多改一处忘了改另一处上线即 bug。2.3 三种压缩触发方式全是硬编码旧架构有三种压缩触发方式SDK 自动检测Agent 运行期间检测到即将超限主动触发用户手动/compact用户在对话中输入命令Overflow 重试模型返回 token 超限错误自动重试最多 3 次问题不在于触发方式不够多而在于——你无法通过插件替换这些策略。想自定义什么时候该压缩的判断逻辑只能改核心代码。2.4 痛点总结痛点具体表现逻辑散落散布在 sanitize、validate、limit、repair、compact 5 个文件大量重复compact.ts 复制了 attempt.ts 的模型解析、沙箱配置等大量代码无法替换想换个压缩算法必须改核心代码策略硬编码三种压缩触发方式全硬编码在核心代码无后处理Agent 一轮结束后没有任何钩子做后续优化子 Agent 隔离父子 Agent 之间没有上下文共享/清理机制微信文章里说的改一处崩全程指的就是这些。三、ContextEngine 的核心思路把做什么和怎么做分开OpenClaw 3.7 的 ContextEngine 接口PR #2220144 个文件改动解决方案其实很经典——定义一组接口让核心运行时只关心要做什么具体怎么做交给可替换的引擎。用官方的话说这叫零阻碍接入。翻译成人话以后换个上下文处理算法像换插件一样简单。3.1 七个生命周期钩子ContextEngine 定义了7 个钩子覆盖了上下文的完整生命周期会话开始 → ① bootstrap() — 初始化引擎状态 → ② ingest() — 每条消息摄入 → ③ assemble() — 组装模型上下文 → 调用模型 → ④ afterTurn() — 回合后处理 → ⑤ compact() — 需要压缩时执行 子 Agent 场景 → ⑥ prepareSubagentSpawn() — 准备子 Agent 上下文 → ⑦ onSubagentEnded() — 清理子 Agent 上下文用人话对照一下变化从前硬编码现在ContextEngine 钩子意味着什么消息直接写入 JSONLingest()— 引擎决定怎么存可以存到向量库、做预处理sanitize→validate→limit→repairassemble()— 引擎决定怎么组装可以用 RAG、用检索、用任何算法三种硬编码压缩方式compact()— 引擎决定怎么压可以不压、可以自定义摘要策略回合结束什么都不做afterTurn()— 引擎做后处理可以异步优化上下文子 Agent 完全独立prepareSubagentSpawn()onSubagentEnded()父子 Agent 可以共享上下文3.2 接口定义精简版interfaceContextEngine{readonlyinfo:ContextEngineInfo;// 3 个必选 上下文管理的三件核心事ingest(params:{sessionId,message}):PromiseIngestResult;assemble(params:{sessionId,messages,tokenBudget?}):PromiseAssembleResult;compact(params:{sessionId,sessionFile,tokenBudget?,...}):PromiseCompactResult;// 4 个可选 增强能力bootstrap?(params):PromiseBootstrapResult;afterTurn?(params):Promisevoid;prepareSubagentSpawn?(params):PromiseSubagentSpawnPreparation|undefined;onSubagentEnded?(params):Promisevoid;}3 个必选方法覆盖了上下文管理最本质的三件事消息怎么存、上下文怎么组、太多了怎么压。4 个可选方法提供增强能力不实现也不影响基本运转。这个设计非常克制——不多不少刚好够用。四、向后兼容的艺术LegacyContextEngine 与绞杀者模式引入新接口最怕什么Breaking change。OpenClaw 用了一个经典的架构模式——Strangler Fig绞杀者模式在旧系统外面包一层新接口旧逻辑原封不动跑在新接口里。LegacyContextEngine就是这个包装器方法实际做了什么效果ingest()返回{ ingested: false }什么都不做SessionManager 照旧处理assemble()原样返回 messages不改动旧管线照旧跑compact()调用原来的压缩函数压缩逻辑完全不变afterTurn()空操作没有副作用结果不配置任何 context engine 插件时系统行为和升级前 100% 一致。零风险升级。这就是为什么 89 项代码提交能顺利上线的原因——不是蛮力堆功能是架构上保证了不破坏已有行为。五、注册与解析机制怎么做到换插件一样简单5.1 进程全局注册表// 通过 Symbol.for() 挂在 globalThis 上// 为什么monorepo 构建可能把模块打包成多份拷贝// Symbol.for() 确保不管有几份 js 文件注册表只有一个constREGISTRYSymbol.for(openclaw.contextEngineRegistryState);registerContextEngine(id,factory);// 注册getContextEngineFactory(id);// 获取listContextEngineIds();// 列出所有5.2 Slot 机制constDEFAULT_SLOT_BY_KEY{memory:memory-core,// 记忆插件contextEngine:legacy,// 上下文引擎};一个坑位只能站一个人。两个插件都声明kind: context-engine只有被配置选中的那个加载。5.3 一行配置搞定切换{plugins:{slots:{contextEngine:lossless-claw}}}不配这一行 → 默认legacy→ 行为不变。这就是像换插件一样简单的实现原理。六、实战10 分钟写一个自定义 Context Engine这不是空谈看代码exportdefaultfunctionregister(api){api.registerContextEngine(my-rag-context,()({info:{id:my-rag-context,name:RAG Context,ownsCompaction:true},asyncingest({sessionId,message}){// 每条消息写入向量数据库awaitvectorDb.insert(sessionId,message);return{ingested:true};},asyncassemble({sessionId,messages,tokenBudget}){// 不是暴力截断而是 RAG 检索最相关的历史消息constrelevantawaitvectorDb.search(sessionId,latestQuery,tokenBudget);return{messages:relevant,estimatedTokens:countTokens(relevant)};},asynccompact({sessionId}){// RAG 模式下不需要压缩——assemble 时按需检索return{ok:true,compacted:false};},}));}三个核心方法加起来不到 20 行。但效果是什么你把上下文管理从暴力截断变成了语义检索而且没有改动 OpenClaw 的任何核心代码。七、ContextEngine ≠ 记忆系统别搞混了很多人会混淆这两个概念。简单区分ContextEngine上下文管理Memory 插件记忆系统管什么当前 session 内的消息流跨 session 的持久化知识库核心问题哪些消息送给模型、何时压缩怎么索引、搜索、存取记忆生命周期一个 session 内跨越所有 session存储session JSONL 文件Markdown 文件 SQLite/LanceDB它们之间的桥梁是Memory Flush——在 ContextEngine 执行压缩之前先触发一个静默 Agent 回合提醒 Agent 把值得保留的对话内容写入记忆文件。上下文管理决定模型这次能看到什么记忆系统决定Agent 下周还记得什么。两者协同但独立。八、从 ContextEngine 学到的架构思维不管你用不用 OpenClaw这次的 ContextEngine 设计有几个通用的工程模式值得带走8.1 绞杀者模式Strangler Fig新接口包装旧逻辑渐进式替换。不一口气重写而是让新旧共存逐步迁移。这在任何大型系统的重构中都适用。8.2 接口 注册表 配置驱动定义接口 → 工厂函数注册到全局注册表 → 配置文件选择用哪个引擎 → 运行时动态解析。这套模式在Java 的 SPI、Python 的 entry_points、Rust 的 trait 中都有对应。8.3 Best-effort 回调子 Agent 生命周期回调失败只记日志不阻断主流程。在分布式系统中让非关键路径的失败不影响主路径是基本原则。8.4 必选 可选方法分离3 个必选方法保证核心能力4 个可选方法扩展增强能力。实现者可以从最简开始逐步增加功能。九、这跟我们做的事有什么关系我们的项目AI Agent 记忆系统逆向工程做的事就是这个——逆向拆解 4 个火爆的开源 AI Agent 框架的记忆系统源码级记录每一个设计细节。ContextEngine 只是 OpenClaw 分析的一部分。完整的文档覆盖了框架语言特点文档数OpenClawTypeScript插件架构、混合搜索、优雅降级12 篇nanobotPython极简主义2 个 Markdown 文件搞定7 篇⚡NullClawZig10 种存储后端、9 阶段检索管线9 篇OpenFangRust知识图谱、记忆衰减、统一 SQLite 底座10 篇从 2 个 Markdown 文件到 10 种存储后端、从暴力截断到 9 阶段检索管线——4 种完全不同的设计哲学让你一次看透 AI Agent 记忆系统的全貌。适合谁正在构建 AI Agent 的工程师直接参考已经验证过的架构想理解记忆到底怎么实现的研究者源码级拆解不是概念堆砌想在 LangGraph / LangChain / 自研框架中做上下文管理的开发者每个框架都有复刻指南完整文档 架构图 代码分析全部开源GitHub 仓库https://github.com/breath57/how-ai-agents-remember如果觉得对你有帮助给个 ⭐ 吧。我们还在持续更新。十、总结OpenClaw 3.7 的 ContextEngine 接口核心价值用一句话概括以后换个上下文处理算法像换插件一样简单不用再担心改一处崩全程。它不是一个多了个功能的小更新而是一次架构层面的升级——把 AI Agent 中最头疼的上下文管理问题从硬编码在核心代码里变成了可插拔的标准接口。7 个生命周期钩子、绞杀者模式的向后兼容、全局注册表 Slot 机制的引擎管理——这些设计模式不仅适用于 OpenClaw同样适用于你正在做的任何 AI Agent 系统。不论你用什么技术栈上下文管理的核心问题是一样的。理解它、借鉴它、在你的项目中用好它。本文基于 AI Agent 记忆系统逆向工程项目 中对 OpenClaw 的源码分析撰写。项目持续更新中欢迎 Star 和 PR。