Mem0 Pi Agent 插件 Pin 技能详解:[PINNED] 标记机制、mem0_memory 工具链与 Dream 剪枝保护原理
导读
本文以 Pi Agent 插件中的 pin 技能文档为主体,系统讲解如何用 [PINNED] 文本标记把一条关键记忆(核心偏好、重要决策、不可变事实)标记为高优先级,使其在 Dream 记忆整合(consolidation)的剪枝阶段被跳过。读完本文,你将掌握 pin/unpin 的完整三步操作流程、mem0_memory 工具的各 action 参数用法,并能从插件源码层面理解保护标记是如何被 Dream 协议识别、以及 /mem0-pin 命令与技能流程在“是否保留记忆 ID”上的实现差异。
Pin 技能定位:为关键记忆上保险
pin 技能定义在 pin/SKILL.md,其 frontmatter 声明了技能用途:
Pins or unpins a memory to protect it from pruning during dream consolidation. Use when a memory is critical and must never be removed, such as core preferences, important decisions, or immutable personal facts.
该插件(@mem0/pi-agent-plugin)为 Pi Agent 提供跨会话、跨设备持久化的语义记忆,共内置 8 个技能与 8 个斜杠命令(完整清单见 README.md 的 Skills 与 Commands 表格)。其中 dream 技能负责记忆整合:合并近重复项、解决矛盾、剪掉过期条目。被剪枝的候选包括“超过 180 天且近期未访问的记忆”和“内容过于模糊(少于 5 个有效词)的记忆”——这正是 pin 技能存在的意义:给不可丢失的记忆上锁。
三步 Pin 流程(完整继承自技能文档)
技能文档将执行过程划分为三个步骤,以下完整保留并补充参数细节。
第一步:定位目标记忆
用户可以提供记忆 ID 或搜索查询二选一:
- 给定记忆 ID:直接按 ID 定位,无需搜索。
- 给定搜索查询:
- 调用
mem0_memory工具,参数action="search"、query=<查询文本>; - 向用户展示带编号的候选列表(内容预览形式);
- 询问:“Which memory to pin? Enter a number.”,等待用户输入编号。
- 调用
这里涉及插件的记忆作用域机制:search 默认在当前作用域(project / session / global)内检索。从 tools.ts 源码看,action="search" 会先用 resolveSearchFilters 依据作用域构造过滤条件(user + app_id [+ run_id]),再调用 mem0.search,输出经 formatMemoryList 格式化并截断至 200 行 / 50KB。scope 参数通常应省略——插件的工具描述明确提示“正常查询不要传 scope,省略即自动使用 project 默认值”(见 tools.ts 的 promptGuidelines)。
第二步:执行 Pin
核心机制只有一句话:把 [PINNED] 前缀拼接到记忆文本开头。这个标记是 Dream 整合识别“免剪枝记忆”的唯一依据。
技能文档规定的操作序列是:
- 调用
mem0_memory,action="add",content="[PINNED] <原始记忆文本>"——存入一条带标记的新记忆; - 再调用
mem0_memory,action="delete",传入原始记忆 ID——删除旧记忆。
针对新记忆(用户想固定一段尚未入库的文本):
- 只执行一次
mem0_memory,action="add",content="[PINNED] <用户文本>"。
注意:技能文档的 add + delete 序列会换发一个新的记忆 ID。仓库中另有一条保留 ID 的路径——斜杠命令
/mem0-pin直接使用mem0.update(target.id, { text: "[PINNED] <text>" })原地改写,详见下文“源码对照”。
第三步:确认输出
完成后按如下格式向用户回执:
Pinned: "<memory content, first 80 chars>"
仅当内容超过 80 个字符时才在末尾追加 ...。
Unpin 反向流程
当用户说出 “unpin” 时,技能文档规定四步走:
- 找到该记忆(搜索或按 ID);
- 创建一条不带
[PINNED]前缀的新记忆; - 删除带 pin 标记的版本;
- 打印
Unpinned: "<content>..."。
源码原理:[PINNED] 标记如何被 Dream 识别
Pin 技能的价值完全依赖 Dream 整合对标记的“跳过”行为,仓库中两处源码/技能文档共同构成了这一契约:
-
Dream 提示词协议:dream/prompt.ts 导出的
DREAM_PROTOCOL是/mem0-dream命令触发整合时注入给 Agent 的完整工作流(ORIENT → GATHER TARGETS → CONSOLIDATE → REPORT),其中第 2 步明确要求:Skip any memory starting with
"[PINNED]".即任何以
[PINNED]开头的记忆都不进入 DELETE / MERGE / REWRITE 分类,直接从整合目标中排除。 -
Dream 技能的剪枝启发式:dream/SKILL.md 给出了更细的判断规则——
- 近重复判定(合并候选)要求同时满足:关键词重叠 >60%、同一分类、且“Neither memory is pinned (content does not start with
[PINNED])”; - 剪枝候选(prune candidates)的末尾专门强调:“Always skip memories where content starts with
[PINNED], regardless of age.”——无论多老,一律跳过。
- 近重复判定(合并候选)要求同时满足:关键词重叠 >60%、同一分类、且“Neither memory is pinned (content does not start with
综合这两处可以确认:保护不是通过 mem0 服务端的某个字段实现的,而是文本约定 + 提示词约束——[PINNED] 前缀既是写入时的标记,也是 Dream 流程在 GATHER/ANALYZE 阶段的人机共识开关。这也解释了为什么技能文档强调 pin 时要“prepending [PINNED] to the memory text”,而不是调用某个专门的 pin API。
此外,Dream 整合本身有防重复与触发门槛:dream/index.ts 实现了锁文件(mem0-dream.lock,1 小时过期)与 mem0-dream-state.json 状态,自动整合需满足默认门槛 minHours: 24、minSessions: 5、minMemories: 20(见 dream/index.ts 的 DEFAULTS)。也就是说,pinned 记忆保护的是这些整合(手动或自动)发生时不会被误删。
技能流程与 /mem0-pin 命令的源码对照
pin 技能面向 Agent(由 LLM 按 SKILL.md 指引调用 mem0_memory 工具),而 commands.ts 注册的 /mem0-pin 命令面向用户终端,两者在“多候选选择”与“写入方式”上略有差异,值得对照:
| 环节 | pin 技能(SKILL.md) | /mem0-pin 命令(commands.ts) |
|---|---|---|
| 检索 | mem0_memory action="search" |
mem0.search(query, { filters, threshold: config.searchThreshold, topK: 10, rerank: true })(commands.ts) |
| 多候选 | 编号列表,用户输入编号 | ctx.ui.select 交互式选择器 |
| 幂等检查 | — | 若文本已以 [PINNED] 开头,直接回执 “Already pinned”(commands.ts) |
| 写入 | add("[PINNED] ...") + delete(旧 ID) |
mem0.update(id, { text: "[PINNED] ... " }),保留原记忆 ID |
| 确认 | 打印 Pinned: "<前80字符>" |
发送 “Pinned — protected from dream pruning” 反馈消息 |
从 commands.test.ts 的测试用例可以验证命令实现:用例断言 mem0.update 以 { text: "[PINNED] important fact" } 被调用,且对已是 [PINNED] 前缀的记忆走幂等分支(见 commands.test.ts 等断言)。README 命令表中 /mem0-pin <query> 的“preserves ID”描述即对应这条 update 路径。
一个需要注意的实践细节:由于 /mem0-pin 的检索依赖 searchThreshold,若相关记忆得分低于阈值,命令会直接返回 “No matches”——README 说明该阈值默认 0.3(配置示例中给出 0.2 的写法),是 /mem0-search、/mem0-forget、/mem0-pin 三个命令共用的最低相似度门槛,调高更严格、调低可减少漏召回(见 README.md 中 searchThreshold 说明)。
mem0_memory 工具参数速查(pin 场景相关)
pin 技能依赖的全部工具能力,都收敛在 mem0_memory 这一个工具上。其参数 schema 定义于 tools.ts,与 pin/unpin 直接相关的字段如下:
| 参数 | 类型 | pin 场景用途 |
|---|---|---|
action |
枚举:search / add / get_all / update / delete / delete_all |
定位用 search,写入用 add(或 update),收尾用 delete |
query |
string | action="search" 时必填,建议使用聚焦的名词短语 |
content |
string | action="add" 时必填;pin 时传 [PINNED] <原文>;action="update" 时作为替换文本 |
memory_id |
string | update / delete 时必填,取此前 search 或 get_all 返回的 ID |
scope |
枚举:project / session / global |
可选;省略即用默认 project 作用域 |
三个作用域对应的过滤条件在 README.md 中有表格说明:project(user + app_id,app_id 取 git 仓库根目录,monorepo 子目录共享同一记忆池)、session(再加 run_id,临时性上下文)、global(仅 user,跨全部项目)。pin 操作默认应发生在 project 作用域内,只有用户明确要求跨项目时才用 global。
典型实战组合
结合仓库文档,pin 技能通常与以下能力组合使用:
/mem0-dream前后:先/mem0-status查看连接与记忆数,整理前把核心偏好 pin 住,再触发整合,确保 Dream 的 MERGE/DELETE/REWRITE 分类不会触碰受保护条目;- 与 forget 区分:forget/SKILL.md 走的是搜索后确认删除的路径,与 pin 正好相反——pin 是“禁止删”,forget 是“主动删”;
- unpin 时机:当被 pin 的事实失效(例如项目决策被推翻)时,按上文四步 unpin,否则该事实会永久留存并可能干扰后续整合。
小结
pin 技能用极轻量的一条约定——[PINNED] 文本前缀——在 mem0 记忆体系中实现了“免剪枝”语义:写入时通过 mem0_memory 的 add/delete(或命令侧的 update)打上标记,Dream 整合协议在 GATHER 与 ANALYZE 阶段依据前缀跳过这些记忆,从而让核心偏好、关键决策与不可变事实在整个记忆生命周期内不被自动清理。理解了这一文本标记机制及其在 dream/prompt.ts、dream/SKILL.md、commands.ts 中的呼应关系,就能在 Pi Agent + Mem0 的记忆管理实践中准确运用 pin/unpin 与 Dream 整合的配合。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00