Memory Retrieval Policies: Recency, Relevance, Importance
How recency, importance, and similarity combine to rank memories for the current query.
A memory store can contain the right episode and still rank it below stale or keyword-heavy records. Retrieval policy corrects that ordering by combining semantic similarity with time, importance, explicit validity, and a bounded context budget.
The retrieval-policy contract
A retrieval policy recalls a coarse candidate set, computes comparable signal values, reranks the candidates, trims them to a prompt budget, and updates read-driven state. Vector similarity supplies recall; recency and importance change the order after recall.
Signals need normalization because cosine, decay, and importance can have different ranges. Recall size, rerank cost, and the final prompt contribution also need explicit bounds so retrieval does not grow with the store.
Chunking chooses storage units, the write policy controls admission, and hierarchical paging chooses a tier. Retrieval policy operates after those decisions on the candidates available for the current read.
Combine recency, importance, and similarity
The formulation from Park et al. (2023), §A.1, is the canonical reference, and knowing each piece in detail is what makes the implementations downstream legible.
Recency. Exponential decay over the time since the episode was last retrieved (not just last written). The paper uses a decay factor of 0.995 per sandbox hour, which sounds modest until you compound it: after 24 sandbox hours an episode’s recency term is 0.995^24 ≈ 0.886; after a week (168 hours) it is 0.995^168 ≈ 0.43; after a month it is 0.995^720 ≈ 0.027. The choice of decay constant is the load-bearing knob. Too aggressive (0.99 per hour) and any episode older than a few days drops out of the top-K regardless of importance; too gentle (0.999 per hour) and recency becomes effectively constant and the policy collapses to importance-plus-similarity. A defensible default for real-world wall-clock time is a half-life in the 7-to-30-day range, set explicitly; recency = exp(-Δt / τ) with τ chosen so that recency(τ) = 0.5.
Importance. The anchored 1-10 salience score, normalized to [0, 1] by dividing by 10. The dependency on the salience scorer producing a distributed score (and not the all-7s collapse) is what makes this term informative; the salience-collapse failure mode named in the segmentation piece is also the most common way the retrieval-side rerank silently regresses to similarity-plus-recency.
Similarity. Cosine similarity between the query embedding and the episode embedding, no normalization needed since cosine is already in [-1, 1] and effectively in [0, 1] for reasonable embedding models. The choice of embedding model matters here in the same way it matters everywhere; the text-embeddings article named the trade-offs; the relevant gotcha for retrieval policies specifically is that some embedding models have very tight cosine distributions (everything between 0.7 and 0.9 for any reasonable query/document pair), which silently squashes the similarity term’s dynamic range. Mitigation: rescale the observed cosine band to [0, 1] by min-max normalization over the recalled candidates, not over the global range.
Combination. Linear weighted sum: α·recency + β·importance + γ·similarity. The paper’s default is equal weights and the empirical result is that equal weights outperform any single-signal baseline by a wide margin. Workload-specific tuning matters at the margins; a customer-support agent where importance is the strongest signal benefits from β > α, γ; a coding agent where similarity-to-current-code matters most benefits from γ > α, β; a personal-assistant agent in long conversation where the most-recent preferences supersede older ones benefits from α > β, γ. But the variance from tuning is dwarfed by the variance between equal-weights and any single-signal baseline; get to equal-weights first, tune second.
Top-K selection. After computing the combined score for every candidate from the coarse recall (typically K_recall = 20-50), sort and take the top N (typically N_final = 3-10). The 4-to-1 oversampling ratio between recall and final is the standard pattern from the reranking article; recall has to be wide enough that the right episode is in the candidate set, even if it’s not the highest cosine hit; the rerank uses the additional signals to find it.
Update state after a read
Every successful retrieval should write back to the store. Three updates worth doing on every retrieval:
Update last_read_at. Each top-N episode gets its last_read_at advanced to the current time, which refreshes its recency term for the next retrieval. This is the LRU update, and it’s what keeps useful episodes from decaying out of the top-K just because they were written long ago. An episode written six months ago but read fifty times in the last week should have a recency term of nearly 1, not nearly 0; the last_read_at update is what makes that the case.
Increment retrieval_count. A monotonic counter on each episode, incremented on every successful retrieval. Optionally folded into the importance term as importance' = importance + δ · log(1 + retrieval_count) (logarithmic to avoid letting a few highly-retrieved episodes dominate the entire policy). This is the LFU contribution; frequency-of-use is a meaningful signal that the static write-time importance doesn’t capture.
Conditional importance boost. When an episode is retrieved and the agent’s subsequent answer cites it (or simply succeeds against a downstream evaluation), boost the importance. When an episode is retrieved and the answer goes badly, optionally demote. This is the read-driven salience update MemoryBank introduced; the Ebbinghaus-curve-inspired strengthening of memories that prove useful. It is the closest agent analogue to the brain’s reactivation-strengthens-memory consolidation pattern, and the closest cache analogue to the priority boost in priority-aware cache replacement.
The discipline that separates a useful read-driven update from a counterproductive one is bounded magnitude. A 5% boost per retrieval keeps the policy responsive to actual usage; a 50% boost per retrieval makes the importance term swing wildly on every read and the rerank becomes unstable. The Generative Agents paper uses a 0.995 per-hour decay on the recency term and effectively a constant 1.0 per-retrieval refresh on last_read_at; MemoryBank uses an Ebbinghaus-shaped S = S_0 · exp(-t/η) where η grows with retrieval count, so each retrieval extends the half-life rather than ratcheting up a separate score. Both are defensible; the wrong answer is to compound multiple unbounded boosts and watch the importance term diverge.
A normalize-and-blend implementation
The smallest interesting build: a retrieval policy that runs cosine recall, normalizes the three signals, blends them with tunable weights, updates the read-driven state, and returns the top-N. Uses Chroma as the substrate. Install: pip install chromadb numpy.
| |
Per-candidate min-max normalization makes the three signals comparable. Without it, a tight cosine band such as [0.6, 0.8] has much less range than recency and contributes little to the result. last_read_refresh_floor_s prevents a loop from refreshing every top-N episode on every second. delta_retrieval_count supplies a small LFU contribution; large values lock in old popular episodes even with logarithmic scaling. The policy uses a dataclass so weights and half-life can be calibrated per workload instead of being buried in the retrieval function.
Handle temporal queries and stale facts
Two non-obvious refinements show up in production retrieval policies and are worth knowing by name.
The anti-recency boost. Sometimes you want to surface old content; for example, when answering “what did we decide three months ago about X?” the answer is by construction old, and the recency term will push it down. The fix is to recognize the temporal intent of the query and invert the recency term for those queries; multiply by (1 - recency) rather than by recency; or, more often, drop the recency term entirely (set α = 0) when the query carries explicit temporal markers (“yesterday,” “last week,” “three months ago,” “originally”). Mem0 and Letta both expose temporal-intent flags on retrieval for this reason.
The staleness gate. Some content has explicit validity intervals; a knowledge-graph edge with valid_until set, a reflection whose source episodes have been superseded, a fact tagged with a confidence that has been demoted by a sleep-time consolidator. The retrieval policy should filter out (not just down-weight) any candidate that fails an explicit staleness check before scoring. A down-weighted stale candidate can still surface above a fresh one if the down-weight is small relative to the other signals; a hard filter is what enforces the staleness boundary.
The diversity penalty. A top-K dominated by five near-duplicates of the same episode wastes 4/5ths of the prompt budget on redundant content. The mitigation is a maximum-marginal-relevance (MMR) pass after the score-and-rank; for each candidate, deduct a fraction of its score for each higher-ranked candidate it’s textually similar to, so near-duplicates are spread across the top-K rather than concentrated at the top. The same MMR trick the reranking article named for static-corpus search applies here without modification.
Further reading
- Generative Agents: Interactive Simulacra of Human Behavior; Park et al., 2023; the canonical reference for the
α·recency + β·importance + γ·similarityformula. The §A.1 retrieval-function appendix has the exact formulation, the 0.995 per-hour decay constant, and the equal-weights baseline. Every production retrieval policy in 2026 is either a port of this formulation or a knowing divergence from it; read it as the empirical baseline the rest of the field calibrates against. - MemoryBank: Enhancing Large Language Models with Long-Term Memory; Zhong, Guo et al., AAAI 2024; introduces the Ebbinghaus-curve-shaped strengthening of memories under repeated retrieval. The mechanism (
S = S_0 · exp(-t/η)with η extended by each retrieval) is the cleanest formalization of read-driven salience updates, and the production memory frameworks that ship retrieval-count boosts are mostly variations on this. - Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory; Chhikara et al., ECAI 2025; the three-channel hybrid recall (semantic + BM25 + entity graph) and the channel-fusion pattern that underpins the 2026 production retrieval stack. The LOCOMO-benchmark numbers (91% lower p95 latency, ~90% token-cost reduction vs full-context baselines, 26% LLM-as-judge improvement over OpenAI’s memory baseline) are the strongest published evidence that channel fusion beats single-channel recall by a meaningful margin.
- ARC: A Self-Tuning, Low Overhead Replacement Cache; Megiddo & Modha, USENIX FAST 2003; the foundational cache-replacement paper that frames the LRU-vs-LFU trade-off as a workload-tunable parameter rather than a fixed design choice. The agent-memory analogue is the per-user weight tuning that Mem0 and Letta both expose; reading the ARC paper makes the trade-off’s shape much more legible than any agent-memory writeup alone.