Sleep-time consolidation
Memory reorganizes itself while the agent is idle — duplicates merge, scattered entity facts distill into mental models, and raw evidence is never deleted.
Agents write memory under time pressure: mid-task, one observation at a time, with no view of what the last hundred entries add up to. Consolidation is the counterweight — a background worker that uses idle time to turn accumulation into organization. Use this pattern (mostly: understand and observe it, since it's on by default on hosted instances) when a long-lived scope is collecting many entries about the same entities and you want distilled knowledge to emerge without an explicit pipeline.
How it works
The consolidation worker sweeps periodically and only touches scopes that have gone idle — no ingestion activity for a couple of minutes — because reorganizing memory underneath an actively writing agent would be a race. Each sweep does two kinds of work:
- Merge near-duplicate guidance. Lessons and rules that write-time reconciliation missed — paraphrases that arrived through different paths — are merged behind one canonical entry. Merges are deterministic and cheap, so they are not budget-capped.
- Distill entity fact clusters. When enough entries accumulate about one entity ("Acme Corp" mentioned across dozens of facts and observations), the worker distills the cluster into a consolidated, entity-level summary grounded only in the source entries, with the source IDs kept as provenance. Recurring, high-confidence summaries are promoted into
mental_modelentries — the section injected first in assembled context, ahead of rules, lessons, and raw facts (see Context priority).
Distillation calls an LLM, so each sweep runs under a bounded per-sweep budget of distillation operations — consolidation is deliberately slow and steady rather than exhaustive. The same idle-time worker also hosts workflow induction (see Procedural memory), guardrail distillation (see The learning loop), and, when enabled, utility-weighted forgetting.
What it never does: delete raw evidence. Merged duplicates are superseded — flagged with superseded_by and a consolidated_into pointer — and distilled summaries carry source_ids back to the entries they came from. Consolidation adds a distilled layer on top of episodic history; it does not replace it.
Walkthrough
A week of Acme tickets leaves Ari's scope with dozens of scattered Acme facts and observations. You don't call anything — you observe what the worker does with them.
# Before: many raw entries, no distilled layer.
before = client.memory_health(session_id="support:acme")
print(before["entry_counts"])
# {'fact': 38, 'observation': 21, 'trace': 64, 'lesson': 5, ...}
# ... the scope goes idle; consolidation sweeps run ...
after = client.memory_health(session_id="support:acme")
print(after["entry_counts"])
# Consolidated entity summaries appear; near-duplicate guidance collapses
# behind canonical entries.
# The payoff shows up in assembled context: the distilled Acme profile
# now leads the block, before rules, lessons, and raw facts.
ctx = client.get_context(
session_id="support:acme",
query="Acme export ticket",
)
print(ctx["context_block"])## Mental Models
- Acme Corp support profile: Scale plan since May 3, CSV-heavy usage,
exports peak on Mondays, prior export-timeout incidents resolved via
the batched exporter.
## Lessons Learned
- When an export times out, check the report row count before retrying
...Every agent that queries this scope now gets the one-paragraph Acme picture first, instead of re-deriving it from 59 scattered entries — and Sana's weekly digest reads the same distilled profile Ari's tickets built.
Two ways to observe the worker over time:
memory_health()before and after idle periods — watchentry_countsgain distilled types while near-duplicate guidance collapses behind canonical entries.mental_modelentries appearing inget_context()— the "Mental Models" section materializing at the top of context blocks is consolidation paying rent.
You can also write mental_model entries yourself (intent="mental_model") when you already have a curated entity summary — see SDK methods → Mental models. Consolidation is the automatic path to the same entry type.
When not to rely on it
Consolidation is eventually consistent by design — it waits for idle windows and spends a bounded budget per sweep. Don't lean on it when:
| Need | Reach for instead |
|---|---|
| The very next query must see a deduplicated, reconciled store | Write-time reconciliation — reconcile synchronously at the write, don't wait for sleep |
| A belief must flip the moment a contradicting fact arrives | Bi-temporal supersession at write time — see Bi-temporal memory |
| You have a curated summary ready now | Write the mental_model entry explicitly instead of waiting for distillation |
| The scope never goes idle (continuous high-rate ingestion) | Idle-gated sweeps won't touch it; reconcile at write time and consider splitting the scope |
Related
- The memory model —
mental_modelandobservationin the entry taxonomy, and why mental models lead context assembly - Write-time reconciliation — the synchronous counterpart that catches duplicates before they land
- Procedural memory — workflow induction, the other thing idle sweeps distill
- Utility-weighted forgetting — the opt-in archival pass that shares the same idle worker
- The learning loop — where consolidation sits among the runtime's maintenance features
- Trust, confidence, and staleness —
memory_health()fields in detail
Configuration. Consolidation is an instance feature, on by default on hosted instances (MUBIT_CL_SLEEP_CONSOLIDATE=0 disables it). Instance knobs: MUBIT_CL_CONSOLIDATE_IDLE_SECS (how long a scope must be quiet before it's touched, default 120), MUBIT_CL_CONSOLIDATE_INTERVAL_SECS (sweep cadence, default 300), and MUBIT_CL_CONSOLIDATE_MAX_LLM_OPS (distillation budget per sweep, default 4 — deterministic merges are uncapped).