Skip to content

wanmeime/openclaw-mem0-fix

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

openclaw-mem0-fix

Patches for the @mem0/openclaw-mem0 plugin (v1.0.11) to fix critical issues with agent-level memory isolation, run_id generation, and autoCapture after OpenClaw 5.3+ upgrade.

Problem Statement

After upgrading OpenClaw to 5.3+, the @mem0/openclaw-mem0 plugin (v1.0.11) has three critical issues:

Issue Symptom Impact
user_id not concatenated user_id: jiaod instead of jiaod:agent:feishu-main All agents share the same memory namespace — no isolation
run_id missing run_id: None Session-scoped memories cannot be filtered or expired
autoCapture broken No memories auto-captured after conversation Important facts from conversations are lost

Root Cause Analysis

Issue 1: currentSessionId closure variable not shared across plugin instances

In OpenClaw 5.3+, the plugin's register() function is called multiple times per conversation. Each call creates a new closure with its own currentSessionId variable:

  • before_prompt_build hook sets currentSessionId in Instance A
  • memory_add tool reads currentSessionId from Instance B — always undefined

This means:

  • extractAgentId(currentSessionId) returns undefined → no agent isolation
  • buildAddOptions() has no run_id fallback → run_id is None
  • autoCapture in agent_end hook runs in a different instance → fails silently

Issue 2: registerHooks() function scope

The registerHooks() function is defined as a standalone function (not inside the register() closure). It directly references currentSessionId which causes ReferenceError: currentSessionId is not defined in the hook handler.

Issue 3: allowConversationAccess not configured

The agent_end hook (used for autoCapture) requires allowConversationAccess: true in the plugin configuration. Without it, the hook is blocked by OpenClaw's security model.

Fixes Applied

Fix 1: Module-level global session store

Added a module-level _globalSessionIdMap variable to share currentSessionId across all plugin instances:

// Module level (outside any function)
var _globalSessionIdMap = {};

// In setCurrentSessionId
setCurrentSessionId: (id) => {
  currentSessionId = id;
  _globalSessionIdMap["latest"] = id;  // Write to global
},

// In getCurrentSessionId
getCurrentSessionId: () => currentSessionId || _globalSessionIdMap["latest"],  // Fallback to global

Fix 2: registerHooks() uses session object instead of direct closure reference

Replaced all direct currentSessionId references inside registerHooks() with session.getCurrentSessionId():

// Before (causes ReferenceError)
const sessionId = ctx?.sessionKey ?? currentSessionId ?? void 0;

// After (works across instances)
const sessionId = ctx?.sessionKey ?? session.getCurrentSessionId() ?? void 0;

Added getCurrentSessionId to the session object passed to registerHooks():

{
  setCurrentSessionId: (id) => { currentSessionId = id; _globalSessionIdMap["latest"] = id; },
  getCurrentSessionId: () => currentSessionId || _globalSessionIdMap["latest"],
  getStateDir: () => pluginStateDir
}

Fix 3: buildAddOptions() fallback to global session

// In buildAddOptions, fallback chain
const fallbackSessionId = currentSessionId || _globalSessionIdMap["latest"];
if (fallbackSessionId) opts.run_id = fallbackSessionId;

Fix 4: _resolveUserId() fallback to global session

const _resolveUserId = (opts) => resolveUserId(cfg.userId, opts, currentSessionId || _globalSessionIdMap["latest"]);

Fix 5: Agent ID auto-extraction in all memory tools

Each tool now auto-extracts agentId from currentSessionId when not explicitly provided:

// memory_add
const effectiveAgentId = p.agentId ?? extractAgentId(currentSessionId);
const uid = resolveUserId3({ agentId: effectiveAgentId, userId: p.userId });

// memory_search, memory_list, memory_delete
const effectiveAgentId = agentId ?? extractAgentId(getCurrentSessionId());
const uid = resolveUserId3({ agentId: effectiveAgentId, userId });

Fix 6: allowConversationAccess configuration

Required in openclaw.json:

{
  "plugins": {
    "entries": {
      "openclaw-mem0": {
        "hooks": {
          "allowConversationAccess": true
        }
      }
    }
  }
}

Results After Fix

Field Before After
user_id jiaod jiaod:agent:feishu-main
run_id None agent:feishu-main:feishu:direct:ou_xxx
autoCapture Not working Working
Agent isolation None Per-agent namespace via user_id suffix

Installation

Option 1: Direct file replacement

# Backup original
cp ~/.openclaw/npm/node_modules/@mem0/openclaw-mem0/dist/index.js \
   ~/.openclaw/npm/node_modules/@mem0/openclaw-mem0/dist/index.js.bak

# Copy patched file
cp dist/index.js ~/.openclaw/npm/node_modules/@mem0/openclaw-mem0/dist/index.js

# Restart Gateway
systemctl --user restart openclaw-gateway.service

Option 2: Extensions directory (survives upgrades)

# Create extensions directory
mkdir -p ~/.openclaw/extensions/openclaw-mem0/dist

# Copy patched file
cp dist/index.js ~/.openclaw/extensions/openclaw-mem0/dist/index.js
cp dist/openclaw.plugin.json ~/.openclaw/extensions/openclaw-mem0/dist/

Note: The extensions path may take priority over the npm path depending on your OpenClaw version. Verify with openclaw plugins list.

Configuration

Ensure your ~/.openclaw/openclaw.json includes:

{
  "plugins": {
    "slots": {
      "memory": "openclaw-mem0"
    },
    "entries": {
      "openclaw-mem0": {
        "enabled": true,
        "hooks": {
          "allowConversationAccess": true
        }
      }
    },
    "allow": [
      "openclaw-mem0"
    ]
  }
}

See config/openclaw-mem0-example.json for a complete example.

How Agent Isolation Works

Session Key: agent:feishu-main:feishu:direct:ou_xxx
                    │
                    ▼
         extractAgentId() → "feishu-main"
                    │
                    ▼
         agentUserId("jiaod", "feishu-main")
                    │
                    ▼
         user_id = "jiaod:agent:feishu-main"

Each agent gets a unique user_id namespace:

  • Agent feishu-mainjiaod:agent:feishu-main
  • Agent custom-botjiaod:agent:custom-bot
  • Main agent (no suffix) → jiaod

Mem0's search() and getAll() filter by user_id, so memories are naturally isolated per agent.

Compatibility

Component Version
OpenClaw 4.26+
@mem0/openclaw-mem0 1.0.11
mem0ai (npm) 3.0.1
Qdrant 1.x

Note: Issues started after upgrading @mem0/openclaw-mem0 to the latest version on OpenClaw 4.26 (run_id missing, unable to read old data). Fixed in 5.2, broke again in 5.3, now fixed permanently.

Warning

This patch modifies the compiled dist/index.js file. It will be overwritten when the @mem0/openclaw-mem0 package is updated via openclaw plugins update or npm update. Re-apply the patch after any upgrade, or use the extensions directory approach.

License

This patch is provided under the same license as the original @mem0/openclaw-mem0 plugin (Apache-2.0). The original plugin is copyright of mem0ai.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages