Mem0 插件 tour 技能解析:按类别浏览、语义检索与跨项目汇总 AI 代理项目记忆
本文以 Mem0 插件中的 tour 技能文档为核心,完整拆解 /mem0:tour 命令的三种运行模式(单项目完整漫游、peek 紧凑检索、跨项目汇总)及其背后的 get_memories / search_memories 调用规范、过滤器构造与类别分组规则;并结合插件源码中的身份解析、项目 ID 解析、类别体系与共享检索脚本,说明这些参数在真实实现中如何被填充与消费,帮助读者在 Claude Code、Cursor、Codex 等 AI 编码环境中把 tour 作为项目记忆审阅、团队 onboarding 与知识盘点的主要入口。
一、tour 技能是什么:定位与入口
tour 是 Mem0 插件(位于 integrations/mem0-plugin 目录)内置的 17 个 slash 技能之一,定义在 skills/tour/SKILL.md。技能文件的 frontmatter 明确其用途:
Browses all stored memories grouped by category with full content display. Use when reviewing all project memories, exploring stored knowledge, onboarding to a project, or getting an overview of captured decisions, conventions, and learnings.
翻译过来即:按类别浏览当前项目已存储的全部记忆并完整展示内容,典型场景是审阅项目记忆、探索已沉淀的知识、新项目 onboarding,或总览已捕获的决策、约定与经验教训。插件 README 的技能表把它描述为 /mem0:tour —— "Browse all memories grouped by category",并将其列为安装验证步骤之一("Try /mem0:remember "we use TypeScript" then /mem0:tour to see it stored"),即写完一条记忆后立刻用 tour 验证它是否落库。
tour 与同目录下的 skills/peek/SKILL.md 是"重/轻"互补关系:peek 是带查询词的紧凑单行检索("Lighter than /mem0:tour"),tour 则是无查询词时的全量类别化浏览。tour 本身也吸收了 peek 的紧凑模式(见下文 peek mode),因此 tour 技能文档实际上覆盖了三条执行路径。
二、三条执行路径:tour 的模式路由
tour 技能文档把调用参数解析为互斥的三种模式,路由规则非常明确:
| 调用形式 | 模式 | 数据范围 | 输出形态 |
|---|---|---|---|
/mem0:tour |
完整漫游 | 当前项目全部记忆 | 按类别分组、完整内容、降序计数 |
/mem0:tour <query> |
Peek mode | 当前项目语义检索 | 紧凑单行结果 |
/mem0:tour --all-projects [query] |
跨项目模式 | 全部项目 | 按 app_id 再按类别分组 |
文档中的路由原文:"If --all-projects is NOT present, use the standard single-project flow below"(无跨项目标志时走单项目流程);"If no query argument and no --all-projects flag, use the full tour flow below"(既无查询词也无标志时走完整漫游)。即:先判 --all-projects,再判 query 是否存在,最后才落到完整漫游。
三种模式共同依赖两个 MCP 工具——get_memories(带过滤与分页的记忆列表)和 search_memories(带过滤与重排的语义搜索)。这两个工具来自插件连接到的 Mem0 远端 MCP 服务器,连接配置见 mcp_config.json(以 MEM0_API_KEY 环境变量插值 Authorization: Token ${MEM0_API_KEY} 请求头),工具全集见 README 的 "MCP Tools" 表:add_memory、search_memories、get_memories、get_memory、update_memory、delete_memory、delete_all_memories、delete_entities、list_entities。
三、完整漫游:六步执行流程
无参数调用 /mem0:tour 时,技能文档定义了六步流程。
Step 1:拉取项目全量记忆
调用 get_memories,过滤条件与分页参数固定:
filters={"AND": [{"user_id": "<active_user_id>"}, {"app_id": "<active_project_id>"}]}
page_size=100
这里的两个占位符不是装饰。user_id 与 app_id 正是 Mem0 平台给记忆打的两级作用域:记忆按"用户 × 项目"归属,所有检索都必须显式声明范围。插件侧对这两个值有确定性的解析规则(见第五节源码剖析):user_id 默认取 MEM0_USER_ID 环境变量,缺失时回退到系统 $USER,再回退到 default;app_id(项目 ID)优先取 MEM0_PROJECT_ID,其次查 ~/.mem0/project_map.json 的本地映射,再回退到 git remote 的 slug(如 owner-repo 形式),最后才是当前目录 basename。这意味着 tour 的"当前项目"边界是可预测、可覆写的——/mem0:switch-project 技能正是通过覆写这一解析来切换作用域。
Step 2:三个并行的补充语义检索
在拉取全量的同时,并行发起三条 search_memories 调用,针对关键主题拿一份按相关性排序的结果:
query="architecture decisions design choices"
query="bugs errors failures anti-patterns"
query="project setup tooling conventions preferences"
三者统一参数:filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}]}、top_k=10、rerank=true。
文档中有一条关键警告:
Do NOT filter by
metadata.typein these calls. The platform auto-assignscategories— filtering onmetadata.typemisses memories that were auto-categorized but don't have an explicitmetadata.type.
即不要在这三个调用里按 metadata.type 过滤:Mem0 平台会自动给记忆分配 categories 字段,而自动归类出来的记忆往往没有显式的 metadata.type,一旦加了该过滤条件,这部分记忆就会被漏掉。这是 tour 文档中最容易踩的坑,也解释了为什么 Step 3 的分组规则把平台 categories 字段放在第一优先级。
Step 3:合并去重与类别归组
所有结果(全量列表 + 三路检索)按记忆 ID 合并去重,然后为每条记忆确定分组,优先级为:
- 平台
categories字段(每条记忆上的数组,由 Mem0 自动分配),取第一个类别值; metadata.type字段(如存在,通常由 hooks/agent 显式写入),作为无categories时的回退;- 两者皆无则归入 "other" 桶。
类别名到显示名的映射表(需完整继承):
| Platform category / metadata.type | Display name |
|---|---|
architecture decisions、architecture_decisions、decision |
Architecture Decisions |
anti patterns、anti_patterns、anti_pattern |
Anti-Patterns |
task learnings、task_learnings、task_learning |
Task Learnings |
coding conventions、coding_conventions、convention |
Coding Conventions |
user preferences、user_preferences、user_preference |
User Preferences |
project profile、project_profile |
Project Profile |
tooling setup、tooling_setup、environmental |
Tooling & Setup |
technology、professional_details |
Tooling & Setup |
session_state |
Session State |
compact_summary |
Compact Summaries |
| 其他任何值 | Other |
注意这张表同时兼容空格/下划线/单复数/中文命名习惯的多种写法——因为 categories(平台自动分配,自然语言风格)与 metadata.type(hook 写入,蛇形命名)两种来源的取值风格并不统一,映射表就是两者的归一化层。
Step 4:展示规则
分组按记忆数降序排列;每个非空组输出:
## <display_name> (<count> memories)
- <full_memory_content> (score: <similarity_score_if_available>)
- ...
三条展示纪律:
- 每条记忆展示完整文本,不截断(与 peek 模式的 80 字符截断形成对比);
- 某组超过 10 条时,按新近度(来自检索调用的则按相似度分)展示前 10 条,并标注
... and <N> more; - 空组整组跳过,不打印空标题。
Step 5 / Step 6:汇总行与空态
结尾输出总数行:
<N> memories across <M> categories — project: <project_id>, branch: <active_branch>
若本项目零记忆,输出空态提示:
No memories stored yet for project <project_id>.
Run /mem0:onboard to import project files, or start working — mem0 captures learnings automatically.
这里把空态直接引向 /mem0:onboard(项目文件导入向导)——tour 因此同时承担了"记忆系统是否在工作"的健康检查职能,与 /mem0:health、/mem0:stats 一起构成 README 推荐的三步验证链。
四、Peek 模式与跨项目模式:紧凑检索与多项目汇总
Peek mode(带 query、无 --all-projects)
/mem0:tour auth middleware 这类调用走紧凑模式,执行两个并行的 search_memories:
- 宽检索:
query=<query>,filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}]}、top_k=10、rerank=true; - 定向检索:在宽检索基础上追加
{"metadata": {"type": "decision"}}过滤,top_k=5、rerank=true。
注意与完整漫游 Step 2 的差别:peek 模式允许按 metadata.type=decision 做定向召回(它只要紧凑的 top 结果,丢一点自动归类记忆无妨),而完整漫游的三路补充检索则禁止该过滤(要保证类别全景)。两路结果按 ID 去重后,以固定格式输出:
## mem0 search: "<query>" (<N> results)
1. [decision] Auth module uses JWT with RS256 keys (2025-05-15) [mem0:a3f8b2c1]
2. [anti_pattern] Don't use symmetric HS256 — leaked in env (2025-05-10) [mem0:7e2d9f4a]
3. [convention] All middleware in src/middleware/ (2025-05-08) [mem0:c4d5e6f7]
单行格式为 <number>. [<type>] <content, 80 chars> (<date>) [mem0:<short_id>]——内容截断 80 字符,[mem0:<short_id>] 是 8 位十六进制短引用,与 peek 技能的"引用解析"能力打通:/mem0:peek 或 tour 结果中的 [mem0:a3f8b2c1] 可以直接作为参数回查单条记忆的全文。无结果时输出 No memories matching "<query>" for project <project_id>.。
Cross-project 模式(--all-projects)
/mem0:tour --all-projects [query] 跨全部项目搜索,核心变化只有一个:去掉 app_id 过滤。
get_memories用filters={"AND": [{"user_id": "<active_user_id>"}]}、page_size=200——无app_id;- 若同时给了 query,再跑
search_memories,top_k=20,同样无app_id; - 结果先按
app_id分组,再在每个项目内按类别分组; - 展示模板:
## <app_id_1> (<N> memories) ← current
**Architecture Decisions** — <memory content>
...
## <app_id_2> (<N> memories)
...
<N> memories across <M> projects
- 当前项目在标题行以
← (current)标记。
app_id 过滤的有/无,就是"单项目"与"跨项目"的全部区别,这与第五节中 _search.py 的过滤器构造逻辑完全一致。
五、源码纵深:tour 参数背后的解析与消费链路
tour 文档中的占位符(<active_user_id>、<active_project_id>、rerank、filters 结构)在插件脚本里都有确定的实现,理解它们能预判 tour 的边界行为。
user_id 与 API key 的解析
scripts/_identity.py 给出两级解析链:
- API key 按序取:
MEM0_API_KEY环境变量 →CLAUDE_PLUGIN_OPTION_API_KEY(Claude Code userConfig 注入)→ 旧版CLAUDE_PLUGIN_OPTION_MEM0_API_KEY→ 正则扫描~/.zshrc、~/.bashrc等 profile 文件(专门覆盖桌面应用不继承 shell 环境变量的场景); resolve_user_id():MEM0_USER_ID显式覆写 →$USER→ 字面量"default"。
所以 tour 的 <active_user_id> 在多数机器上就是系统用户名;多身份协作场景用 MEM0_USER_ID 切换即可,且该覆写同时影响 remember、peek 等所有技能的读写作用域。
app_id 的四级回退
scripts/_project.py 的 resolve_project_id() 实现了四级回退:MEM0_PROJECT_ID 环境变量 → ~/.mem0/project_map.json 按 cwd 查表(附带按 remote hash 的"自愈"查表,目录改名后仍能命中并回写新 key)→ git remote get-url origin 转 slug → cwd 的 basename。这意味着:tour 末尾汇总行里的 project: <project_id> 对 git 仓库通常是 owner-repo 形式;同一仓库被 clone 到不同路径不会分裂成两个项目(只要 remote 一致),而纯本地目录则以目录名作为项目 ID。resolve_branch() 则从 git 解析当前分支,对应汇总行尾的 branch: <active_branch>。
过滤器构造与 rerank 默认值
scripts/_search.py 是所有预取 hook 共享的检索助手,把 POST https://api.mem0.ai/v3/memories/search/ 封装为一次函数调用,其构造逻辑与 tour 文档的 filter 写法一一对应:
- 非全局检索时,过滤条件组装为
{"AND": [{"user_id": ...}, {"app_id": ...}, (可选 "metadata": {"type": ...})]}——与 tour Step 1/2 的写法一致,也印证了"追加metadata.type会收窄结果"的原因; - 全局模式使用
{"OR": [{"user_id": "*"}]}且不含app_id,即跨项目语义; should_rerank()(第 18-33 行)说明:REST 搜索端点在省略rerank时不会重排,此时结果按原始向量相似度排序,最相关记忆可能掉出top_k窗口,因此 hook 注入路径默认开启 rerank,并可用MEM0_RERANK=0/false/no/off关闭。tour 文档中每个search_memories调用都显式写rerank=true,正是为了在类别展示前拿到可靠的相关性排序;- 该助手还带有 5 秒超时与失败静默(返回空列表并打 stderr 日志),这是 hook 场景的容错设计;tour 本身走 MCP 工具调用,但该文件说明了平台搜索端点的行为前提。
类别体系:tour 分组的供给侧
tour 的显示名映射表(第三节)对应插件自动安装的"编码优化类别体系"。scripts/setup_coding_categories.py 定义了 17 个编码类别——architecture_decisions、anti_patterns、task_learnings、tooling_setup、bug_fixes、coding_conventions、user_preferences、dependency_decisions、performance_findings、security_constraints、testing_patterns、data_model、api_contracts、deployment_runbook、team_norms、domain_glossary、experiment_results——每个类别附一段描述文本,供平台在自动归类时参照。脚本行为:python setup_coding_categories.py 干跑对比现状与提案,--apply 才真正调用 client.project.update(custom_categories=[...]),且 project.update 总是整体替换类别列表;幂等性由 _categories_match() 的键集比对保证。该配置在会话启动时由生命周期钩子后台执行一次并缓存于 ~/.mem0/categories_setup.json。
这解释了 tour 分组表的来源:hook/agent 显式写入的 metadata.type 用的是这套蛇形命名(如 architecture_decisions),而平台自动分配的 categories 可能是自然语言风格(如 architecture decisions),tour 的映射表同时覆盖两套命名,保证两侧记忆都落入正确的显示分组;project_profile、session_state、compact_summary 等则对应 hooks.json 中会话启动、Stop、PreCompact 等生命周期钩子自动写入的记忆类型。
与生命周期钩子的关系
hooks.json 声明了 SessionStart(加载既有记忆作为引导上下文)、UserPromptSubmit(注入相关记忆)、PreToolUse(阻止直接写 MEMORY.md、对 mcp__mem0__* 工具调用强制 user_id/app_id 元数据、读文件时扫描相关记忆)、Stop(提醒代理在回合结束前持久化学习)、PostToolUse(统计与 bash 错误扫描)等事件处理器。其中 PreToolUse 的 mem0-enforce-metadata 钩子(scripts/enforce_metadata_defaults.sh)正是 tour Step 3 中 metadata.type 回退来源的写入方:它保证记忆写入时带上类型元数据,让 tour 的三级分组规则有稳定的回退层可用。
六、实战要点与边界
- 验证记忆落库的首选动作:README 推荐的验证链是
/mem0:remember写入 →/mem0:tour查看,配合/mem0:health检查连通性、/mem0:stats看计数。tour 输出为空时,按空态提示先跑/mem0:onboard。 - 作用域可预测:tour 看到什么,取决于
user_id×app_id两级作用域;怀疑"看不到某些记忆"时,先确认MEM0_USER_ID、MEM0_PROJECT_ID覆写与~/.mem0/project_map.json映射,而不是怀疑检索本身。 - 全量漫游禁用
metadata.type过滤:这是 tour 文档明确写出的平台行为差异(自动categoriesvs 显式metadata.type),在自定义任何 tour 变体时都应当保留这一约束。 - rerank 的代价与收益:每个
search_memories都开rerank=true,换取类别展示内的相关性排序;hook 注入路径的默认实现与MEM0_RERANK开关说明平台侧对重排延迟有明确预算意识,tour 的三路并行检索把这部分延迟摊薄了。 - 跨项目模式的容量参数:跨项目
get_memories用page_size=200(单项目为 100)、检索top_k=20(peek 为 10/5),分组先按app_id再按类别,当前项目以← (current)标记。
七、参考文件索引
| 内容 | 路径 |
|---|---|
| tour 技能定义(本文主体文档) | integrations/mem0-plugin/skills/tour/SKILL.md |
| peek 技能(紧凑检索对照) | integrations/mem0-plugin/skills/peek/SKILL.md |
| 插件总览、MCP 工具表、17 技能列表 | integrations/mem0-plugin/README.md |
| MCP 服务器连接配置 | integrations/mem0-plugin/mcp_config.json |
| 生命周期钩子声明 | integrations/mem0-plugin/hooks.json |
| 身份(API key / user_id)解析 | integrations/mem0-plugin/scripts/_identity.py |
| 项目 ID / 分支解析 | integrations/mem0-plugin/scripts/_project.py |
| 共享检索助手(filters / rerank) | integrations/mem0-plugin/scripts/_search.py |
| 编码类别体系(17 类) | integrations/mem0-plugin/scripts/setup_coding_categories.py |
| 元数据强制钩子脚本 | integrations/mem0-plugin/scripts/enforce_metadata_defaults.sh |
| 插件清单(版本/描述) | integrations/mem0-plugin/plugin.json |
需要说明的适用前提:tour 依赖已安装 Mem0 插件并连通远端 MCP 服务器、MEM0_API_KEY 已配置(见 README 的安装步骤);类别自动归类的效果依赖插件的编码类别体系是否已随会话启动脚本应用。除技能文档明确给出的 page_size/top_k 参数外,本文所有行为结论均来自上述仓库文件,未引入外部数据。
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