Introduction
When an agent needs to recall information beyond the currently loaded daily logs, OpenClaw provides powerful semantic search through the memory_search tool. This tool combines vector similarity search with keyword matching to surface the most relevant memories. This lesson explores the hybrid search pipeline, MMR deduplication, and temporal decay.
Key Concepts
- memory_search — the primary retrieval tool that performs hybrid semantic and keyword search across all memory files.
- Hybrid Search — combines vector similarity scores with BM25 text matching scores using configurable weights.
- MMR (Maximal Marginal Relevance) — a diversity algorithm (lambda 0.7) that reduces redundant results by penalising documents too similar to already-selected ones.
- Temporal Decay — an exponential decay function with a 30-day half-life that favours recent memories over older ones.
- memory_get — a targeted tool for reading a specific memory file when you know exactly which one you need.
Real World Context
Consider a developer assistant that has accumulated months of daily logs. When the user asks "How did we fix the authentication bug?", pure keyword search might miss entries that discuss "OAuth token refresh" without using the word "authentication". Pure vector search might surface semantically similar but irrelevant entries about "authorization policies". Hybrid search combines both approaches to find the most relevant result, and temporal decay ensures that the recent fix is ranked above a similar discussion from six months ago.
Deep Dive
The memory_search Tool
The memory_search tool is the agent's primary interface for recalling past information:
textmemory_search(query: "How to configure deployment")
Behind the scenes, this triggers a multi-stage retrieval pipeline. Before examining each stage, understand that the goal is to combine the precision of keyword matching with the recall of semantic understanding.
Hybrid Search Formula
OpenClaw computes a final relevance score by blending two signals:
textfinalScore = (vectorWeight × vectorScore) + (textWeight × textScore)
The vectorScore comes from embedding the query and comparing it against pre-computed embeddings of memory chunks using cosine similarity. The textScore comes from BM25, a classical information retrieval algorithm that scores documents based on term frequency and inverse document frequency.
After computing these scores, they are combined using the configured weights (which default to balanced values). This hybrid approach catches both semantically similar content and exact keyword matches.
MMR — Reducing Redundancy
After scoring, the results pass through Maximal Marginal Relevance with a lambda of 0.7:
textMMR(d) = λ × Sim(d, query) - (1 - λ) × max(Sim(d, selected))
Before applying MMR, you might get five results that all discuss the same topic from slightly different angles. MMR addresses this by iteratively selecting results that are both relevant to the query (the first term) and diverse from already-selected results (the second term).
With lambda at 0.7, the algorithm weights relevance more heavily than diversity, ensuring that highly relevant results are not discarded just because they overlap with each other. The 0.3 diversity component is enough to prevent near-duplicate results from flooding the output.
Temporal Decay
All scored results are then adjusted by temporal decay:
textdecayFactor = e^(-λt) # Where t is the age of the document and half-life is 30 days
This exponential decay means a memory from 30 days ago receives half the temporal boost of a memory from today. After 60 days, it receives one quarter, and so on.
Critically, evergreen files like MEMORY.md are exempt from temporal decay. Since MEMORY.md contains curated, always-relevant information, it would be counterproductive to penalise it for age.
memory_get — Targeted Retrieval
When the agent knows exactly which file it needs, it can bypass search entirely:
textmemory_get(file: "memory/2025-06-15.md")
This reads the specified file directly, which is faster and more precise than searching. It is useful when the agent has already identified the relevant file through a prior search or contextual reasoning.
Common Pitfalls
- Relying solely on vector search — pure semantic search can miss exact keyword matches. The hybrid approach exists because neither method alone is sufficient.
- Ignoring the 30-day half-life — if your agent needs to recall events from months ago with high priority, the default temporal decay may suppress those results. Consider adjusting decay settings for long-memory use cases.
- Over-searching when memory_get suffices — if you know the exact file path,
memory_getis faster and more reliable thanmemory_search. Reserve search for when you need discovery.
Best Practices
- Write descriptive daily log entries — both vector and keyword search benefit from clear, detailed entries. Vague notes like "fixed bug" are hard to retrieve later.
- Trust the hybrid pipeline — resist the urge to over-engineer query strings. The combination of vector similarity, BM25, MMR, and temporal decay handles most retrieval scenarios well out of the box.
- Use memory_get for known files — when you already know which daily log or memory file contains the information, skip the search pipeline and read directly.
Summary
memory_searchperforms hybrid retrieval combining vector similarity and BM25 keyword scoring.- The formula
finalScore = (vectorWeight × vectorScore) + (textWeight × textScore)blends both signals. - MMR with lambda 0.7 reduces redundant results while preserving relevance.
- Temporal decay (30-day half-life) favours recent memories; evergreen files like MEMORY.md are exempt.
memory_getprovides direct file access when the target is already known.