-
Notifications
You must be signed in to change notification settings - Fork 665
memory_recall can fail after DB migration/import while memory-pro search still works (runtime scope/agent resolution mismatch) #273
Description
Summary
After migrating memory-lancedb-pro from a 768-dim DB to a new 1024-dim DB, the memory data could be restored into the new LanceDB and openclaw memory-pro search worked, but the memory_recall tool in the running OpenClaw session returned No relevant memories found.
This turned out to be a combination of migration/import friction and a tool-runtime scope resolution issue.
Environment
- Plugin:
memory-lancedb-pro@1.1.0-beta.9 - OpenClaw host: macOS
- Embedding model:
bge-large:latestvia Ollama-compatible endpoint - Old DB: 768 dims
- New DB: 1024 dims
What happened
- Switched plugin config to a new 1024-dim
dbPath - Restarted gateway
- Verified plugin loaded and pointed at the new DB
memory_recallreturned no results- CLI showed the new DB was empty
- Historical memories still existed in JSONL backup
- Imported backup into new DB
- After import:
openclaw memory-pro statsshowed memories presentopenclaw memory-pro search ...returned results- but
memory_recallstill returned no results in-session
Additional import issue
A subset of backup entries were long session-summary style memories. Import hit repeated embedding errors like:
Document exceeded context limit (400 the input length exceeds the context length), attempting chunking...
As a practical recovery step, trimming the longest entries before import allowed the full dataset to be restored.
Root cause we found locally
The main behavioral mismatch was:
- CLI search worked
memory_recalltool did not
The relevant code path appears to be tool runtime context resolution in src/tools.ts:
function resolveToolContext(
base: ToolContext,
runtimeCtx: unknown,
): ToolContext {
return {
...base,
agentId: resolveRuntimeAgentId(base.agentId, runtimeCtx),
};
}During tool registration in index.ts, tools are registered with:
agentId: undefined // Will be determined at runtime from contextIf the host does not pass agentId / sessionKey as expected in the tool runtime context, then agentId remains undefined.
From src/scopes.ts, that means getAccessibleScopes(undefined) falls back to getAllScopes(), which only includes explicitly defined scopes.
In our case, restored memories were in agent:main, but the plugin config did not explicitly define agent:main in scopes.definitions, so tool-side resolution could end up searching the wrong accessible scope set even though CLI with explicit --scope agent:main worked.
Local workaround / fix that restored memory_recall
We made three local changes:
1) Add a runtime fallback in resolveToolContext
function resolveToolContext(
base: ToolContext,
runtimeCtx: unknown,
): ToolContext {
return {
...base,
agentId: resolveRuntimeAgentId(base.agentId, runtimeCtx) || "main",
};
}2) Explicitly configure scope definitions / access
"scopes": {
"default": "agent:main",
"definitions": {
"global": { "description": "Shared knowledge across all agents" },
"agent:main": { "description": "Primary private memory scope for the main agent" }
},
"agentAccess": {
"main": ["global", "agent:main"]
}
}3) Lower retrieval thresholds back to more forgiving values
"retrieval": {
"minScore": 0.3,
"hardMinScore": 0.35
}After reload, both of these worked again:
openclaw memory-pro search ...memory_recall
Why this is worth fixing in the plugin
The current behavior is fragile because tool correctness depends on runtime context injection being perfect, while the scope manager treats undefined agentId very differently from a concrete agent.
This can produce a confusing state where:
- the database is healthy
- CLI retrieval is healthy
- but agent tool recall appears broken
Suggested fixes
-
Add a safer fallback for tool runtime
agentId- maybe default to
mainfor main-session usage - or use a more robust derivation path when runtime context is partial
- maybe default to
-
Make built-in
agent:*scopes more resilient when no explicit definition exists- or ensure
getAllScopes()includes active built-in agent scopes when memories already exist there
- or ensure
-
Improve import behavior for overlong memory texts
- proper chunking/truncation strategy during import
- clearer reporting for which entries failed and why
-
Consider a migration helper for dimension/dbPath changes
- detect backup presence
- optionally re-import into the new DB automatically or interactively
Repro signal
A strong signal for this issue is:
memory-pro searchreturns relevant results fromagent:mainmemory_recallreturnsNo relevant memories found- tool runtime has no usable
agentId/sessionKey agent:mainis not explicitly present inscopes.definitions
If helpful, I can also open a follow-up PR with the fallback fix.