Debugging agent recall: why your agent can't find what it stored
You stored a memory. You’re sure you did — you even got the UUID back. But when your agent recalls it, nothing. Or worse, the wrong memory surfaces instead.
This is the most common frustration with semantic memory systems, and it’s almost never a bug. It’s a mismatch between what you stored, how you’re querying, and how scoring works.
The recall scoring formula
Before debugging, you need to understand what recall actually does. MemoClaw doesn’t just do a simple “find similar text” lookup. It runs a hybrid 4-signal scoring:
hybrid = vector_sim × 0.55 + keyword_match × 0.25 + recency × 0.20
score = hybrid × context_importance × access_boost × type_decay
Each signal can make or break your result:
- vector_sim (55%): Cosine similarity between your query embedding and the stored memory embedding
- keyword_match (25%): BM25 full-text match — exact word overlap matters
- recency (20%):
exp(-age_days / 30)— newer memories score higher - context_importance: Your memory’s importance, boosted by query relevance
- access_boost: Frequently recalled memories get a boost (up to 2x)
- type_decay: Memory types decay at different rates (observations decay fast, corrections decay slow)
When keyword match is strong (>0.3), the weights shift: keywords get 0.35, vectors drop to 0.45. This adaptive boosting means exact wording matters more than you’d expect.
Problem 1: Wrong namespace
Symptom: recall returns zero results, even though list shows the memory exists.
This is the #1 gotcha. You stored a memory in the project-x namespace but recalled from default (or vice versa).
# You stored here:
memoclaw store "Database uses Postgres 15" --namespace project-x
# But you're recalling here (default namespace):
memoclaw recall "What database do we use?"
# → No results!
# Fix: specify the namespace
memoclaw recall "What database do we use?" --namespace project-x
# → Found it!
Quick check — list your namespaces to see where memories live:
memoclaw list --namespace project-x
For OpenClaw agents: make sure your skill configuration or session hooks pass the same namespace for both store and recall. A common mistake is storing with a namespace in one hook and recalling without it in another.
Problem 2: Semantic gap
Symptom: the memory exists in the right namespace but doesn’t surface for your query.
Embeddings capture meaning, but they’re not mind readers. Sometimes there’s a gap between how you stored something and how you’re querying it.
# Stored:
memoclaw store "Ana prefers 2-space indentation in all JavaScript files"
# Query that works well:
memoclaw recall "What indentation style does Ana use?"
# → Found! (high semantic similarity)
# Query that might miss:
memoclaw recall "code formatting preferences"
# → Might not rank high enough (too abstract)
Fixes:
-
Be specific in your query. “What indentation does Ana prefer?” beats “code style” every time.
-
Store memories with rich context. Instead of “prefers tabs”, store “Ana prefers 2-space indentation in JavaScript and TypeScript files, not tabs.”
-
Use tags as a safety net. Even if semantic search misses, you can filter by tags:
memoclaw recall "formatting rules" --tags preferences,editor
Tag filtering narrows the candidate set before semantic scoring, making it much more likely to find what you need.
Problem 3: Recency bias
Symptom: old but important memories get buried under newer, less relevant ones.
Recency accounts for 20% of the hybrid score. A memory that’s 90 days old has a recency score of exp(-90/30) = 0.05. A memory from yesterday scores ~0.97. That’s a big gap.
# Stored 3 months ago (important but old):
memoclaw store "Production database connection string uses read replicas" \
--importance 0.9
# Stored yesterday (trivial but fresh):
memoclaw store "Discussed code review process in standup"
# Query:
memoclaw recall "database connection"
# The old memory might score lower than expected because of recency decay
Fixes:
- Pin important memories. Pinned memories are exempt from type-based decay:
memoclaw store "Production DB uses read replicas on port 5433" \
--importance 0.95 \
--pinned \
--type decision
- Use the right memory type.
correctionandpreferencetypes have 180-day half-lives.observationdecays in 14 days. Choose accordingly:
| Type | Half-life | Use for |
|---|---|---|
correction | 180 days | User corrections, factual fixes |
preference | 180 days | Long-term preferences |
decision | 90 days | Architecture, design choices |
general | 60 days | Default |
project | 30 days | Sprint/project-specific context |
observation | 14 days | Ephemeral notes, observations |
- Recall the memory occasionally. The access_boost signal means memories that get recalled often rank higher:
min(1 + access_count × 0.1, 2.0). If something is important, recalling it reinforces it.
Problem 4: Low importance score
Symptom: memory exists, is semantically relevant, but consistently ranks below less relevant results.
The context_importance multiplier means a memory with importance 0.3 will score roughly a third of what an identical memory with importance 0.9 would score.
# This will quietly disappear in results:
memoclaw store "API rate limit is 100 req/min" --importance 0.3
# This will surface reliably:
memoclaw store "API rate limit is 100 req/min" --importance 0.9
Fix: if you stored a memory with low importance, update it:
memoclaw update <memory-id> --importance 0.9
Rule of thumb for importance scores:
- 0.9-1.0: Things that break if wrong. Corrections, credentials rules, safety boundaries.
- 0.7-0.8: Important preferences, project architecture decisions.
- 0.5-0.6: Nice-to-know, general observations.
- 0.3-0.4: Ephemeral stuff, probably not worth storing.
Problem 5: Deduplication ate your memory
Symptom: you stored a memory but can’t find it by ID. The store response said "deduplicated": true.
MemoClaw automatically deduplicates. If you store something semantically similar to an existing memory, it merges them instead of creating a duplicate. The original memory gets updated content, and the new UUID might differ from what you expected.
# First store:
memoclaw store "User prefers dark mode"
# → ID: abc-123, deduplicated: false
# Second store (similar content):
memoclaw store "User likes dark themes in all apps"
# → ID: abc-123, deduplicated: true (merged with existing!)
Fixes:
-
Check the
deduplicatedfield in store responses. If it’strue, your content was merged into an existing memory. -
Use
recallinstead ofgetto find your memory. Since the ID might not be what you stored, semantic search is more reliable. -
Recall before storing to check if a similar memory already exists. This is a good practice anyway.
The debug toolkit
When recall isn’t working as expected, use these free endpoints to investigate:
Check the _signals breakdown
The recall response includes a _signals object for each result:
{
"_signals": {
"vector": 0.92,
"keyword": 0.15,
"recency": 0.78,
"base_importance": 0.8,
"effective_importance": 0.96,
"context_importance": 0.98,
"relation_count": 1,
"type_decay": 0.95
}
}
This tells you exactly why a memory ranked where it did. Low vector similarity? Your query is semantically off. Low recency? The memory is old. Low type_decay? You used a fast-decaying memory type.
Use free text search as a fallback
memoclaw search "database connection" --namespace project-x
POST /v1/search does keyword-only matching — no embeddings, no scoring, completely free. If your memory shows up here but not in recall, the problem is semantic rather than missing data.
List and audit
# List everything in a namespace
memoclaw list --namespace project-x --limit 50
# Check suggested memories (stale/decaying ones)
memoclaw suggested --category decaying
Check your stats
# See how many memories you have and usage patterns
memoclaw stats
Prevention checklist
To avoid recall problems before they happen:
- Store specific, context-rich memories — not fragments
- Set appropriate importance scores — don’t leave everything at 0.5
- Use the right memory type — match decay to expected relevance lifetime
- Pin critical memories — exempt them from decay
- Tag consistently — use tags as a filtering safety net
- Use namespaces — keep projects isolated
- Recall before storing — avoid unintended deduplication
Semantic memory isn’t magic. It’s math. When your agent can’t find what it stored, the _signals breakdown tells you exactly which signal is dragging down the score. Wrong namespace, semantic gap, recency bias, low importance, or unexpected deduplication — it’s almost always one of these five.
Want to lock memories so they can never drift? Read about immutable memories next.