@clawdactual/openclaw-recall
v0.4.1
Published
Automatic associative memory recall for OpenClaw agents — surfaces relevant context before the model processes each message
Maintainers
Readme
🧠 openclaw-recall
Automatic associative memory for OpenClaw agents.
Recall surfaces relevant context from your agent's memory systems before the model processes each message — like building your agent a hippocampus. No manual searching required.
Why?
AI agents have long-term storage (files, databases) and working memory (context window), but the bridge between them is manual. The agent must decide to search, know what to search for, and choose which system to query.
The biggest failure mode isn't bad search results — it's the agent not searching at all.
Recall fixes this by intercepting every message, running parallel semantic search across your agent's memory, and injecting the most relevant results into the context window — automatically.
Installation
Quick install (recommended)
# Install directly from GitHub
openclaw plugins install github:Morpheis/openclaw-recall
# Or clone and install locally
git clone https://github.com/Morpheis/openclaw-recall.git
openclaw plugins install ./openclaw-recallManual install
# Copy to extensions directory
mkdir -p ~/.openclaw/extensions/openclaw-recall
cp -r /path/to/openclaw-recall/* ~/.openclaw/extensions/openclaw-recall/
# Add to your openclaw.json{
"plugins": {
"allow": ["openclaw-recall"],
"entries": {
"openclaw-recall": {
"enabled": true
}
}
}
}Then restart:
openclaw gateway restartVerify it's working
# Check plugin loaded
openclaw plugins list | grep recall
# Watch recall in real-time
openclaw logs --follow | grep recall
# Or use the /recall command in chat
/recallRequirements
- OpenClaw 2026.3.x or later
- An embedding provider for memory search (Voyage, OpenAI, Gemini, or Mistral API key configured in OpenClaw)
- sqlite3 CLI for LCM source (pre-installed on macOS/Linux)
- qmd CLI for QMD source (optional:
npm install -g @tobilu/qmd)
How It Works
Message arrives → before_prompt_build hook fires
│
┌─────▼──────────┐
│ Skip Checks │ Heartbeats, short msgs, casual msgs
└─────┬──────────┘
│
┌─────▼──────────┐
│ Extract Query │ Proper nouns + adaptive strategy
└─────┬──────────┘
│
┌─────────────┴─────────────┐
│ (parallel) │ (parallel)
▼ ▼
┌───────────────┐ ┌───────────┐
│ Text Recall │ │ Engram │
│ ┌────┐┌────┐ │ │ Knowledge │
│ │mem ││LCM │ │ │ Graph │
│ └────┘└────┘ │ │ Search │
│ ┌────┐ │ └─────┬─────┘
│ │QMD │ │ │
│ └────┘ │ │
│ ↓ rank/dedup │ │
│ ↓ filter │ │
│ ↓ top N │ │
└───────┬───────┘ │
│ │
▼ ▼
## 🧠 Recalled Context ## 🔗 Knowledge Graph
(text snippets) (nodes + edges)
│ │
└────────┬───────────────┘
▼
{ prependContext } → injected into model context
(sections omitted individually if no results)The model sees a block like this at the top of its context:
## 🧠 Recalled Context
Automatically retrieved based on the user's message.
Use for context; search for more detail if needed.
- **[memory/2026-03-15.md:42-48]** Discussed monorepo PR, Gemini review
suggested printf over echo for cross-platform compatibility
- **[lcm:messages/2525]** [assistant] Weekly summary written...
## 🔗 Knowledge Graph
- **[engram:acme/AuthService]** AuthService (service) → calls: UserDB, TokenCache ← called_by: API-Gateway
- **[engram:acme/API-Gateway]** API-Gateway (service) → calls: AuthService, OrderService ← called_by: FrontendEach section is independent — if text recall finds nothing but engrams match, only the Knowledge Graph section appears (and vice versa). Nothing is injected when both are empty — zero overhead.
How much context does it use?
Recall is controlled by a single setting: maxSnippets (default: 5). Each snippet is truncated to ~250 characters at a sentence boundary. With 5 snippets, recall typically adds ~300-400 tokens to the context — a fraction of most context windows.
There's no percentage-based token budget. You control exactly how many results you want, and the plugin takes the best ones.
Memory Sources
Recall searches multiple systems in parallel and merges the results. Enable what you have.
Memory Search (built-in)
Searches OpenClaw's built-in memory index via openclaw memory search. Works with any configured embedding provider (Voyage, OpenAI, etc.).
This is the universal source — if you only enable one, enable this one.
"sources": {
"memorySearch": {
"enabled": true,
"maxResults": 5
}
}Note: If you use the
memory-lancedbplugin (which has its own auto-recall), the memory-search source is automatically disabled to avoid duplicate work. LCM and QMD sources still run since lancedb doesn't cover them. Override this with"skipMemorySearchIfLancedb": false.
LCM (conversation history)
Searches the Lossless Context Management database via SQLite FTS5 full-text search. Finds relevant past conversations — including messages that have been compacted out of the active context window.
Requires the lossless-claw plugin.
"sources": {
"lcm": {
"enabled": true,
"scope": "messages",
"maxResults": 3
}
}Scope options:
"messages"— search raw conversation messages (default, most useful)"summaries"— search compacted summary nodes"both"— search everything
QMD (local search index)
Searches a QMD index via BM25 (fast keyword search, no API calls). Useful for agents with large file collections already indexed by QMD.
"sources": {
"qmd": {
"enabled": true,
"command": "qmd search",
"maxResults": 5
}
}Engram (knowledge graphs) — Dedicated Section
Searches Engram knowledge graphs — persistent relationship graphs of codebases, organizations, infrastructure, and concepts.
Unlike other sources, engram results get their own ## 🔗 Knowledge Graph section rather than competing in the ranked recall pool. Graph context is structural (nodes + edges) — fundamentally different from text snippets — so it shouldn't compete on relevance score. Engram search runs in parallel with text recall, adding no extra latency.
If no engram results match, the section is omitted entirely (zero extra tokens).
Example output:
## 🧠 Recalled Context
Automatically retrieved based on the user's message.
- **[memory/2026-03-25.md]** Mental Model tool built...
- **[lcm:messages/436]** Discussed API key rotation policy for staging environment...
## 🔗 Knowledge Graph
- **[engram:acme/AuthService]** AuthService (service) → calls: UserDB, TokenCache ← called_by: API-GatewayAuto-detection: If ~/.config/engram/models.db exists, this source can auto-activate. Set enabled: true to force it on, or enabled: false to disable.
"sources": {
"engram": {
"enabled": true,
"maxResults": 3,
"excludeModels": ["personal-contacts"]
}
}Config options:
enabled—true/false(default:false, auto-detects if DB exists)command— engram CLI command (default:engram; customize if engram isn't on your PATH)maxResults— max engram snippets per message (default: 3, independent of text recall'smaxSnippets)excludeModels— array of model names to skip (e.g., personal/family models you don't want in recall)
Enabling and Disabling
Disable the entire plugin
"plugins": {
"entries": {
"openclaw-recall": {
"enabled": false
}
}
}Disable individual sources
Keep the plugin active but turn off specific backends:
"config": {
"sources": {
"memorySearch": { "enabled": true },
"lcm": { "enabled": false },
"qmd": { "enabled": false }
}
}memory-lancedb coexistence
When memory-lancedb is active, Recall automatically disables only the memory-search source (since lancedb handles its own recall for that layer). Other sources like LCM and QMD continue running — lancedb doesn't search conversation history or local file indexes.
To force memory-search on even with lancedb:
"config": {
"skipMemorySearchIfLancedb": false
}Exclusion Patterns
This is the most important thing to tune. Without good exclusion patterns, recall will surface noise — changelogs, license files, vendored dependencies, backup directories — instead of the context that actually matters.
Why exclusions matter
Every noisy result displaces a useful one. With a limited snippet count (default 5), one bad result means 20% of your recall budget is wasted. Invest time tuning exclusions early — watch the ## 🧠 Recalled Context block in your agent's responses for a few days and add patterns for anything irrelevant that keeps showing up. The quality improvement compounds over time.
How patterns work
There are two types of exclusions:
excludeFiles — exact filename matches (case-insensitive). These are files already injected into your agent's context by OpenClaw's bootstrap system. No point recalling what's already there.
"excludeFiles": [
"AGENTS.md", "SOUL.md", "TOOLS.md", "IDENTITY.md",
"USER.md", "HEARTBEAT.md", "MEMORY.md", "PERSONALITY.md"
]excludePatterns — glob-style path patterns with * and ** wildcards (case-insensitive). These filter out entire categories of files. Custom patterns are additive — built-in defaults are always included, so you only need to add patterns specific to your setup.
"excludePatterns": [
"**/my-backup/**",
"**/*-venv/**",
"**/pipeline/data/**",
"**/zh-cn/**"
]Built-in defaults
These patterns are always active (your custom patterns add to them, never replace them):
**/node_modules/** # npm/yarn dependencies
**/dist/** # compiled output
**/build/** # build artifacts
**/lib/** # vendored libraries
**/vendor/** # vendored dependencies
**/changelog.md # release notes (noisy keyword overlap)
**/CHANGELOG.md
**/license.md # license text
**/LICENSE.md
**/contributing.md # contribution guides
**/CONTRIBUTING.md
**/code-of-conduct.md # codes of conduct
**/CODE_OF_CONDUCT.md
**/security.md # security policies
**/SECURITY.mdPattern syntax
| Pattern | Matches |
|---------|---------|
| **/node_modules/** | Any file inside any node_modules directory |
| **/CHANGELOG.md | Any file named CHANGELOG.md at any depth |
| **/*-venv/** | Any directory ending in -venv (like pdf-venv, docling-venv) |
| **/pipeline/data/** | Specific subdirectory path |
| **/zh-cn/** | Chinese localization directories |
Tips for tuning exclusions
- Start broad, refine later. Begin with the defaults and add patterns as you notice noise in the recalled context block.
- Watch the recalled context block. If you see the same irrelevant source repeatedly, add a pattern for it.
- Exclude backup directories. Backup mirrors cause duplicate results that displace unique content.
- Exclude generated files. Build output, compiled code, and auto-generated content rarely contains useful recall context.
- Exclude localization you don't use. i18n directories in other languages add noise to keyword searches.
- Exclude large data directories. Raw datasets, logs, and pipeline data overwhelm useful results.
Full Configuration Reference
All settings go under plugins.entries.openclaw-recall.config:
{
"plugins": {
"entries": {
"openclaw-recall": {
"enabled": true,
"config": {
// Max snippets injected per message (default: 5)
// This is the primary knob for controlling recall volume.
// Lower = tighter, higher quality. Higher = more context surfaced.
"maxSnippets": 5,
// Minimum relevance score 0-1 to include a result (default: 0.3)
// Raise this if you're getting too much noise
"minRelevanceScore": 0.3,
// Skip recall for very short messages after metadata stripping (default: enabled, 40 chars)
// Proper nouns in short messages override this (e.g., "OathKeeper?" still triggers)
"skipShortMessages": {
"enabled": true,
"minChars": 40
},
// Skip heartbeat messages entirely (default: true)
"skipHeartbeats": true,
// Only skip memory-search when lancedb is active (default: true)
// Other sources (LCM, QMD) still run since lancedb doesn't cover them
"skipMemorySearchIfLancedb": true,
// Files already in context — excluded from results
"excludeFiles": [
"AGENTS.md", "SOUL.md", "TOOLS.md", "IDENTITY.md",
"USER.md", "HEARTBEAT.md", "MEMORY.md", "PERSONALITY.md"
],
// Glob patterns to exclude (additive — built-in defaults always included)
"excludePatterns": [
"**/my-backup/**",
"**/*-venv/**"
],
// Memory sources — enable what you have
"sources": {
"memorySearch": { "enabled": true, "maxResults": 5 },
"lcm": { "enabled": true, "scope": "messages", "maxResults": 3 },
"qmd": { "enabled": false, "command": "qmd search", "maxResults": 5 },
"engram": {
"enabled": true, // auto-detects if DB exists when omitted
"maxResults": 3,
"excludeModels": [], // model names to skip (e.g., "personal-contacts")
"command": "engram"
}
},
// Debug logging (writes NDJSON to workspace)
"debug": {
"enabled": false,
"logPath": ".recall/debug.log"
}
}
}
}
}
}How Recall Differs from memory-lancedb
| | memory-lancedb | openclaw-recall | |---|---|---| | Storage | Own LanceDB database | No storage — searches existing systems | | What it searches | Only its own captured memories | Everything: memory files, conversations, local indexes | | Captures new info | Yes (auto-capture) | No — read-only, never writes | | Dependencies | LanceDB binary + OpenAI key | Zero new deps — uses existing infrastructure | | Query strategy | Embeds full prompt | Adaptive: proper nouns + key phrases + segmented | | Multi-source | Single source | Multi-source with parallel search + cross-source boost | | Coexistence | N/A | Auto-disables memory-search source when lancedb active; LCM/QMD still run |
Both are valid approaches. Recall is designed for agents that already have memory systems (OpenClaw memory, LCM, QMD) and want automatic retrieval without adding another database.
Troubleshooting
Plugin not loading
- Check
plugins.allowincludes"openclaw-recall" - Check
plugins.entries.openclaw-recall.enabledistrue - Run
openclaw plugins list | grep recall— should show "loaded" - Run
openclaw doctorfor compatibility warnings
No results appearing
- Check your embedding provider is configured:
openclaw memory status - Try a manual search:
openclaw memory search --json --query "test" - Heartbeat messages are skipped by default
- Short messages (<40 chars after metadata stripping) are skipped unless they contain proper nouns
- If all sources are disabled, nothing will be searched
Poor or noisy results
- Most common fix: add exclusion patterns for noisy directories
- Raise
minRelevanceScore(try 0.4 or 0.5) - Lower
maxSnippetsto keep only the highest-quality results - Enable debug logging to see what's being searched and returned
Duplicate results
- Add backup/mirror directories to
excludePatterns - Check QMD collections for overlapping indexed paths
- Cross-source dedup normalizes paths but can't catch all mirrors
Commands
| Command | Description |
|---------|-------------|
| /recall | Show plugin status, active sources, and configuration |
Roadmap
- [x] Memory search source (OpenClaw built-in)
- [x] LCM source (conversation history via FTS5)
- [x] QMD source (local BM25 search)
- [x] Proper noun prioritization in query extraction
- [x] Metadata envelope stripping
- [x] Cross-collection deduplication with path normalization
- [x] Short message / casual message filtering
- [x] LCM tool call/result filtering (noise reduction)
- [x] LCM content cleaning (strip metadata from results)
- [x] memory-lancedb coexistence (skip only memory-search, not entire plugin)
- [x] Explicit capability registration (
before_prompt_build+/recallcommand) - [x] Engram source (knowledge graph search with auto-detection)
- [ ] npm publish / ClawHub listing
- [ ] Recall quality analytics (track hits/misses across sessions)
- [ ] Per-channel config (different settings per channel)
License
MIT
