Skip to content

Memory Engine Ranking

Document ID: MEM-005
File Path: docs/06-memory-engine/ranking.md
Version: 1.1.0
Status: Draft
Owner: AI Platform Team
Last Updated: 2026-07-13


This document defines how the Memory Engine orders the candidate set produced by Retrieval. Ranking decides which memories are most worth spending scarce context tokens on before Compression trims to the budget.

Good retrieval maximizes recall; good ranking maximizes the usefulness of what reaches the model.


SignalMeaningSource
relevanceSemantic/keyword match to the queryFusion score from retrieval
recencyHow recent the memory iscreated_at / updated_at
importanceIntrinsic value of the memoryStored importance field
frequencyHow often it has been usefulAccess/usefulness counters
proximityGraph distance from query entitiesKnowledge graph hops
confidenceSource trust / verificationlabels.confidence

The default ranking is a weighted sum of normalized signals:

score = w_rel * relevance
+ w_rec * recency_decay(age)
+ w_imp * importance
+ w_frq * frequency_norm
+ w_prx * proximity_decay(hops)

Default weights (tenant- and query-overridable via ranking.weights):

weights:
relevance: 0.55
recency: 0.20
importance: 0.15
frequency: 0.05
proximity: 0.05

All signals are normalized to [0,1] before weighting so no single raw scale dominates.


Recency uses exponential decay so fresh memories are favored without erasing durable knowledge:

recency_decay(age) = exp(-age / half_life)

Half-life is configurable per memory type, reflecting how fast each kind of memory goes stale:

TypeHalf-life (default)
Conversation2 days
Workflow14 days
Episodic90 days
Semantic / Organizational∞ (no decay)

Semantic facts (policies, docs) intentionally do not decay.

Implementation note (RM-AIM-P2 RAG-205): age is real wall-clock age against the record’s created_ms, stamped at ingestion from a Clock injected at the engine boundary (SystemClock in production, ManualClock in tests — the core stays clock-free). Before RAG-205 the implementation used insertion- sequence distance as a deterministic age proxy with these same numbers as “sequence units”; that proxy remains only as the fallback for legacy records stored without a timestamp (created_ms == 0), which are also excluded from any time-range-filtered query (an unknown creation time cannot be placed in a window — fail-closed).


importance is a stored [0,1] value set by:

  • Explicit caller assignment at write time
  • Heuristics (e.g. user-pinned, approval decisions, error post-mortems)
  • Background scoring (e.g. memories frequently retrieved and used)

Importance lets a highly relevant-but-trivial match lose to a slightly-less-relevant-but-critical one.


The Engine tracks how often a retrieved memory is actually used (the caller can report usage via the Event Bus). A memory repeatedly retrieved but never used is down-weighted over time; one consistently used is boosted. This creates a slow feedback loop toward genuinely useful memories.


Before returning, the ranker applies Maximal Marginal Relevance (MMR) to avoid returning N near-duplicates of the same fact:

MMR = λ * relevance(d) - (1-λ) * max_similarity(d, already_selected)

This trades a little relevance for coverage, so the result set spans distinct facts. Exact/near-duplicate collapsing is also handled here (and again in Compression).


After scoring, an ABAC policy pass (via the Policy Engine) drops any record the principal may not see based on content-derived attributes (e.g. a memory tagged pii:true for a principal lacking PII scope). Scope-level filtering already happened earlier in Retrieval §5.


The ranker returns each result with a score and a score_breakdown so callers and operators can see why something ranked where it did (see Memory API §7). This transparency is required for auditability and tuning.


  • Weights and half-lives are configurable per tenant and overridable per query.
  • The Engine logs ranking inputs so offline evaluation (NDCG, MRR against labeled relevance sets) can tune defaults.
  • A/B weight profiles can be assigned per project to compare ranking quality.

For a fixed corpus version and weight profile, ranking is deterministic. Feedback signals (frequency) are versioned by snapshot so a replayed query reproduces the historical ordering.


RequirementTarget
Ranking over 100 candidates< 5 ms p95
MMR diversification< 3 ms
Policy filter pass< 4 ms



VersionDateDescription
1.0.02026-06-27Initial Memory Engine Ranking specification
1.1.02026-07-13§4: recency now uses real wall-clock age via created_ms (RM-AIM-P2 RAG-205); the seq-distance proxy documented as the legacy fallback