Skip to content

ShyZhen/memory-layer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Memory Layer 插件

https://github.com/ShyZhen/memory-layer

面向 OpenClaw 的企业级多渠道多用户记忆分层插件。

memory-layer 为 OpenClaw 提供多用户分层记忆能力,在保留共享知识的同时隔离每个用户的个人长期记忆。它把团队共享记忆与用户个人记忆拆开存储,避免不同用户之间的长期记忆互相污染,同时保留对旧版 MEMORY.md / memory/*.md 习惯的兼容。

默认情况下,它与渠道无关,基于 OpenClaw 的 session key 工作,适合钉钉、Telegram 以及其他支持独立 session key 的渠道场景。

英文版请见 README-en.md。 维护设计说明请见 ARCHITECTURE.md

发布 && 安装

发布

  • ClawHub 发布前检查
clawhub package publish ShyZhen/memory-layer@main --family code-plugin --name @shyzhen/memory-layer --display-name "Memory Layer 记忆分层" --dry-run
  • ClawHub 正式发布
clawhub package publish ShyZhen/memory-layer@main --family code-plugin --name @shyzhen/memory-layer --display-name "Memory Layer 记忆分层"
  • npm 发布
cd memory-layer
npm pack
npm publish --access public

安装

  • 安装方式1:直接从 ClawHub 安装:
openclaw plugins install @shyzhen/memory-layer
  • 安装方式2:先从 npm 打包,再从本地 tarball 安装

原因:当前部分 OpenClaw / ClawHub 运行环境在安装 scoped 包 @shyzhen/memory-layer 时,可能会因为临时 zip 路径处理问题报 ENOENT。先 npm pack 再本地安装可以稳定绕过这个问题。

npm pack @shyzhen/memory-layer
openclaw plugins install ./shyzhen-memory-layer-0.7.0.tgz

核心能力

  • 个人记忆按用户隔离,无需为每个终端用户单独创建 Agent 或 workspace
  • 共享记忆与个人记忆分层存储,适合团队协作场景
  • 兼容旧版 MEMORY.mdmemory/*.md 使用习惯。如果已经存在污染,推荐手动拆分迁移、清洗。
  • 保留 OpenClaw 原生“长期记忆 / 每日日记”语义,但把它改造成按用户隔离的多用户版本
  • 支持多个 Agent 共用同一份共享记忆文件
  • 新的个人记忆不再写回共享旧文件
  • 支持通过 enabledChannels 限制生效渠道

适用场景

  • 一个 Agent 同时服务多个钉钉用户
  • 希望每个用户都有自己的长期记忆
  • 希望团队共享知识可以跨用户、跨会话复用
  • 不想继续把新的个人记忆写回旧版共享 MEMORY.md
  • 需要逐步从旧 memory 习惯迁移到新的分层记忆模型

存储结构

默认目录结构如下:

  • shared/memory.md:团队共享记忆
  • users/<channel>/<account>/<peer>/memory.md:当前用户的长期记忆
  • users/<channel>/<account>/<peer>/notes/YYYY-MM-DD.mdYYYY-MM-DD-*.md:当前用户的旧版日记重定向文件
  • users/<channel>/<account>/<peer>/history/YYYY-MM-DD.md:当前用户的近期对话历史

默认这些文件位于 Agent workspace 下的 .memory-layer/ 目录内。

工作方式

在每次 Agent 运行前,插件会按 contextInjectionMode 注入分层上下文:

  • 共享记忆
  • 当前用户的个人记忆
  • 当前用户的兼容 notes/
  • 当前用户的近期 history/(仅在注入策略允许时)

在每次 Agent 运行结束后,插件会自动:

  • 把最近一轮真实用户消息和本轮助手回复追加到当前用户的 history 文件
  • 在启用显式保存命令时,保存用户要求持久化的记忆

注意:

  • contextInjectionMode = "new-session" 时,共享记忆、个人记忆和兼容 notes/ 会在新 session 首轮注入
  • 此时 history/ 只会在自动归档后新开的 session 中注入,不会在用户主动 /new/reset 后带回,尊重用户的命令操作
  • 插件不会把 /new/reset 产生的 synthetic 会话启动提示归档进 history/
  • 对于支持插件 before_reset hook 的较新 OpenClaw 版本,插件会优先根据结构化 reason: "new" | "reset" 识别手动 reset;对于较老版本,则继续使用 reset 启动提示与独立 /new/reset 文本作为兜底兼容

对于插件接管的私聊会话,插件还会拦截并重写旧版 memory 文件读写,确保新的个人记忆不会再写进共享的旧版 MEMORY.md 中。 对于插件自己维护的 shared/memory.md、个人 memory.md、每日 history,还会按字符上限做软裁剪,避免文件无限增长。

可以把它理解为:插件没有推翻 OpenClaw 原生 memory 的基本分工,而是在多用户场景下做了一层“按用户隔离”的增强:

  • 原来写 MEMORY.md / memory.md 的逻辑,会进入当前用户个人长期 memory.md
  • 原来写 memory/YYYY-MM-DD.md 的逻辑,会进入当前用户自己的 notes/
  • 这让原生“长期记忆 / 每日日记”的语义得以保留,但不再混写到所有用户共享的一套文件里
  • 同时支持“显式保存命令”,见下文章节

推荐配置

启用插件后,需要关闭 session-memory,防止openclaw继续写入默认记忆文件

{
  "hooks": {
    "internal": {
      "entries": {
        "session-memory": {
          "enabled": false
        }
      }
    }
  },
  
  "plugins": {
    "allow": [
      "memory-layer"
    ],
    "entries": {
      "memory-layer": {
        "enabled": true,
        "config": {
          "baseDir": ".memory-layer",
          "recentHistoryDays": 2,
          "includeGroups": false,
          "allowInlineSaveCommands": true,
          "contextInjectionMode": "new-session"
        }
      }
    }
  }
}

配置项说明

  • baseDir 分层记忆的根目录。相对路径会相对于当前 Agent workspace 解析。默认值为 .memory-layer
  • sharedFilePath 可选。指定共享记忆文件路径。 不配置时默认使用 <baseDir>/shared/memory.md。 如果多个 Agent 需要共用同一份团队记忆,可以把它们都指向同一个绝对路径。
  • recentHistoryDays 注入近期历史时,读取“最近有内容的 N 个日期文件”,而不是简单按自然日回看。默认值为 2
  • contextInjectionMode 统一控制整个 Layered Memory Context 的注入策略,包括共享记忆、个人记忆、兼容 notes 以及近期 history。默认值为 new-session。 可选值:
    • always:每轮都注入,兼容旧行为
    • new-session:(推荐设置)共享记忆、个人记忆和兼容 notes 会在新 session 首轮注入;history/ 只会在自动归档后新开的 session 中注入,不会在用户主动 /new/reset 后带回。如果当前 session 刚写入了共享/个人记忆,下一轮也会补注入一次。这是默认值,更适合一般聊天场景
    • off:关闭整个分层上下文注入
  • historyInjectionMode 已废弃的兼容别名。旧配置仍可继续使用,但新配置建议改用 contextInjectionMode
  • includeGroups 是否让插件处理群聊、频道、主题等非私聊会话。默认值为 false
  • enabledChannels 可选。限制插件只在指定渠道生效。 如果不配置,则对所有支持的渠道生效。
  • autoCreateFiles 是否预创建默认的分层记忆文件与模板内容。默认启用。 关闭后,插件不会主动生成默认 shared/memory.md、个人 memory.mdmeta.json 模板,但在真实写入发生时,仍可能创建必要的父目录或目标文件。
  • allowInlineSaveCommands 是否启用显式保存命令。默认启用。
  • enabledAgents 可选。只对指定 Agent 生效。 如果不配置,则对所有已加载该插件的 Agent 生效。
  • maxStoredSharedChars 共享记忆文件的存储软上限。默认值为 200000 表示不裁剪。
  • maxStoredPersonalChars 每个用户个人 memory.md 的存储软上限。默认值为 200000 表示不裁剪。
  • maxStoredHistoryChars 每个用户每日 history/YYYY-MM-DD.md 的存储软上限。默认值为 300000 表示不裁剪。

显式保存命令

如果用户消息中包含以下命令,插件会自动保存:

  • 记住:...
  • remember: ...
  • 共享记忆:...
  • remember-shared: ...

规则如下:

  • 记住 / remember 写入当前用户自己的 memory.md
  • 共享记忆 / remember-shared 写入共享记忆文件

这部分可以视为对 OpenClaw 原生 memory 行为的额外优化:

  • 原生路径写入逻辑仍然会被兼容并重定向到分层目录
  • 除了等待模型自己触发旧版 memory 写入,用户还可以通过 记住:... / 共享记忆:... 直接、明确地把内容写入个人长期记忆或共享记忆
  • 这让多用户企业场景下的“我现在就要记住这件事”变得更稳定、更可控

notes 与 history 的实际作用

  • history/ 记录的是当前用户最近一轮原始入站消息与本轮助手回复,用来提供短期连续性上下文
  • contextInjectionMode = "new-session" 时,共享记忆、个人记忆和兼容 notes 会在新 session 首轮注入;history/ 只会在自动归档后新开的 session 中注入,不会在用户主动 /new/reset 后带回
  • 在支持 before_reset 的新版本 OpenClaw 上,插件会直接根据 reset hook 事件判断“这是一次手动 /new / /reset”;在旧版本上,则回退到识别 OpenClaw 注入的 reset 启动提示或独立命令文本
  • 如果当前 session 刚写入了共享/个人记忆,下一轮还会补注入一次,避免刚保存的记忆暂时不可见
  • notes/ 不是每次对话都会写入
  • 只有当旧版工具去读写 memory/YYYY-MM-DD.mdmemory/YYYY-MM-DD-*.md 时,插件才会把这些路径重定向到当前用户自己的 notes/
  • 如果当前 Agent 完全不再使用旧版 memory/*.md 路径,那么 notes/ 可能长期为空,或只留下少量历史兼容文件

支持的 Session Key

插件当前支持以下常见的 OpenClaw session key 形式:

  • agent:<agentId>:dm:<peerId>
  • agent:<agentId>:<channel>:dm:<peerId>
  • agent:<agentId>:<channel>:<accountId>:dm:<peerId>
  • agent:<agentId>:<channel>:direct:<peerId>
  • agent:<agentId>:<channel>:group:<id>
  • agent:<agentId>:<channel>:channel:<id>
  • agent:<agentId>:<channel>:group:<id>:topic:<topicId>
  • ...:thread:<threadId>

重要限制:

  • session.dmScope = "main" 可以运行,但会退化为单用户模式

原因是这种模式下所有私聊会共享同一个 session key,因此插件只能把所有私聊视为同一个“用户层”,无法实现按真实用户隔离的个人记忆。

多 Agent 共享记忆

如果你希望多个 Agent 共用同一份团队共享记忆,可以把它们的 sharedFilePath 都配置为同一个绝对路径。

示例:

{
  "plugins": {
    "entries": {
      "memory-layer": {
        "enabled": true,
        "config": {
          "baseDir": ".memory-layer",
          "sharedFilePath": "C:\\Users\\zhenhuaixiu\\.openclaw\\memory\\team-shared.md",
          "recentHistoryDays": 2,
          "includeGroups": false
        }
      }
    }
  }
}

这表示:

  • 每个 Agent 仍然保留各自 workspace 下的个人记忆层
  • 所有启用该插件的 Agent 共同读写同一份共享团队记忆

限制到指定渠道

如果你只想让插件在特定渠道生效,可以配置 enabledChannels

示例:

{
  "plugins": {
    "entries": {
      "memory-layer": {
        "enabled": true,
        "config": {
          "enabledChannels": ["dingtalk", "telegram"],
          "baseDir": ".memory-layer"
        }
      }
    }
  }
}

如果省略 enabledChannels,则默认对所有支持渠道生效。

部署与兼容建议

  • 强烈建议禁用内置的 session-memory hook,避免旧逻辑继续把个人记忆写回共享路径
  • 旧版根目录 MEMORY.md 可以继续保留,作为兼容性的共享上下文
  • 没有必要把 sharedFilePath 指向根目录 MEMORY.md
  • 对于插件接管的私聊会话,不建议再依赖旧版 memory_searchmemory_get
  • OpenClaw 原生 memory 的自动 flush / 搜索索引针对的是根目录 MEMORY.mdmemory/*.md,不会直接接管 .memory-layer/**
  • 插件启动时会对 session.dmScope = "main" 和已启用的 session-memory 输出 warning,帮助排查“为什么没有按用户隔离”
  • 如果你的 OpenClaw 版本已经支持 before_reset 插件 hook,推荐直接使用当前版本插件;它会优先走结构化 reset 识别。即使线上仍有旧版本节点,当前插件也保留了提示词兜底,不需要额外切换配置

说明

  • 这是一个刻意保持文件化、可直接查看的实现,方便排查与迁移
  • 近期历史是时效性上下文,不应视为唯一事实来源
  • 如果你需要了解内部重写规则、兼容原因或维护排查细节,请查看 ARCHITECTURE.md

About

openclaw的plugin:`memory-layer` 为 OpenClaw 提供多用户分层记忆能力,在保留共享知识的同时隔离每个用户的个人长期记忆。它把团队共享记忆与用户个人记忆拆开存储,避免不同用户之间的长期记忆互相污染,同时保留对旧版 `MEMORY.md` / `memory/*.md` 习惯的兼容。

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors