ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

mem0 Export Skill 解析:把 AI Agent 项目记忆导出为可移植 Markdown 的完整实现(mem0-plugin)

mem0 Export Skill 解析:把 AI Agent 项目记忆导出为可移植 Markdown 的完整实现(mem0-plugin) mem0 Export Skill 解析把 AI Agent 项目记忆导出为可移植 Markdown 的完整实现mem0-plugin【免费下载链接】embedchainThe Memory Layer for AI Agents - Drop-in memory infrastructure for AI agents and apps. Context that persists. Built for production.项目地址: https://gitcode.com/GitHub_Trending/em/embedchain本篇围绕 mem0 插件的exportSkill/mem0:export命令背后展开完整还原其解析身份 → 分页拉取全量记忆 → 格式化为 YAML frontmatter 块 → 写入导出文件 → 打印汇总的五步流程并结合插件配套脚本parse_export_file.py、Python SDK 的get_all()分页实现与测试用例解释导出文件为何必须严格遵守该格式以及它如何与importSkill 构成备份—迁移闭环。读完后你可以掌握如何在 Agent 会话中正确执行项目记忆导出、逐字段理解导出文件格式契约以及如何用仓库自带的解析器验证导出结果的可导入性。一、Mem0 Export 是什么定位与适用场景export是 mem0-plugin 内置的 17 个/mem0:技能之一其技能定义位于 export/SKILL.md技能头部的 frontmatter 声明了它的用途Exports all project memories to a portable Markdown file for backup or migration. Use when backing up memories, migrating to another project, sharing memory state with teammates, or archiving before cleanup.即把当前项目在 Mem0 平台上的全部记忆导出为一个可移植的 Markdown 文件。插件 README 的技能表中将其描述为 Export memories to portable Markdown对应的命令为/mem0:export。适用场景原文档明确列出备份backing up memories清理或删除记忆前先留档跨项目迁移migrating to another project与/mem0:import配合把 A 项目的记忆状态搬到 B 项目团队共享sharing memory state with teammatesMarkdown 文件可直接进版本库或随 PR 流转归档archiving before cleanup批量删除前的快照。需要说明的前提该 Skill 运行在已安装 mem0 插件的 AI 编程环境Claude Code / Cursor / Codex 等中通过插件注册的远程 MCP Server 提供get_memories、add_memory等工具见 mcp_config.json认证头为Token ${MEM0_API_KEY}。也就是说导出动作由 Agent 调用get_memories工具完成而不是本地直连存储——这也是可移植的关键文件本身不依赖任何本地状态。二、执行流程全解五步导出以下流程完整继承自 export/SKILL.md 的 Execution 章节并逐步补充仓库内的实现佐证。Step 1解析身份Resolve identity导出前先确定导出谁在哪个项目的记忆涉及两个标识符user_id取MEM0_USER_ID环境变量未设置则取$USER再没有则用default。project_id在 API 中作为app_id使用取MEM0_PROJECT_ID环境变量否则走项目解析器project resolver。这条解析规则并非 Skill 的孤立约定而是整个插件的统一身份体系。在 _identity.py 中可以确认resolve_user_id()的实现与文档完全一致def resolve_user_id() - str: explicit os.environ.get(MEM0_USER_ID, ).strip() if explicit: return explicit return os.environ.get(USER) or default而 project resolver 的完整优先级定义在 _project.py 的resolve_project_id()中按顺序为MEM0_PROJECT_ID环境变量显式覆盖~/.mem0/project_map.json按 cwd 查表命中失败时还会按 git remote URL 的 SHA-256 哈希做自愈式兜底文件夹改名/移动后仍能找回旧映射git remote slug剥离协议前缀与.git后缀取owner-repo如gitgithub.com:mem0ai/mem0.git→mem0ai-mem0兼容 HTTPS、SSH、ssh://、git://及自定义 host 别名等多种 URL 形态兜底当前工作目录的 basename。从源码结构看同一文件里的resolve_branch()会执行git branch --show-current失败返回unknown——这正好对应导出 frontmatter 中的branch字段的典型来源。理解了这条解析链就能解释为什么MEM0_PROJECT_ID是导出前最值得检查的变量它决定了导出文件名中的project_id以及拉取记忆时app_id过滤条件的取值。Step 2分页拉取全部记忆Fetch all memoriesSkill 指定调用get_memories工具参数为filters{AND: [{user_id: active_user_id}, {app_id: active_project_id}]}page_size200分页终止条件原文档明确要求若响应是分页的——即结果中包含nextcursor或本条数等于page_size——就继续翻页直到取完所有记忆。这一点在 Python SDK 的实现中得到印证。插件走的是远程 MCP 的get_memories工具其底层语义与 SDK 的get_all()一致见 main.pydef get_all(self, options: Optional[GetAllMemoryOptions] None, **kwargs) - Dict[str, Any]: Retrieve all memories, with optional filtering. ... Returns: A paginated dict: {count: int, next: str | None, previous: str | None, results: [...]} # Reject top-level entity params - must use filters instead invalid_keys ENTITY_PARAMS set(kwargs.keys()) if invalid_keys: raise ValueError( fTop-level entity parameters {invalid_keys} are not supported in get_all(). fUse filters{{user_id: ...}} instead. )两个关键事实可以直接指导导出实现返回体是标准分页字典{count, next, previous, results}。因此 Skill 中的结果包含nextcursor判断与 SDK 契约吻合请求会POST到/v3/memories/并把page、page_size作为 query 参数附带。身份参数必须放在filters里SDK 显式拒绝顶层的user_id/app_id等实体参数抛出ValueError并提示改用filters{user_id: ...}。这正是 export Skill 把身份写进filters的AND数组而非顶层的原因。分页参数本身由 types.py 的GetAllMemoryOptions定义filters、page、page_size另支持start_date/end_dateISO 8601 时间窗、categories、show_expired、latest_only。export 场景只用到filterspage_size但这也提示如果只需要导出某批分类的记忆可以在此基础上追加categories过滤属于原文档流程之外的可选扩展官方 Skill 默认拉全量。Step 3把每条记忆格式化为 YAML frontmatter 块这是导出格式的核心契约。原文档规定每条记忆记录产生如下精确格式--- id: memory.id created_at: memory.created_at type: memory.metadata.type or confidence: memory.metadata.confidence or branch: memory.metadata.branch or files: memory.metadata.files joined with , or categories: memory.categories joined with , or --- memory.memory or memory content string各字段含义与来源字段取值来源缺失时写法idmemory.id平台侧记忆主键—created_atmemory.created_at时间戳如2024-01-15T10:00:00Z空串typememory.metadata.type记忆类型标签空串confidencememory.metadata.confidence置信度空串branchmemory.metadata.branch捕获时的 git 分支空串filesmemory.metadata.files列表用, 拼成单行空串categoriesmemory.categories列表用, 拼成单行空串原文档的格式注意事项必须严格遵守---分隔符必须独占一行且行尾无多余空白files与categories以逗号分隔的形式写在同一行每条记忆正文之后、下一条---之前留一个空行为了可读性字段缺失或为 null 时写空字符串绝不能写null。Step 4写入导出文件输出文件名规则原文档原文mem0-export-project_id-YYYY-MM-DD.md其中YYYY-MM-DD为当天 UTC 日期。文件通过 Write 工具或等效手段写入当前工作目录。命名中包含project_id与日期有两个实际意义其一import 侧是靠文件名里的mem0-export子串来发现候选文件的见后文project_id让多项目导出互不混淆其二UTC 日期保证同一天的重复导出文件名稳定便于覆盖式刷新。Step 5打印汇总Exported N memories to filenameN为实际写入的记忆块总数。错误处理原文档 Error Handling 全量继承若get_memories返回错误或零条记忆输出No memories found for project project_id. Nothing exported.若写文件失败向用户报告错误。值得注意的设计是空结果被视为正常分支而非报错——导出零记忆不会中断流程只是明确告知未导出任何内容这对自动化脚本友好。三、格式契约的底层原理为什么必须精确export 文件不是给人看的普通笔记而是import侧解析器的结构化输入。仓库里的 parse_export_file.py 就是这条契约的反向实现读它可以从消费者视角理解每个格式细节为什么不能含糊分块边界解析器用正则(?m)^---\s*$按整行---切分全文奇偶下标配对frontmatter 正文。这解释了 export 侧---必须独占一行的原因——一旦分隔符混入正文或行尾多出不规则字符切分结构即被破坏。frontmatter 取值规则_parse_frontmatter()用^([A-Za-z_][A-Za-z0-9_]*)\s*:\s*(.*)$匹配key: value只按第一个冒号切分值里可以合法包含冒号因此created_at: 2024-01-01T10:00:00Z这类时间戳能完整保留。列表字段files、categories由_parse_list_field()按逗号拆分并去除空白空值归一为[]——对应 export 侧逗号分隔单行的写法。空内容跳过正文为空或纯空白的块直接丢弃CLI 入口保证任何异常缺参、文件不存在都输出[]且退出码为 0让上层 Skill 可以安全地解析失败即[]地分支处理。测试用例 test_parse_export_file.py 中的test_parse_blocks_round_trip专门验证了按 export Skill 规则生成的块能被解析器无损还原——即导出格式 → 解析是一个被单测守护的往返契约round tripblock ( ---\n fid: {memory_id}\n fcreated_at: {created_at}\n ... ffiles: {, .join(files)}\n fcategories: {, .join(categories)}\n ---\n f{memory_content}\n \n ) records parse_blocks(block) assert r[files] files assert r[content] memory_content此外还有针对多行正文、缺失可选字段、含冒号值、空输入等边缘情况的测试。实践含义是手工编辑导出文件时宁可少写字段也不能改坏---结构与逗号分隔写法否则对应记录会在导入阶段被静默跳过。四、导出之后与 import Skill 的备份—迁移闭环导出的真正价值在 import/SKILL.md 中兑现两者共用同一套文件格式。/mem0:import filename的流程是按文件名包含mem0-export的.md文件定位导出文件多个时询问用户运行python3 PLUGIN_ROOT/scripts/parse_export_file.py file得到 JSON 记录数组每条含id、type、confidence、branch、files、categories、content对每条记录调用add_memorytextcontent、user_id/app_id取当前活跃身份、metadata回填type/confidence/branch/files非空才传并附加source: importinferFalse原文档明确要求不传原始id——平台会分配新 ID单条失败不中断最后输出Imported N/total memories into project project_id。由此形成完整的运维闭环/mem0:export留档 → 文件随版本库/IM 流转 → 目标项目/mem0:import恢复。由于导入是幂等可重跑的去重由平台处理导出文件可以放心地多次使用。五、实操清单与验证方法在 Agent 会话中执行导出的最小前提与步骤确认身份MEM0_API_KEY已配置插件 MCP 认证依赖它MEM0_USER_ID、MEM0_PROJECT_ID按需显式设置否则按前文的解析链回退到$USER/default与 git remote slug。发起导出在支持该插件的客户端中运行/mem0:export或在对话中要求导出本项目的全部记忆Agent 将按 export/SKILL.md 的五步执行。核对产物当前工作目录应出现mem0-export-project_id-YYYY-MM-DD.md终端输出Exported N memories to filename。验证可导入性可选用仓库自带解析器做一次试解析确认块数量与字段python3 integrations/mem0-plugin/scripts/parse_export_file.py ./mem0-export-project_id-YYYY-MM-DD.md输出为 JSON 数组输出[]说明文件格式不符合契约多半是---分隔行被改动应重新导出而非手工修补。六、小结mem0-plugin 的exportSkill 用一份 5 步指令定义了 Agent 记忆的可移植载体身份解析决定导出范围user_idapp_id的AND过滤page_size200与nextcursor 保证全量拉取YAML frontmatter 块格式则是一条被 parse_export_file.py 与 test_parse_export_file.py 双向守护的结构化契约。理解这条导出格式 → 解析 → 重新入库的链路后你就能把 Mem0 的项目记忆当作普通代码资产一样备份、评审与迁移——这正是该 Skill 在 插件 README 中列出的 backup / migration / sharing / archiving 四个场景能够落地的全部基础。【免费下载链接】embedchainThe Memory Layer for AI Agents - Drop-in memory infrastructure for AI agents and apps. Context that persists. Built for production.项目地址: https://gitcode.com/GitHub_Trending/em/embedchain创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表