You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Feb 27, 2026. It is now read-only.
The memory_search tool (built into OpenClaw) searches MEMORY.md and memory/*.md files using a local SQLite QMD index. Our actual memory system lives in PostgreSQL (nova_memory database) with vector embeddings in memory_embeddings table — entity facts, daily logs, lessons, events, processed chats, etc. (3,600+ embeddings).
This creates a split: the tool searches the filesystem while our real memories are in the database. The filesystem files are mostly session notes that get embedded into the database anyway. We should hook the tool to query the database directly.
Proposed Solution
Create a new hook: memory-recall
Fires on before_tool_call (OpenClaw supports this — see pi-tools.before-tool-call.ts)
Intercepts calls to memory_search tool
Instead of letting the default filesystem search run, queries memory_embeddings in PostgreSQL using the same OpenAI text-embedding-3-small embeddings we already have
Returns results in the same format the tool expects (path, snippet, score, startLine, endLine)
Falls back to default filesystem search if database is unavailable
Query flow:
Embed the query using OpenAI text-embedding-3-small (same model as our embeddings)
Query memory_embeddings with cosine similarity (`<=>\ operator via pgvector)
Apply memory_type_priorities weighting
Return top N results formatted as MemorySearchResult
Problem
The
memory_searchtool (built into OpenClaw) searchesMEMORY.mdandmemory/*.mdfiles using a local SQLite QMD index. Our actual memory system lives in PostgreSQL (nova_memorydatabase) with vector embeddings inmemory_embeddingstable — entity facts, daily logs, lessons, events, processed chats, etc. (3,600+ embeddings).This creates a split: the tool searches the filesystem while our real memories are in the database. The filesystem files are mostly session notes that get embedded into the database anyway. We should hook the tool to query the database directly.
Proposed Solution
Create a new hook:
memory-recallbefore_tool_call(OpenClaw supports this — seepi-tools.before-tool-call.ts)memory_searchtoolmemory_embeddingsin PostgreSQL using the same OpenAItext-embedding-3-smallembeddings we already haveQuery flow:
text-embedding-3-small(same model as our embeddings)memory_embeddingswith cosine similarity (`<=>\ operator via pgvector)memory_type_prioritiesweightingMemorySearchResultHook structure:
Existing infrastructure to leverage
memory_embeddingstable with pgvector — already has 3,600+ embedded recordsmemory_type_prioritiestable — weights different source typestext-embedding-3-small(1536 dims) — same model, same embeddingsproactive-recall.py— existing Python script that does this exact query (can reference for SQL patterns)loadPgEnv()from~/.openclaw/lib/pg-env.ts— standard PG connection patternFiles to create/modify
hooks/memory-recall/handler.ts— new hookhooks/memory-recall/package.json—{"type": "module"}hooks/memory-recall/HOOK.md— hook metadata forbefore_tool_callagent-install.sh— sync new hook to~/.openclaw/hooks/Constraints
MemorySearchResultformatmaxResultsandminScoreparameters from the tool callloadPgEnv()for database credentials (standard pattern)Related
semantic-recallhook — automatic per-turn injection (different: that's push, this is pull)proactive-recall.py— Python script with the exact pgvector query patternmemory_embeddingstable — the actual data sourceagent_turn_context(complementary feature)