Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content
Concepts

Retrieval semantics

How a recall query becomes an answer — routing, retrieval lanes, fusion scoring, budget tiers, and the explain breakdown.

When your agent calls recall(), Mubit does more than a vector search. The query is routed, candidates are gathered from several independent retrieval lanes, the lanes are fused into a single ranked evidence list, and an answer is synthesized with citations back into that list. This page explains each stage so you can predict what a query will return — and tune it when it doesn't.

Mental model: one query fans out into parallel retrieval lanes; fusion scoring merges them into one ranked evidence list; synthesis reads that list and cites it. Every knob on the request (entry_types, limit, rank_by, budget, temporal bounds) shapes exactly one of those stages.

Routing

Every query carries a mode:

ModeWhat happens
agent_routed (default)A router agent classifies the query and may expand it into a small set of alternative phrasings (variants) to improve semantic recall over paraphrased memories. Variants are grounded in the input — the router never invents new concepts — and are capped (default 3). Evidence is then synthesized into a final_answer.
direct_bypassSkips the router and answer synthesis; runs the direct semantic-search lane and returns raw evidence. Lower latency, no LLM in the loop.

Retrieval lanes

Candidates are gathered from independent lanes. Each returned evidence item is tagged with the lane that produced it in its retrieval_mode field:

retrieval_modeLane
semanticEmbedding similarity search over long-term memory (the main lane; also blends lexical/sparse term matching in fusion)
working_memoryLive working-memory variables and goals for the run (on by default; disable with include_working_memory=False)
chronologicalTemporal scan — activated when the request sets min_timestamp/max_timestamp; filters by each entry's occurrence time (falling back to ingest time)
trace_scanDirect scan over run traces
exact_referenceExact lookup by a stable reference_id (byte-for-byte re-read)
checkpointStored context checkpoints
rule_overlayRules injected regardless of similarity — hard constraints always ride along
lesson_overlayCross-run lessons injected by relevance (see The learning loop)
archive_overlayArchived artifacts surfaced alongside semantic hits
recency_fallbackMost-recent entries returned when no lane produced a confident match

Fusion scoring

Each candidate's final score is a weighted blend of component scores:

  • Semantic — embedding similarity to the query (and its variants).
  • Lexical — term/sparse match strength.
  • Recency — newer entries score higher. Recency decays exponentially with a half-life (default 7 days: an entry scores half as much at 7 days old, a quarter at 14).
  • Reinforcement — entries with positive outcome history (see record_outcome) get a multiplicative boost; a fully-reinforced, production-verified entry can reorder above fresher near-duplicates.

Two adjustments apply on top: entries whose stored env_tags intersect the request's env_tags get a relevance boost (conflicting tags get a small penalty), and superseded entries take a 0.5x stale penalty.

rank_by shifts the blend:

rank_byBehaviorWeights (semantic / lexical / recency)
relevance (default)Semantic-dominantcurrent default weights
freshnessRecency boosted0.50 / 0.10 / 0.40
balancedEven split0.60 / 0.15 / 0.25

Budget tiers

budget controls the latency/quality trade-off of candidate gathering:

budgetBehavior
lowSkips deep graph traversal, fewer ANN candidates — fastest
mid (default)Standard retrieval
highDeeper graph traversal, more candidates, optional reranking — best recall

Shaping the candidate set

Request fieldEffect
entry_typesOnly evidence of these types is returned (e.g. ["fact", "lesson"])
limitMaximum evidence items (default 5)
min_timestamp / max_timestampInclusive occurrence-time window (unix seconds); activates the temporal lane
env_tagsCaller's stack context, e.g. ["lang:python:3.12"] — boosts stack-matching entries
agent_idFilters evidence to the types in that agent's registered read_scopes
user_id / laneScope to one user's memories / one coordination lane
prefer_current_runCurrent-run evidence only; skips cross-run lesson overlay
evidence_onlySkip answer synthesis, return evidence only — saves the per-query LLM call
ℹ️Note

From SDK v0.12.0 the typed recall() helpers forward budget, rank_by, explain, min_timestamp/max_timestamp, and evidence_only directly in all three languages (client.recall(query=..., explain=True)). On earlier SDK versions these are wire-level fields the typed Python helper does not forward — send them directly over the transport (POST /v2/control/query with e.g. {"run_id": ..., "query": ..., "explain": true}) or via client.advanced.query({...}). entry_types, env_tags, limit, and the scope fields are recall() kwargs on every version. See Control HTTP API.

Explain

Set explain: true on the request and every evidence item carries an ExplainInfo breakdown. A returned evidence item looks like this:

{
  "id": "8f2c1a9e-...",
  "content": "CSV export fails when column headers contain commas; quote headers before export.",
  "source": "agent",
  "score": 0.81,
  "run_id": "support:acme:ticket-118",
  "entry_type": "lesson",
  "retrieval_mode": "lesson_overlay",
  "reference_id": "ltm:lesson:8f2c1a9e",
  "referenceable": true,
  "is_stale": false,
  "superseded_by": "",
  "knowledge_confidence": 0.74,
  "explain_info": {
    "semantic_score": 0.78,
    "lexical_score": 0.42,
    "recency_score": 0.31,
    "temporal_decay_factor": 0.62,
    "stale_penalty_applied": false,
    "temporal_intent_detected": false,
    "rank_by_mode": "relevance",
    "fusion_weights_used": { "semantic": 1.0, "lexical": 0.25, "recency": 0.1 }
  }
}

score is retrieval relevance for this query; knowledge_confidence is durable reliability of the entry itself — different axes. See Trust, confidence, and staleness.

Citations

When the response includes a synthesized final_answer, the citations field lists 0-based indices into evidence that the answer is grounded in. Indices are validated server-side against the evidence length, so every value is safe to dereference — use them to render citations or audit grounding. An empty list means the model cited nothing or abstained.

Example: Ari checks for a known error

Nimbus's support agent Ari gets a ticket about a failed CSV export and asks memory before answering:

result = client.recall(
    session_id="support:acme:ticket-241",
    query="Have we seen this CSV export error before?",
    entry_types=["lesson", "fact", "trace"],
    env_tags=["service:export", "format:csv"],
    limit=5,
)
for i in result.get("citations", []):
    print(result["evidence"][i]["content"])

The recurring CSV-export bug has produced lessons in earlier runs, so the lesson_overlay lane surfaces them even though this ticket is a brand-new run — that cross-run carry-over is the point of the overlay lanes.

Related