1. 两个 OpenClaw 协作时,记忆为什么总是断片
我一开始只跑一个 OpenClaw,觉得够用了。后来接了个技术沙龙策划的活,创意阶段需要天马行空,执行阶段需要抠预算、排物料、写风险预案,同一个 Agent 来回切换角色,输出质量明显不稳定。于是我在同一台机器上起了第二个实例,一个专门做创意,一个专门做落地。
问题马上就来了。OpenClaw A 在 3000 端口产出了活动主流程和招募文案,我切到 3001 端口的 OpenClaw B,问它“基于刚才的方案出物料清单”,它一脸茫然。两个实例各自有独立的会话上下文,A 的产出对 B 来说完全不存在。我试过手动复制粘贴,但每次都要人肉搬运,根本谈不上 24/7 自动协作。
这里的关键检索词是 OpenClaw 多实例记忆共享。OpenClaw 本身是一个可以跑在自己设备上的个人 AI 助手,你分配任务它就干活,但它的记忆默认是实例本地的。两个实例要协作,必须有一个外部记忆层来打通。MemOS 的 OpenClaw 插件就是干这个的,它通过 user_id 把不同实例的对话和产出归到同一个记忆空间里,再通过召回机制把历史上下文自动注入到当前对话。
但光有 MemOS 还不够。两个 OpenClaw 实例在调用模型时,如果各自用不同的 API Key、不同的 Base URL,请求链路会变得很难排查。我实测下来,用 TaoToken 统一 Key 接入之后,两个实例的模型调用走同一个入口,MemOS 插件的 user_id 透传也更稳定。下面我把整个配置链路拆开讲,包括 settings 片段、user_id 透传验证,以及我踩过的几个报错。
2. TaoToken 统一 Key 与 MemOS 插件的前置准备
在动手改配置之前,先把两样东西准备好:TaoToken 的 API Key,以及 MemOS 插件的安装。这两步不分先后,但 Key 的格式和插件的配置字段要对上,否则后面请求会 401。
先说 TaoToken。它的定位是统一模型接入层,你可以在一个地方拿到 Key,然后让多个 OpenClaw 实例共用。打开 https://taotoken.net/api 可以看到 API 入口,Key 在控制台里生成。我建议单独建一个 Key 给 OpenClaw 用,方便后面按实例排查调用量。生成之后你会拿到一串以 sk- 开头的字符串,这个就是后面配置里的 API Key。
再说 MemOS 插件。MemOS 官方发的 OpenClaw 插件在 GitHub 上可以找到,安装命令是openclaw plugins install github:MemTensor/MemOS-Cloud-OpenClaw-Plugin。装完之后需要 restart gateway,插件才会生效。这里有个细节:如果你跑两个实例,两个实例都要装插件,而且要用各自的 OPENCLAW_HOME 去装,不能只装一个然后复制目录,否则插件注册信息可能对不上。
MemOS 那边你需要注册并拿到一个 mpg- 开头的 API Key,这个 Key 是访问记忆池的凭证,和 TaoToken 的 Key 是两回事。TaoToken 的 Key 管模型调用,MemOS 的 Key 管记忆读写,两个都要配。user_id 则是 MemOS 用来区分记忆空间的标识,默认是 openclaw-user,两个实例配成同一个值就能共享记忆。
我建议在动手之前先确认三件事:TaoToken Key 是否可用、MemOS 插件是否在两个实例里都 enabled、user_id 是否在两个 .env 里一致。这三件事任何一件出问题,后面的协作都会断。你可以先用cat ~/.openclaw/openclaw.json | grep memos检查插件状态,看到"enabled": true再往下走。
3. 可复制的 settings 配置片段与 user_id 透传
这一节是核心,我把两个实例的配置拆成可复制的片段。路径和你实际环境可能略有差异,但字段名和结构是一致的。先看 OpenClaw A 的配置目录,我习惯放在~/.openclaw,B 放在~/.openclaw-exec。
OpenClaw A 的.env文件内容如下,注意 TaoToken 的 Base URL 和 MemOS 的 user_id 要同时写进去:
# ~/.openclaw/.env TAOTOKEN_API_KEY=sk-your_taotoken_key_here TAOTOKEN_BASE_URL=https://taotoken.net/api MEMOS_API_KEY=mpg-your_memos_key_here MEMOS_USER_ID=openclaw-userOpenClaw B 的.env在~/.openclaw-exec/.env,内容除了工作目录不同,Key 和 user_id 保持一致:
# ~/.openclaw-exec/.env TAOTOKEN_API_KEY=sk-your_taotoken_key_here TAOTOKEN_BASE_URL=https://taotoken.net/api MEMOS_API_KEY=mpg-your_memos_key_here MEMOS_USER_ID=openclaw-user接下来是openclaw.json里的模型和插件配置。这个文件在两个实例里都要改,我用 JSON 片段展示关键字段。注意 model 的 provider 指向 TaoToken,plugin 的 user_id 从环境变量读取:
{ "model": { "provider": "openai-compatible", "baseUrl": "https://taotoken.net/api", "apiKey": "${TAOTOKEN_API_KEY}", "modelId": "claude-sonnet-4-20250514" }, "plugins": { "memos-cloud-openclaw-plugin": { "enabled": true, "apiKey": "${MEMOS_API_KEY}", "userId": "${MEMOS_USER_ID}" } } }如果你用的是 TOML 格式的 settings,等价写法如下:
[model] provider = "openai-compatible" base_url = "https://taotoken.net/api" api_key = "${TAOTOKEN_API_KEY}" model_id = "claude-sonnet-4-20250514" [plugins.memos-cloud-openclaw-plugin] enabled = true api_key = "${MEMOS_API_KEY}" user_id = "${MEMOS_USER_ID}"这里的三件套是 Base URL、API Key、Model ID,缺一不可。Base URL 用https://taotoken.net/api,不要加多余的路径;API Key 用 TaoToken 控制台生成的 sk- 串;Model ID 按你实际要用的模型填,我测试时用的是 claude-sonnet-4 系列。MemOS 插件的 userId 字段直接引用环境变量,这样两个实例只要 .env 一致,user_id 就自动对齐。
改完配置后,两个实例都要 restart gateway。A 用openclaw gateway restart,B 用OPENCLAW_HOME=~/.openclaw-exec openclaw gateway restart。重启后你可以用openclaw plugins list确认 memos 插件处于 active 状态。如果插件没加载,先检查 openclaw.json 的 JSON 语法,逗号和引号是最容易出错的地方。
4. 验证请求:user_id 透传与跨实例记忆召回
配置改完不算完,得验证 user_id 真的透传到了 MemOS,而且 B 能读到 A 的产出。我设计了一个最小验证流程,你照着做一遍就能确认链路通没通。
第一步,在 OpenClaw A 的界面里发一条带标记的消息。我用的 prompt 是:“请产出一份技术沙龙的活动主流程,包含开场、主题分享、圆桌讨论三个环节,每个环节标注预计时长。”等 A 返回结果后,不要手动保存,MemOS 插件会自动写回。
第二步,检查 MemOS 是否收到了这条记忆。你可以通过 MemOS 的控制台或者 API 查询 user_id 下的记忆条目。如果能看到 A 的产出,说明写回链路正常。这一步很关键,因为如果写回失败,B 那边再怎么召回也是空的。
第三步,切到 OpenClaw B 的界面,发一条不包含任何背景信息的请求:“基于已有的活动方案,列出物料清单和风险预案。”注意,这里我故意不提“技术沙龙”四个字,看 B 能不能自己从记忆里召回。
实测下来,B 在思考阶段会先调用 MemOS 的记忆检索,然后把 A 的产出作为上下文注入。返回的物料清单里包含了签到台、投影设备、茶歇这些和 A 的议程对得上的条目,风险预案里也提到了圆桌讨论超时的应对。这说明 user_id 透传生效了,两个实例确实在共享同一个记忆池。
如果你想更直观地验证,可以在 B 的请求里加一句“请引用你读到的方案原文”。B 会把 A 产出的环节名称复述出来,这就直接证明了召回的是 A 的记忆而不是 B 自己编的。我试过这一步,B 准确复述了“开场、主题分享、圆桌讨论”三个环节,链路是通的。
这里有个细节:MemOS 的召回是自动的,你不需要在 prompt 里手动指定 user_id。插件会根据配置里的 userId 字段去检索,然后把相关记忆注入到模型上下文里。所以你在 B 的界面里感觉不到额外的操作,但背后已经完成了一次跨实例的记忆搬运。
5. 常见报错排查:401、local proxy failed 与 choices 为空
配置过程中我踩了几个坑,这里按报错原文列出来,方便你对照排查。
第一个是 401 Unauthorized。这个最常见,原因是 TaoToken 的 API Key 没配对,或者 .env 文件没被正确加载。你先确认echo $TAOTOKEN_API_KEY能输出 sk- 开头的串,如果输出为空,说明 .env 没 source 或者路径不对。另一个可能是 openclaw.json 里的 apiKey 字段写成了硬编码而不是${TAOTOKEN_API_KEY},导致变量没替换。改成引用环境变量后 restart gateway 即可。
第二个是 local proxy failed。这个报错通常出现在 Base URL 配置错误的时候。如果你把 Base URL 写成了https://taotoken.net/api/v1或者带了多余的斜杠,请求会打到错误的路径上。正确的写法是https://taotoken.net/api,不要加 v1,也不要加尾部斜杠。另外检查一下你的网络环境是否能正常访问这个地址,可以用curl -I https://taotoken.net/api看返回状态码。
第三个是 reading choices 相关报错,比如cannot read property 'choices' of undefined。这个一般是模型返回格式和 OpenClaw 预期不一致导致的。排查方向有两个:一是 Model ID 是否写对,如果你填了一个 TaoToken 不支持的模型名,返回体里可能没有 choices 字段;二是 MemOS 插件注入的上下文是否过长,导致请求被截断。我遇到过一次是因为 user_id 下的记忆条目太多,召回时把上下文撑爆了,后来在插件配置里限制了召回条数就解决了。
第四个是 OAuth 相关报错。如果你在 OpenClaw 里配了 OAuth 登录,但 TaoToken 的 Key 是 API Key 模式,两者可能会冲突。解决办法是在 openclaw.json 里明确指定 auth 类型为 api-key,不要走 OAuth 流程。具体字段是"auth": {"type": "api-key"},加上之后 restart 就能绕过 OAuth 检查。
排查的时候建议按顺序来:先确认 Key 能输出,再确认 Base URL 能 curl 通,然后看 openclaw.json 语法,最后看 MemOS 插件日志。每一步都有对应的验证命令,不要跳步。我一开始就是跳过了 curl 验证,结果在 401 上卡了半小时。
6. 让两个 OpenClaw 长期跑下去的几个实用建议
跑通之后,我让两个实例连续跑了几天,积累了一些经验。首先是 user_id 的命名,建议用项目名而不是默认的 openclaw-user,这样以后你有多个协作组的时候不会串记忆。比如MEMOS_USER_ID=salon-project,两个实例都改成这个值,记忆池就按项目隔离了。
其次是记忆条数的控制。MemOS 默认会召回一定数量的历史条目,如果项目跑久了,召回内容会越来越长,既增加 token 消耗也拖慢响应。你可以在插件配置里加一个maxRecallItems字段,限制每次召回的最大条数,我设的是 10,实测下来够用。
第三是定期检查两个实例的插件状态。OpenClaw 升级或者 gateway 重启后,插件偶尔会掉。你可以写一个简单的检查脚本,用openclaw plugins list | grep memos判断是否 active,不 active 就自动 restart。这样能避免半夜协作断链。
最后是模型调用的监控。两个实例 24/7 跑,TaoToken 的调用量会累积。你可以在控制台里按 Key 查看用量,如果发现某个实例调用异常频繁,可能是陷入了循环召回。这时候检查一下 prompt 里有没有触发无限反思的指令,适当加一些终止条件。
这套方案我用了两周,技术沙龙策划的活确实省了不少人肉搬运。创意和执行分开之后,两个实例的输出质量都比单实例来回切换要好。如果你也想让多个 OpenClaw 协作,建议先从两个实例、一个共享 user_id 开始,跑通验证流程之后再扩展。