首页
/ mem0 OpenCode 插件 mem0-remember 技能详解:逐字写入、类型分类与异步写入确认流程

mem0 OpenCode 插件 mem0-remember 技能详解:逐字写入、类型分类与异步写入确认流程

2026-09-05 09:26:20作者:胡唯隽

mem0 仓库中的 integrations/mem0-plugin 为 OpenCode、Claude Code、Cursor、Codex 等 AI 编码工具提供跨会话持久记忆能力,其中 mem0-remember 是专门负责"把用户明确陈述的事实逐字(verbatim)存入记忆"的技能。本文以该技能的 SKILL.md 为核心,结合插件源码,完整拆解其四步执行流程、类型分类规则、add_memory 参数细节与异步事件确认机制,读完你可以理解该技能如何保证"用户说什么就存什么",并能独立复现其调用链。

技能定位与插件背景

mem0-remember 技能文件位于 mem0-remember/SKILL.md。其 YAML frontmatter 声明了触发条件:

name: mem0-remember
description: Stores a memory verbatim from user input with appropriate type
  classification and metadata. Use when the user says remember this, save
  this, store this, note that, or explicitly asks to record a decision,
  preference, convention, or learning.

关键点在于 verbatim(逐字):当用户明确说"记住这个 / 保存一下 / 记下这个约定"时,Agent 不做任何改写或事实抽取,直接把原文作为记忆写入,只额外补充分类与元数据。

该技能是 OpenCode 插件体系的一部分。根据 插件 README,OpenCode 的安装方式为一行命令:

opencode plugin @mem0/opencode-plugin

安装后插件通过其 config 钩子自动注册原生记忆工具、生命周期钩子和技能,无需配置 MCP 服务器。插件清单 plugin.json 声明该插件面向 Antigravity agent 提供跨会话、用户级召回能力(版本 0.1.7,Apache-2.0 协议),而 mcp_config.json 则给出了远端 MCP 服务的连接方式(mcp.mem0.ai,鉴权头使用 ${MEM0_API_KEY} 环境变量插值)。同一套技能在 Claude Code 侧的对应版本是 skills/remember/SKILL.md,命令名为 /mem0:remember,流程完全一致,只是 OpenCode 版本命令名为 /mem0-remember,且多了 TUI 输出格式约束。

四步执行流程

Step 1:提取内容

用户以参数形式提供要记忆的内容:

/mem0-remember <text>

如果用户没有提供文本,技能要求 Agent 主动询问:"What should I remember?"。这一步保证写入的 text 一定来自用户明确陈述,而不是 Agent 的推断。

Step 2:对记忆分类

技能要求根据内容信号选择最合适的 metadata.type,完整分类规则如下:

内容信号 类型
"we decided..."、"always use..."、"never..." decision
"X doesn't work because..."、"don't try..." anti_pattern
"I prefer..."、"use X instead of Y" user_preference
"the convention is..."、"we always..." convention
"learned that..."、"figured out..." task_learning
setup、env、tooling、config 相关内容 environmental
其他任何情况 task_learning

这套类型体系服务于插件的检索设计:后续 search_memories 可以通过 filters 中的 {"metadata": {"type": "decision"}} 等条件做定向召回(参见同目录 mem0-search/SKILL.md 中"双路并行搜索:一路宽泛、一路限定 type=decision"的做法)。因此 remember 阶段的分类质量直接决定了之后按类型过滤检索的命中率,默认兜底 task_learning 也保证了任何输入都有确定的类型归属。

Step 3:调用 add_memory 写入

技能规定调用 add_memory 工具的完整参数:

  • text="<用户原文>"
  • user_id=<active_user_id>
  • app_id=<active_project_id>
  • metadata={"type": "<分类类型>", "branch": "<当前分支>", "confidence": 1.0, "source": "remember_command"}
  • infer=False

其中两个关键决策在文档中有明确解释:

  • infer=False:用户已明确陈述事实,不需要 LLM 再做事实抽取(fact extraction),写入即原文;
  • confidence=1.0:因为是用户显式要求存储,可信度取最高值。

从源码可以印证这两个参数并非仅靠提示词约定。在 opencode-mem0.ts 中,add_memory 工具的实现逻辑为:

const meta = args.metadata ?? {};
if (meta.confidence === undefined) meta.confidence = 0.7;
if (!meta.source) meta.source = "opencode";
if (!meta.type) meta.type = "task_learning";
if (!meta.session_id) meta.session_id = sessionId;
if (!meta.files) meta.files = ["*"];
if (!meta.branch) meta.branch = branch;

let infer = args.infer;
if (meta.confidence >= 1.0 && infer === undefined) {
  infer = false;
}

这说明:

  1. 技能指定 confidence: 1.0 时,插件会自动把 infer 置为 false(当 Agent 未显式传 infer 时),与 SKILL.md 中"infer=False because the user stated the fact explicitly"的语义完全一致——即"高置信度显式陈述 ⇒ 逐字写入"在工具层有代码兜底;
  2. 元数据有完整默认值:不传 confidence 时为 0.7(自动捕获场景的置信度),不传 type 时兜底为 task_learning,并自动补 session_idfiles: ["*"]、当前 git 分支——所以技能中显式给出 metadata 是在覆盖这些默认值,使该条记忆可被识别为"remember 命令产生"(source: "remember_command");
  3. user_id / app_id 在插件启动时已解析并注入:opencode-mem0.tsgetUserId() 优先取 MEM0_USER_ID 环境变量,否则取系统用户名;getProjectId() 优先取 MEM0_APP_ID,否则解析 git remote get-url origin 得到 owner/repo,再退化为 git 仓库根目录名。SKILL.md 中的 <active_user_id> / <active_project_id> 即来自这些解析结果,插件还会通过 shell.env 钩子把它们以 MEM0_USER_IDMEM0_APP_IDMEM0_BRANCH 等环境变量暴露给 shell(见 opencode-mem0.ts#L384-L395)。

Step 4:异步事件确认

技能强调:add_memory 的响应返回的是 event_id 而不是 memory_id,因为写入是异步的。确认后需要调用一次 get_event_status(event_id=...)

  • 状态为 SUCCEEDED:输出结果中的 memory ID;
  • 状态为 PENDINGprocessing:以 event ID 作为兜底输出。

确认输出的固定格式为:

Remembered as <type>: "<内容,前 80 字符>"
Memory ID: <来自事件状态的 id>

仅当内容超过 80 字符被截断时才追加 ...。这一约定让用户在 TUI 中能快速看到"存了什么类型、存了什么内容",同时保留了可追溯的 ID。工具层同样有对应实现:opencode-mem0.ts#L616-L626get_event_status 直接请求平台侧的 /v1/event/<event_id>/ 端点查询异步写入结果。

插件如何把技能变成可用命令

opencode-mem0.tsregisterCommands 函数可以看到技能与命令的接线方式:插件遍历 opencode-skills/ 目录下每个含 SKILL.md 的子目录,读取其 frontmatter 的 description 作为命令描述,并把目录名注册为 OpenCode 的斜杠命令(如 mem0-remember/mem0-remember)。命令模板会附带插件启动时解析好的身份上下文(user_id、app_id、session_id、branch),指示 Agent 加载并执行对应 SKILL.md。源码注释特别说明:仅通过 skills.paths 发现的技能可以被 Agent 的技能工具使用,但不会出现在 TUI 斜杠菜单中,因此还需要 registerCommands 显式注册——这解释了为什么 SKILL.md 中用户入口写作 /mem0-remember <text>

此外,插件在 chat.message 钩子里维护了一条"记忆触发"正则(opencode-mem0.ts#L175-L176):

const NUDGE_RE =
  /\b(remember\s+(this|that)|memorize|save\s+this|note\s+(this|that)|don'?t\s+forget|always\s+remember|never\s+forget|keep\s+(this|that)\s+in\s+(mind|memory)|store\s+(this|that))\b/i;

当用户在自然对话(而非斜杠命令)中说"remember this / 别忘了这个"时,插件会向系统上下文注入提示 [MEMORY TRIGGER] User asked to remember something. Call add_memory with the user's statement, confidence=1.0, infer=false.——这与 SKILL.md frontmatter 描述的触发场景("remember this, save this, store this, note that")逐条对应,即使用户不输入斜杠命令,插件也能引导 Agent 按相同参数(confidence=1.0, infer=false)完成逐字写入。

实操:安装、配置与验证

完整可用的操作路径如下(依据 插件 README):

  1. 准备 API Key:从 Mem0 平台获取以 m0- 开头的 API Key,并持久化到 shell 环境:

    echo 'export MEM0_API_KEY="m0-your-api-key"' >> ~/.zshrc
    source ~/.zshrc
    echo $MEM0_API_KEY   # 验证输出
    

    注意:OpenCode 桌面场景下,MCP 配置读取的是环境变量插值(${MEM0_API_KEY} 在会话启动时解析),因此必须持久化设置而非仅当前 shell 临时导出。

  2. 安装插件

    opencode plugin @mem0/opencode-plugin
    

    追加 --global 可全局安装。安装后重启 OpenCode 会话。

  3. 执行 onboard(可选但推荐):/mem0:onboard 会校验 API Key 与连接、导入项目文件、安装面向编码场景的记忆分类,并可重复执行(幂等)。

  4. 使用 remember

    /mem0-remember "we decided to always use TypeScript for the API layer"
    

    按技能流程,Agent 应将其分类为 decision,以 infer=Falseconfidence=1.0source="remember_command" 写入,并回显确认块。也可以用 /mem0:remember "we use TypeScript" 式的自然语句,或直接在对话中说"记住:我们的接口一律用 TypeScript 写"触发 NUDGE 路径。

  5. 验证写入:随后用 /mem0:tour(OpenCode 侧为 /mem0-tour)按分类浏览全部记忆,或用 /mem0-search <关键词> 做语义检索确认该条可被召回。

输出格式约束:为什么技能禁止 Markdown

SKILL.md 末尾有一段 OpenCode 专属的格式约束:

IMPORTANT: Do NOT use markdown in your output. OpenCode TUI renders text verbatim — markdown like bold, ## headers, and | table | syntax appears as raw characters. Use plain text with indentation for structure. Use dashes for lists. Use spaces to align columns instead of markdown tables.

这是因为 OpenCode 的 TUI 终端逐字渲染文本,**加粗**## 标题| 表格 | 等语法会原样显示为可见字符。因此技能明确要求:用缩进表达结构、用短横线做列表、用空格对齐列来替代 Markdown 表格。这条约束体现了 SKILL.md 作为"写给 Agent 的执行手册"的定位——它不仅定义流程,还约束了最终呈现给用户的输出形态,确保确认块在不同终端环境下都可读。

小结

mem0-remember 技能的设计核心可以归纳为三点,且每一点都能在仓库中找到代码级佐证:

  1. 逐字写入text 直接取用户原文,infer=False 跳过 LLM 事实抽取;工具层在 confidence >= 1.0 时自动强制 infer=falseopencode-mem0.ts#L446-L449);
  2. 结构化分类:六种 metadata.type 覆盖决策、反模式、偏好、约定、任务学习与环境配置,兜底 task_learning,为后续按类型过滤的语义检索奠定基础;
  3. 异步确认闭环add_memory 返回 event_id,通过 get_event_status 单次轮询拿到最终 memory_id,并以固定纯文本格式回显,兼顾 TUI 可读性与可追溯性。

如果你要在此基础上做扩展(例如自定义分类或增加确认重试),建议直接参照 mem0-remember/SKILL.md 的四步结构修改 SKILL.md——插件会在下次会话启动时重新读取 description 并注册命令,无需改动插件 TypeScript 代码。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384