ClawXMemory 记忆插件移植部署全记录 —— 从不可能到完全运行

序言

这是一篇来自部署一线的技术日记。记录了将 EdgeClaw 专属的 ClawXMemory 长期记忆插件,成功移植到 OpenClaw 平台上的完整过程。这个过程跨越了数小时的深度分析、三次方案推翻重来、无数次容器崩溃重启,以及最终的成功验收。

背景:为什么要做这件事

我们的 AI 助手体系运行在一台 Intel Celeron J1900 小主机(路由器)上,通过 Docker 容器部署了 OpenClaw——一个多 Agent 网关,连接 Discord、Telegram、WhatsApp 等多个渠道。4 个 Agent(小武、书呆子、小超、小谷)全天候在线,为用户提供服务。

但有一个致命缺陷:Agent 没有长期记忆。 每次对话都是从零开始,之前聊过什么、用户的偏好、正在进行的项目——全部忘得一干二净。

EdgeClaw(OpenClaw 的商业版)有一个强大的记忆插件——ClawXMemory(由 OpenBMB 开发),实现了完整的三层记忆架构:

  • L0:原始对话捕获
  • L1:LLM 驱动的结构化抽取(摘要、事实、项目)
  • L2:时间线与项目索引
  • Profile:用户画像持续更新

问题是:这个插件只在 EdgeClaw 上能跑,直接放到 OpenClaw 上会因为三个根本性差异而崩溃。

第一阶段:调研与分析

走过的弯路

最初考虑过三个方案:

  1. memory-lancedb-pro 插件:需要 AVX 指令集,J1900 不支持,直接淘汰。
  2. 直接复制 ClawXMemory:插件文件放上去就崩,config validation 报错,无限重启。
  3. 运行时适配方案(最终方案):深入分析 EdgeClaw 源码,找出差异点,精准打补丁。

三大根因

通过三个并行的 Explore Agent 对 EdgeClaw 源码的深度分析,我们定位了三个根本原因:

根因 1:Config Write Hash Sentinel ClawXMemory 启动时会调用 reconcileManagedMemoryBoundary() 方法,直接写入 openclaw.json 配置文件。EdgeClaw 内置了 writeConfigSection() API,而 OpenClaw 没有。插件写入失败 → 检测到配置不一致 → 触发重启 → 无限循环。

根因 2:callStructuredJson 不支持 OAuth L1 抽取需要调用 LLM(通过 callStructuredJson),EdgeClaw 用自己的 OAuth token 直接调用。OpenClaw 没有这个认证通道,LLM 调用直接失败。

根因 3:clearMemoryPluginState OpenClaw 在每次重启时会清理插件状态,导致记忆数据被重置。

第二阶段:设计运行时适配方案

核心思路:不改 OpenClaw 源码,只改插件代码,让插件适应 OpenClaw 的运行环境。

Patch 1:环境变量守卫(runtime.ts)

在 reconcileManagedMemoryBoundary() 方法的最开头插入:

if (process.env.CLAWXMEMORY_SKIP_MANAGED_BOUNDARY === "1") {
    this.logger.info?.("[clawxmemory] CLAWXMEMORY_SKIP_MANAGED_BOUNDARY=1; skipping managed config reconciliation");
    return "ready";
}

效果:插件永远不会尝试写入 openclaw.json。我们预先把所有配置写好,插件启动时直接读取,皆大欢喜。

Patch 2:extractionModel 覆写(llm-extraction.ts)

在 resolveSelection() 方法中,插入模型覆写逻辑:

const extractionModel = this.config?.plugins?.entries?.["openbmb-clawxmemory"]?.config?.extractionModel;
if (extractionModel) {
    modelRef = extractionModel;  // 使用配置中指定的模型
}

效果:LLM 抽取不再依赖 EdgeClaw 的 OAuth 认证通道,而是使用我们自己配置的 OpenAI API Key + gpt-4.1-mini 模型。巧妙的是,这里复用了 OpenClaw 原有的全部 provider 解析代码(baseUrl、apiKey、headers),只是把模型引用换了。

配置预写

在 openclaw.json 中预写了 8 项变更:

  • 新增 openai-direct provider(gpt-4.1-mini)
  • 设置 plugins.slots.memory = "openbmb-clawxmemory"
  • 禁用旧的 memory-core 插件
  • 启用 ClawXMemory 并配置 extractionModel
  • 注册 memory 相关 tools
  • 禁用与 ClawXMemory 冲突的内置记忆功能

第三阶段:部署实战

Phase 0-2:顺利

备份、复制插件文件、创建 typebox 符号链接——这几步都很顺利。

Phase 3:补丁之痛

最初想通过 SSH heredoc + python3 内联脚本来修改文件,结果发现复杂的 heredoc 在 SSH 管道中有各种引号转义问题,命令直接挂死。

解决方案:SCP 工作流。 把文件从路由器拉到本地 → 用编辑工具修改 → 推回路由器。虽然多了几步,但稳定可靠。

Phase 4:配置修改

8 项 JSON 修改,用 python3 脚本精确操作,一次成功。

Phase 5:容器重启 —— 噩梦开始

第一次崩溃:权限问题

docker rm + docker run 重建容器后,发现 /home/node/.openclaw(即宿主机的 /opt/docker/openclaw/config)目录权限是 root:root 700。容器内的 node 用户(uid 1000)根本无法读取配置文件。

原始容器是怎么工作的?这成了一个谜——因为我们已经删掉了原始容器,无法回溯。

修复:chmod 755 + chown 1000:1000。

第二次崩溃:配置验证失败

plugins.entries.openbmb-clawxmemory.config: invalid config: must NOT have additional properties

这是最意想不到的问题。我们在 config.ts(TypeScript 类型定义)中添加了 extractionModel 字段,但 OpenClaw 的配置验证不看 TypeScript——它看的是 openclaw.plugin.json 清单文件中的 configSchema,那里有 additionalProperties: false。

修复:在 openclaw.plugin.json 的 configSchema.properties 中添加 extractionModel 字段定义。

第三次:成功!

修复清单文件后重启,容器终于稳定运行。但首次启动要等待 jiti(TypeScript 即时编译器)编译约 780 个缓存文件,在 J1900 上需要 3-4 分钟,期间 CPU 飙到 136%,内存涨到 1.4GB,没有任何日志输出。这段沉默的等待是最考验耐心的。

第四阶段:验收

当日志中出现以下内容时,我知道成功了:

[clawxmemory] CLAWXMEMORY_SKIP_MANAGED_BOUNDARY=1; skipping managed config reconciliation
[clawxmemory] dynamic memory runtime ready: active memory slot is ClawXMemory.
[clawxmemory] dashboard ready at http://127.0.0.1:39394/clawxmemory/

随后的测试对话中,完整的记忆管线开始运转:

  • L0 捕获:多个 agent(书呆子、小武、小谷)的对话全部被捕获
  • L1 LLM 抽取:7 次成功调用 gpt-4.1-mini,0 次失败,中文摘要质量优秀
  • L2 索引:时间线和项目索引自动生成
  • Profile:用户画像持续更新
  • Recall:记忆回忆成功注入对话上下文(recall mode=llm injected=true)

LLM 抽取的摘要示例:

  • "用户询问助手记忆力恢复情况,助手回顾了当前记忆系统的状态和已知项目,确认了核心工作体系和未解决的部署失败问题。"(projects=4, facts=2)
  • "用户询问助理为何被称为书呆子,助理解释其钻研细节和推理过载的特点。"(facts=1)

记忆数据库文件 memory.sqlite 在验收时已增长到 557KB + 4MB WAL,说明数据在持续写入。

技术总结

最终修改清单

文件 修改内容
runtime.ts 添加 env var 守卫,跳过配置写入
llm-extraction.ts 添加 extractionModel 覆写
config.ts 添加 extractionModel 类型定义
openclaw.plugin.json 添加 extractionModel 到 configSchema
openclaw.json 8 项配置变更

关键教训

  1. OpenClaw 的配置验证流程:先验证 JSON Schema(清单文件),再加载 TypeScript。改了 TS 不改清单文件等于白改。
  2. Docker 容器重建的陷阱:docker rm + docker run 会丢失原始容器的运行时状态和权限设置。
  3. jiti 编译时间:在低端 CPU 上,首次编译可能需要数分钟。不要因为没有日志输出就以为容器挂了。
  4. SCP 比 SSH heredoc 更可靠:复杂的文件编辑不要试图通过 SSH 管道内联完成。

运行成本

使用 OpenAI gpt-4.1-mini 进行 L1 抽取,单次调用约 $0.001-0.003。按 4 个 agent 每天 150-300 次对话估算,每月成本约 $5-15,完全可接受。

尾声

从 "这个插件不可能在 OpenClaw 上运行" 到 "全线运行,记忆管线完整",这个过程让我深刻体会到:所谓的"不可能",往往只是还没找到正确的切入点。EdgeClaw 和 OpenClaw 的差异看似巨大,但归根结底只有三个关键函数的行为不同。精准定位、最小化修改、逐步验证——这才是工程实践的正道。

现在,Agent 们终于有了记忆。它们会记住每一次对话、每一个项目、每一个关于用户的事实。从白纸一张到积累成册,这正是 ClawXMemory 的魅力所在。


部署日期:2026 年 4 月 10 日 平台:OpenClaw on Docker / Intel J1900 / 8GB RAM 记忆插件:openbmb-clawxmemory(从 EdgeClaw 源码移植) LLM 后端:OpenAI gpt-4.1-mini