
在 n8n 工作流中接入 Mem0 长期记忆mem0/n8n-nodes-mem0 社区节点完整实战指南【免费下载链接】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/embedchainmem0/n8n-nodes-mem0是一个 n8n 社区节点让工作流具备跨会话的长期记忆从对话消息中提取并存储记忆再按用户/代理等实体维度语义检索回忆。本篇基于仓库内 README 与官方集成文档 docs/integrations/n8n.mdx结合节点源码 Mem0.node.ts、凭据实现 Mem0Api.credentials.ts 和离线测试 Mem0.node.test.ts讲清安装、六个操作的参数细节、异步提取与轮询机制、实体过滤的 OR 语义以及如何把它挂给 n8n 的 AI Agent 当工具用。读完你可以独立完成从安装、建凭据到先查记忆、后写记忆工作流的完整搭建并能定位超时、空结果等常见问题。节点定位与包结构Mem0 定位是The Memory Layer for AI Agents——给 AI 代理与应用提供即插即用的记忆基础设施。该节点将托管版 Mem0 REST API 封装为 n8n 原生节点只需一个Memory资源、六个操作即可覆盖记忆的完整生命周期add / search / get / get many / update / delete。从 package.json 可以看到关键工程事实包名mem0/n8n-nodes-mem0当前版本 0.1.4运行环境要求node 20.15打包入口为index.js该文件有意留空n8n 实际通过 package.json 中的n8n键发现编译产物dist/nodes/Mem0/Mem0.node.js与dist/credentials/Mem0Api.credentials.js构建脚本buildtsc编译 gulp build:iconsgulpfile.js 负责把节点图标 svg 与节点元数据Mem0.node.json复制到 dist因为 tsc 只产出 .js节点元数据 Mem0.node.json 将其归类为AI / Memory类别即安装后出现在 n8n 节点面板的 AI → Memory 分组下。安装与凭据配置安装前提按 docs/integrations/n8n.mdx 的说明安装社区节点需要满足三个前提有一个 Mem0 API Key在 app.mem0.ai 的 Settings → API Keys 页面创建自托管self-hosted的 n8n 实例——从 npm 安装社区节点是自托管功能n8n Cloud 只提供官方验证过的节点实例 Owner 权限因为只有 Owner 能安装社区节点。安装路径n8n 中进入Settings → Community Nodes选择Install输入mem0/n8n-nodes-mem0勾选风险确认框后安装。安装完成后在节点面板搜索Mem0应能看到带 Memory 资源的节点。Mem0 API 凭据凭据类型定义在 Mem0Api.credentials.ts只有两个字段字段说明API Key必填Mem0 API key以m0-开头输入框为密码类型Base URL默认https://api.mem0.ai仅在自托管或非默认部署时覆盖鉴权方式在authenticate中声明为 generic 头注入authenticate: IAuthenticateGeneric { type: generic, properties: { headers: { Authorization: Token {{$credentials.apiKey}}, }, }, };即每个请求都携带Authorization: Token key与 Mem0 官方 SDK 的鉴权方案一致。凭据的Test按钮会发起一次廉价的GET /v1/ping/请求来验证 key 是否有效无需消耗任何记忆配额。六个操作总览README 中的操作表完整继承了官方 API 端点映射节点在 Mem0.node.ts 中为每个操作定义了独立的参数面板Operation说明EndpointAdd从消息中提取并存储记忆POST /v3/memories/add/Search对已存记忆做语义检索POST /v3/memories/search/Get Many列出已存记忆单页或Return AllPOST /v3/memories/Get按 ID 取单条记忆GET /v1/memories/{id}/Update更新记忆文本或元数据PUT /v1/memories/{id}/Delete按 ID 删除单条记忆DELETE /v1/memories/{id}/Add消息、实体与作用域Add 操作的必填/核心参数见源码 L98-L225 的properties定义MessagesfixedCollection每条含Roleuser/assistant/system默认user与Content节点在调用前会校验至少一条消息否则报At least one message is requiredUser ID把记忆关联到该用户Wait for Completion布尔默认true决定是否轮询等待提取完成下一节详述Additional Fields集合控制这次调用提取什么字段请求体键用途Agent IDagent_id按代理作用域App IDapp_id按应用/项目作用域Run IDrun_id按单次会话/运行作用域Metadata (JSON)metadata附加到每条提取记忆的任意 JSON非法 JSON 会报Invalid JSON in Metadata fieldInferinfer默认true关闭后原文存储消息不跑 LLM 提取Custom Instructionscustom_instructions自由文本指导提取器本次保留/忽略什么Custom Categoriescustom_categoriesJSON 数组元素为{category: description}对象为本次调用替换项目级分类目录Includesincludes仅提取匹配该描述的记忆Excludesexcludes跳过匹配该描述的记忆组装请求体的逻辑在 execute 中L410-L461infer缺省取true各实体 ID 与includes/excludes非空才写入 bodymetadata与custom_categories支持字符串或对象两种形态字符串会先JSON.parse再传入。关键的一点是节点在发请求前做了实体守卫// API requires at least one entity id — fail clearly instead of a raw 4xx. if (!body.user_id !body.agent_id !body.run_id !body.app_id) { throw new NodeOperationError( this.getNode(), Add requires at least one of User ID, Agent ID, Run ID, or App ID, ...); }也就是说四个实体 ID 全空时节点会在本地先失败并给出清晰错误而不是把请求打出去再收到一个裸的 4xx。测试用例 Mem0.node.test.ts 验证了这一行为同时也验证了仅填app_id不带user_id是合法的实体作用域L78-L92。Add 的异步提取与轮询机制这是该节点最有工程含量的部分。Add 默认走 LLM 异步提取API 返回event_id与status: PENDING|RUNNING节点随后轮询直到终态。两个互相独立的开关Wait for Completion默认开——决定是否轮询。关掉则立即返回 event IDInfer默认开位于 Additional Fields——决定 API 是否执行 LLM 提取。关掉则消息原文入库。轮询常量定义在文件头部Mem0.node.ts L17-L18const POLL_INTERVAL_MS 1500; const MAX_POLL_ATTEMPTS 40; // ~60s ceiling即每 1.5 秒查询一次GET /v1/event/{event_id}/最多 40 次、约 60 秒封顶。pollEvent函数L598-L626的处理逻辑status SUCCEEDED返回results数组与 Search/Get Many 的输出形状保持一致是干净的数组而非外层信封status FAILED抛Mem0 memory event {id} failed: {reason}40 次轮询后仍未终态抛Timed out waiting for memory event {id} to complete——注意超时不等于写入失败只是服务端还在处理若 Add 首次响应本身就是终态SUCCEEDED/FAILED则跳过轮询直接解包results。测试中用一个永远返回PENDING的 mock 验证了超时路径test/Mem0.node.test.ts L109-L127并且全局 mock 了n8n-workflow的sleep让轮询在测试中瞬时完成。另一个安全细节轮询与 Get/Delete 的 URL 拼接都经过encodeURIComponent测试用../v1/entities这类恶意 ID 验证了路径穿越会被转义为..%2Fv1%2FentitiesL173-L181、L183-L199。Search语义检索Search 的请求体组装L484-L499const body { query, // Query 参数必填 output_format: v1.1, // 固定使用 v1.1 输出格式 top_k, // 来自 Limit 参数默认 50最小 1 }; body.filters buildEntityFilters({...}); // 实体过滤见下节Limit是数值参数minValue: 1默认 50映射为 API 的top_k。返回results数组每个元素即一条记忆 item。Get Many分页与 Return AllGet Many 支持两种模式L502-L530单页模式returnAll: false默认使用Page默认 1最小 1与Page Size默认 50查一页Return AllreturnAll: true节点自动翻页——从第 1 页开始直到某页结果数小于pageSize或响应中没有next指针为止且有一个page 10000的硬上限防失控。测试用例模拟了满页 → 短页的两轮翻页L201-L210验证合并后输出[a,b,c]。Get / Update / Delete按 ID 操作三者共用Memory ID必填字段L342-L351。Update 额外接受Text新记忆文本与Metadata (JSON)且二者至少要提供一个否则报Provide text or metadata to updateL549-L553只传了哪个就只更新哪个未传的键不会进入请求体。Delete 无请求体直接DELETE /v1/memories/{id}/。实体过滤的 OR 语义重要设计Search 与 Get Many 都接受User ID / Agent ID / App ID / Run ID四个字段且至少填一个——API 会拒绝没有实体作用域的查询节点则在校验阶段就本地失败。核心实现是buildEntityFiltersMem0.node.ts L577-L595return clauses.length 1 ? clauses[0] : { OR: clauses };只填一个实体 ID 时过滤条件是扁平的{ user_id: u1 }填多个时组合为OR并集例如{ OR: [{ user_id: u1 }, { agent_id: a1 }, { app_id: p1 }, { run_id: r1 }] }README 对此有一段值得细读的解释Mem0 对每个实体分别建索引所以user_id与agent_id之间的 AND 即使对同时写了两个 ID 的记忆也匹配不到任何东西。多 ID 用 OR 是有意为之取并集、扩大召回不是偷懒。如果你的目标是收窄而不是放宽正确做法是对每个实体 ID 各跑一次操作。测试用例把这一语义固化下来test L135-L163单 ID 发扁平 filter、四 ID 发 OR 数组、空 ID 报错。作为 AI Agent 的工具使用节点在描述中声明了usableAsTool: trueMem0.node.ts L32-L33意味着 n8n 的 AI AgentTools Agent节点可以把它当工具直接挂载无需额外接线让 Agent 自主记住与回忆。官方文档给出的典型形态docs/integrations/n8n.mdxChat Trigger → AI Agent ──tool──▶ Mem0 (Search) ──tool──▶ Mem0 (Add)挂载一个配置为Search的 Mem0 节点和一个配置为Add的 Mem0 节点Agent 会在回答前先查记忆、在有效对话后回写持久事实。注意两个节点要使用相同的 User ID否则写进去的记忆查不出来。还有一个时序要点记忆写入默认是异步的。即使 Add 开着 Wait for Completion此时节点已等到终态才放行如果你的 Add 关了等待、或依赖其他写入路径在搜索刚写入的内容前应留一点间隔——官方 Quickstart 中的两节点示例Manual Trigger → Mem0 Add → Mem0 Search之所以能直接跑通正是因为 Wait for Completion 默认开启Search 节点执行时提取已完成。遥测与归因README 明确声明该节点不发送任何第三方遥测不接触独立的分析服务。它唯一的上报是 Mem0 自己的 API 请求且每个请求都附带查询参数source: N8NMem0.node.ts L387-L388让 Mem0 能看到该集成路径的聚合用量。测试用例 test L129-L133 断言了每个请求的qs.source恒为N8N。测试体系与本地开发该节点带有一套纯离线单元测试test/Mem0.node.test.ts通过 stubIExecuteFunctions并 mockhelpers.httpRequestWithAuthentication不依赖任何网络。覆盖的关键路径包括Add 无实体 ID 的本地拦截报错app_id/includes/excludes正确透传到请求体custom_categories非法 JSON 的报错事件永不终态时的轮询超时单 ID 扁平 filter 与多 ID OR filter 的形状Memory ID / event ID 的 URL 转义Return All 的分页终止条件。本地开发命令package.json scriptspnpm run devtsc watch、pnpm run build清 dist 编译 复制图标、pnpm run lint、pnpm testjest配置见 jest.config.js。常见问题排查综合 README 与 docs/integrations/n8n.mdx 的故障排查章节节点没出现在面板里社区节点只能装到自托管 n8n且只有实例 Owner 能安装n8n Cloud 暂不可用。401 UnauthorizedAPI key 错误或被吊销到 API Keys 面板重新生成并更新凭据。Provide at least one of User ID, Agent ID, App ID, or Run IDAdd / Search / Get Many 都必须有实体作用域至少填一个。刚 Add 完 Search 查不到提取是异步的。保持 Wait for Completion 开启或在两者之间加一个短暂的 Wait 节点。同时填两个实体 ID 结果比预期多多 ID 是 OR 并集属设计行为要收窄就每个 ID 单独跑一次操作。Timed out waiting for memory event写入请求已被接受、服务端仍在处理超时不代表失败可以稍后重试 Search 确认。小结mem0/n8n-nodes-mem0用相当克制的 API 面一个 Memory 资源、六个操作覆盖了长期记忆的完整生命周期同时把托管 API 中最容易踩坑的两件事做了工程化兜底Add 的异步提取用有界轮询 清晰终态错误收敛成同步体验实体过滤用本地前置校验 OR 语义避免无效请求和 AND 空结果。配合usableAsTool它既可以作为工作流中的普通数据节点也可以直接交给 n8n AI Agent 自主调用——这正是给工作流加上持久上下文的最低成本路径。所有实现细节均可在 integrations/n8n-nodes-mem0 目录下逐一查证。【免费下载链接】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),仅供参考