在 ClawdBot (MoltBolt / OpenClaw) 中增加记忆插件 PowerMem 的新玩儿法
![]()
Moltbot 是什么?
Clawdbot(后更名为 Moltbot,又更名为 OpenClaw)是一款开源、以通讯为核心的AI智能体项目,运行在你自己的设备上,通过你已有的渠道(WhatsApp、Telegram、Slack、Discord、Google Chat、Signal、iMessage、Teams、WebChat 等)和你对话,支持语音、Canvas、多代理路由等。
简单点说:Moltbot 最大的特点是不仅能回答问题,更能真正“动手”操作你的电脑系统,执行命令、控制浏览器、管理文件,就像一个 7 x 24 小时在线的 “数字员工”。
Moltbot 部署
方式一:NPM 全局安装
npm install -g moltbot@latest
# 或使用 pnpm
pnpm add -g moltbot@latest
# 初始化并安装守护进程
moltbot onboard --install-daemon
方式二:源代码安装
# 克隆仓库
git clone https://github.com/moltbot/moltbot.git
cd moltbot
# 安装依赖
pnpm install
pnpm ui:build # 首次运行会自动安装 UI 依赖
pnpm build
# 初始化
pnpm moltbot onboard --install-daemon
# 开发模式(监听 TypeScript 变更自动重载)
pnpm gateway:watch
上面两种安装方式二选一,因为我是走的源代码安装:
- pnpm moltbot onboard --install-daemon 初始化
- 同意风险提示
这里会让你确认风险。Moltbot 功能强大,能执行系统命令、读写文件、控制浏览器,但这也意味着如果配置不当或被滥用,可能会带来安全风险,请谨慎使用。
- 选择快速开始
- 配置 AI 模型授权,我手里头有qwen的
- 启动web
问个小问题:“查一下我的电脑型号”,很快 moltbot 回复了我机器的具体型号,虽然任务非常简单,但是还是挺惊喜的,距离“贾维斯”又进了一步了。
Moltbot 的原生记忆解读
Moltbot 的持久记忆可以概括为:「Markdown 文件为单一事实来源 + 可选向量/混合检索」。
存储形态:纯 Markdown 文件
- 事实来源:模型「记得」的内容 = 写入磁盘的 Markdown;不依赖模型内部状态。
- 默认布局(在 workspace 下,如 ~/clawd):
- memory/YYYY-MM-DD.md:按日期的日志,仅追加;会话开始时读「今天 + 昨天」。
- MEMORY.md(可选):长期、人工可维护的记忆;只在 main 私聊 session 加载,群聊不加载。
也就是说:
- 短期、按天的记录 → memory/YYYY-MM-DD.md
- 长期、精选事实 → MEMORY.md
- 持久化完全靠「写进这些文件」,而不是靠对话历史本身。
写入时机与「记忆冲刷」(Memory Flush)
- 平时:模型通过 工具(如 write、edit)或技能,把要记住的内容写到 MEMORY.md 或 memory/YYYY-MM-DD.md。
- 自动冲刷:当 session 快触发自动 compaction 前,Moltbot 会跑一轮 静默的 agent 回合,专门提醒模型「把该持久化的东西写进记忆文件」,并鼓励用 NO_REPLY 不回复用户,避免用户看到这次内部回合。
- 触发条件由 agents.defaults.compaction.memoryFlush 控制,例如在「剩余 token ≈ softThresholdTokens」时触发;每轮 compaction 只做一次 flush,并在 sessions.json 里记 memoryFlushCompactionCount 等,避免重复。
相关代码在 src/auto-reply/reply/memory-flush.ts:
- shouldRunMemoryFlush():根据当前 token、context 上限、reserve、softThreshold 判断是否该 flush。
const shouldFlushMemory =
memoryFlushSettings &&
memoryFlushWritable &&
!params.isHeartbeat &&
!isCliProvider(params.followupRun.run.provider, params.cfg) &&
shouldRunMemoryFlush({
entry:
params.sessionEntry ??
(params.sessionKey ? params.sessionStore?.[params.sessionKey] : undefined),
contextWindowTokens: resolveMemoryFlushContextWindowTokens({
modelId: params.followupRun.run.model ?? params.defaultModel,
agentCfgContextTokens: params.agentCfgContextTokens,
}),
reserveTokensFloor: memoryFlushSettings.reserveTokensFloor,
softThresholdTokens: memoryFlushSettings.softThresholdTokens,
});
- 若 workspace 只读(如 sandbox workspaceAccess: “ro”),则不做 flush。
检索层:向量 + 可选 BM25 混合检索
数据流
MoltbotConfig (raw)
→ agents.defaults.memorySearch [默认]
→ agents.<agentId>.memorySearch [按 agent 覆盖,由 resolveAgentConfig 解析]
↓
mergeConfig(defaults, overrides, agentId)
↓
ResolvedMemorySearchConfig(扁平、带默认、已 clamp)
↓
resolveMemorySearchConfig 若 enabled 则返回,否则 null
↓
getMemorySearchManager / MemoryIndexManager 用其决定 backend、索引路径、embedding、检索参数等
实现方式
- 插件控制:默认使用 memory-core 插件(可设 plugins.slots.memory = “none” 关掉)。
-
工具:
- memory_search:对 MEMORY.md 和 memory/*.md 做语义检索(按 ~400 token 分块、80 token 重叠),返回片段 + 文件路径 + 行号;可选开启 BM25 + 向量 的混合检索。
- memory_get:按路径(及可选 from/lines)读取 MEMORY 或 memory 下的文件片段,供在检索后精确拉取,控制上下文长度。
-
向量索引:
- 对 MEMORY.md 和 memory/*.md 建索引;索引按 agent 存于 ~/.clawdbot/memory/.sqlite(路径可配)。
- 支持远程 embedding(OpenAI、Gemini 等)或本地模型(如 GGUF);可选 sqlite-vec 做向量加速。
- 文件变更有 watcher(debounce),索引异步更新;若 embedding 模型/端点等变化,会整库重建索引。
混搜权重分配
const DEFAULT_HYBRID_ENABLED = true; // 是否开启混搜,默认同时用向量相似度和 BM25 全文,向量找语义、BM25 找精确词(如 ID、命令)。
const DEFAULT_HYBRID_VECTOR_WEIGHT = 0.7; // 向量权重 70%,
const DEFAULT_HYBRID_TEXT_WEIGHT = 0.3; // 关键词权重 30%,最终得分 = 0.7×向量分 + 0.3×文本分(归一化后),偏重语义。
const DEFAULT_HYBRID_CANDIDATE_MULTIPLIER = 4; // 候选池倍数
const DEFAULT_MAX_RESULTS = 6; // 最大返回结果数
const DEFAULT_MIN_SCORE = 0.35; // 最低分数阈值
最终分数的计算公式非常简单(src/memory/hybrid.ts):
// 线性加权合并
const score = vectorWeight * vectorScore + textWeight * textScore;
// BM25 排名转分数(排名越高,分数越高)
function bm25RankToScore(rank: number): number {
return 1 / (1 + rank); // rank=0 → score=1, rank=9 → score=0.1
}
这意味着:
- 向量搜索和文本三七开:最终得分 = 0.7×向量分 + 0.3×文本分(归一化后),偏重语义。
- 候选池放大 4 倍:先取 maxResults × 4 的候选再合并、排序、截到 maxResults,提高最终 Top‑N 质量。
Moltbot + powermem 方案
有 PowerMem VS 没有 PowerMem
| 维度 | 没加 PowerMem(只用 core) | 加了 PowerMem(backend=powermem) |
|---|---|---|
| 存储形态 | 工作区 Markdown(MEMORY.md、memory/*.md)+ 本地 SQLite 向量索引 |
记忆存在 PowerMem 服务端(向量 + 全文 + 图(可选)),Moltbot 不落盘 |
| 智能抽取与去重 | 无:依赖模型自己写 Markdown,可能重复、冲突 | 有:PowerMem 可做 LLM 事实抽取、去重、冲突更新,记忆更干净 |
| 遗忘与衰减 | 无:内容一旦写入就一直在 | 有:PowerMem 支持艾宾浩斯遗忘曲线、时间衰减,可「自然遗忘」旧信息 |
| 多智能体 / 多用户 | 按 agent 隔离(目录与索引分离) | PowerMem 原生 agent_id / user_id、权限与协作,适合多 agent、多用户场景 |
| 部署与依赖 | 仅需 Moltbot + 可选 embedding API,无额外服务 | 需单独部署/运维 PowerMem 服务(HTTP API),多一个组件 |
| 检索能力 | 向量 + 可选 BM25,单机、可控 | 向量 + 全文 + 图检索(可选)、用户画像改写等,能力更丰富、可扩展 |
| 适用场景 | 个人/单机、强调「文件即真相」、简单运维 | 多用户/多 agent、要智能抽取与遗忘、愿多维护一个记忆服务 |
集成 powermem 方案
集成方式:已插件的方式进行集成
┌─────────────────────────────────────────────────────────────────┐
│ Moltbot (Node/TS) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ extension: memory-powermem │ │
│ │ - register() → tools + lifecycle hooks + CLI │ │
│ │ - HTTP client → PowerMem API (fetch) │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
│ HTTPS / HTTP
▼
┌─────────────────────────────────────────────────────────────────┐
│ PowerMem Server (Python) │
│ - POST /api/v1/memories (add, optional infer=true) │
│ - POST /api/v1/memories/search (semantic search) │
│ - DELETE /api/v1/memories/:id (forget) │
│ - GET /api/v1/system/health (health check) │
└─────────────────────────────────────────────────────────────────┘
-
集成方式:新增插件
extensions/memory-powermem,通过 HTTP 调用 PowerMem 已启动的 API 服务;不把 PowerMem 作为库嵌入 Moltbot 进程。 -
部署:用户需单独启动 PowerMem(如
powermem-server --host 0.0.0.0 --port 8000或 Docker),并在 Moltbot 配置中填写baseUrl(及可选apiKey)。
代码结构
moltbot-extension-powermem/
├── index.ts # 插件入口:定义插件、注册工具/CLI/生命周期
├── client.ts # PowerMem HTTP 客户端
├── config.ts # 配置解析与校验
├── moltbot.plugin.json # 插件元数据与 UI 配置
├── package.json # 依赖与 npm 配置
├── tsconfig.json # TypeScript 配置
└──── types/
└── clawdbot-plugin-sdk.d.ts # Moltbot 插件 SDK 类型声明
在 Moltbot Agent 里会暴露这些能力:
- memory_recall — 按查询搜索长期记忆
- memory_store — 写入一条记忆(可选是否智能抽取)
- memory_forget — 按记忆 ID 或按搜索条件删除
使用 powermem 插件
Step1: 前置条件
- 已安装 Moltbot(CLI + gateway 能正常用)
- PowerMem 服务:需要单独安装并启动(见下文两种方式,任选其一)
- 若用 PowerMem 的「智能抽取」:需在 PowerMem 的
.env里配置好 LLM + Embedding 的 API Key(如通义千问 / OpenAI)
Step2:把本插件装进 Moltbot
在你本机执行(路径改成你实际克隆的目录):
# 若插件在本机目录(例如克隆下来的)
moltbot plugins install /path/to/moltbot-extension-powermem
# 开发时想改代码即生效,可用链接方式(不拷贝)
moltbot plugins install -l /path/to/moltbot-extension-powermem
安装成功后,可用 moltbot plugins list 确认能看到 memory-powermem。
Step3:配置 Moltbot 使用本插件
编辑 Moltbot 的配置文件(常见位置:~/.clawdbot/config.json 或项目里的 moltbot.json),在 根级 增加或合并 plugins 段,并把记忆槽指向本插件,并写上 PowerMem 的地址。
示例(JSON):
{
"plugins": {
"slots": { "memory": "memory-powermem" },
"entries": {
"memory-powermem": {
"enabled": true,
"config": {
"baseUrl": "http://localhost:8000",
"autoCapture": true,
"autoRecall": true,
"inferOnAdd": true
}
}
}
}
}
说明:
-
baseUrl:PowerMem 的 HTTP 地址,不要加/api/v1,就写http://localhost:8000或你的实际主机/端口。 - 若 PowerMem 开了 API Key 鉴权,在
config里增加"apiKey": "你的key"。 - 改完配置后重启 Moltbot gateway(或重启 Mac 菜单栏应用),配置才会生效。
Step4:验证插件与 PowerMem 连通
在终端执行:
# 检查 PowerMem 服务是否可达
moltbot ltm health
若输出里没有报错、能看到健康状态,说明插件已连上 PowerMem。
Step5: 测试手动写入 + 搜索
我们来简单测试一下,用手动写入验证数据库是否有数据
pnpm moltbot ltm add "喜欢软件界面为炫酷黑"
pnpm moltbot ltm search "黑色"
若搜索能返回刚写的那条(或类似内容),说明「安装 PowerMem → 安装插件 → 配置 Moltbot」全流程已打通。
下面是执行结果:
➜ moltbot git:(add_powermem) ✗ pnpm moltbot ltm add "我喜欢软件的界面为炫酷黑"
> moltbot@2026.1.27-beta.1 moltbot /Users/jingshun.tq/project/moltbot
> node scripts/run-node.mjs ltm add '我喜欢软件的界面为炫酷黑'
10:52:13 [plugins] memory-powermem: plugin registered (baseUrl: http://localhost:8000, user: moltbot-user, agent: moltbot-agent)
🦞 Moltbot 2026.1.27-beta.1 (6e09492) — I can run local, remote, or purely on vibes—results may vary with DNS.
Stored 1 item(s): [ 672030219405623300 ]
➜ moltbot git:(add_powermem) ✗ pnpm moltbot ltm add "我喜欢软件的界面为炫酷黑"
> moltbot@2026.1.27-beta.1 moltbot /Users/jingshun.tq/project/moltbot
> node scripts/run-node.mjs ltm add '我喜欢软件的界面为炫酷黑'
10:52:47 [plugins] memory-powermem: plugin registered (baseUrl: http://localhost:8000, user: moltbot-user, agent: moltbot-agent)
🦞 Moltbot 2026.1.27-beta.1 (6e09492) — Give me a workspace and I'll give you fewer tabs, fewer toggles, and more oxygen.
Stored 1 item(s): [ 672031428522803200 ]
➜ moltbot git:(add_powermem) ✗ pnpm moltbot ltm search "黑色"
> moltbot@2026.1.27-beta.1 moltbot /Users/jingshun.tq/project/moltbot
> node scripts/run-node.mjs ltm search '黑色'
10:53:16 [plugins] memory-powermem: plugin registered (baseUrl: http://localhost:8000, user: moltbot-user, agent: moltbot-agent)
🦞 Moltbot 2026.1.27-beta.1 (6e09492) — I'll do the boring stuff while you dramatically stare at the logs like it's cinema.
[
{
"memory_id": 672031428522803200,
"content": "喜欢软件界面为炫酷黑",
"score": 0.01639344262295082,
"metadata": {
"_vector_similarity": 0.7113943570021182,
"_quality_score": 0.7113943570021182,
"_fusion_score": 0.01639344262295082,
"_fusion_info": {
"vector_rank": 1,
"fts_rank": null,
"sparse_rank": null,
"rrf_score": 0.01639344262295082,
"fusion_method": "rrf",
"vector_weight": 0.5,
"fts_weight": 0.5,
"sparse_weight": 0
},
"last_searched_at": "2026-01-29T10:53:21.808320Z",
"search_count": 1
}
}
]
看一眼数据库,妥妥的已经写入了
obclient(root@obmysql)[powermem]> select id,document,metadata,user_id,agent_id,run_id,actor_id,hash,created_at,updated_at,category,fulltext_content from memories limit10\G;
*************************** 1. row ***************************
id: 672031428522803200
document: 喜欢软件界面为炫酷黑
metadata: {}
user_id: moltbot-user
agent_id: moltbot-agent
run_id: NULL
actor_id:
hash: c7d63391192d288848068a185d2fd42b
created_at: 2026-01-29T10:52:57.638765+00:00
updated_at: 2026-01-29T10:52:58.886383+00:00
category:
fulltext_content: 喜欢软件界面为炫酷黑
1 row in set (0.006 sec)





