Memory Consolidation and Decay
Most agent memory systems are built for the first week. Writing memories is easy, retrieval works well on a small store, and the demo is convincing.
The problems arrive at month three. The store has tens of thousands of items. The same fact is written eleven times in slightly different words. A decision made in January still ranks highly for a query about the architecture it was replaced by in April. Retrieval quality is measurably worse than it was at launch, and nothing in the system is designed to fix that.
An append-only memory store doesn't get better as it grows. It gets noisier. Consolidation and decay are the maintenance layer that prevents this.
The two failure modes
Redundancy. An agent working on the same codebase across fifty sessions will record "the API uses OAuth2" a dozen times. Each write is individually reasonable. Collectively they crowd the top of every related search result with variations of one fact, pushing out the diversity you actually needed.
Staleness. Facts change. The database migrates, the convention is revised, the user changes their mind. Vector similarity has no opinion about age — a superseded decision from January is exactly as retrievable as its replacement, and an agent that pulls both will produce confidently wrong output.
Neither is fixable at query time. Both need a process that modifies the store.
Consolidation: four phases
phorvec's consolidation runs as a four-phase pass over the memory store, triggered explicitly with memory_consolidate or on a schedule set in config.toml.
1. Deduplication
Identify near-duplicate memories — cosine similarity above a configurable threshold — and merge them, keeping the higher-importance version.
The threshold is the interesting knob. Set it too low and you merge genuinely distinct facts that happen to be phrased similarly. Too high and obvious duplicates survive. It's exposed as configuration rather than hardcoded because the right value depends on what you're storing: terse structured facts cluster much more tightly than free-form conversation turns.
2. Compression
Summarise clusters of related low-importance memories into a single representative item.
The importance filter is what makes this safe. Fifty low-value observations about a refactor compress to one summary without losing anything you'd miss. The same operation applied to high-importance items would be destructive — which is why it isn't.
3. Association
Build or update knowledge-graph edges between memories that are semantically linked but never explicitly connected.
This is the phase that turns a flat store into something navigable. Two memories written six weeks apart in different sessions may describe the same subsystem; nothing links them at write time because neither session knew about the other. Association discovers the connection after the fact, which makes graph traversal — "what else touches this?" — actually productive.
4. Archival
Move memories below the importance threshold out of the active zone.
Note out of the active zone, not deleted. Archived items are excluded from default search but remain accessible with explicit filters. The distinction matters: consolidation should never be the thing that loses information irreversibly.
Decay: importance as a function of time
Consolidation handles redundancy. Decay handles relevance.
Human memory doesn't hold everything at equal strength — importance fades unless something is reinforced. phorvec models the same behaviour with an explicit half-life:
importance(t) = initial_importance × 0.5^(t / half_life)
t is the item's age in hours; half_life is configured under [context]. An item at a 24-hour half-life retains half its importance after a day, a quarter after two.
The effect is that recent working context outranks old working context by default, without anything having to explicitly demote the old material. Items that decay below a threshold become candidates for archival or deletion.
Previewing before it happens
Decay is destructive-ish and time-dependent, which makes it hard to reason about in advance. context_decay_preview projects the importance of current items at a future time without modifying anything — so you can see what's about to fall off a cliff and decide whether to intervene.
Pinning: the necessary escape hatch
Decay without an exemption is dangerous. Some things must never fade regardless of age:
- A user's stated allergy or accessibility requirement
- A hard architectural constraint
- A security policy
- Anything the user explicitly asked the agent to remember
context_pin marks an item exempt from decay and automatic cleanup. Pinned items are also automatically anchored against retention sweeps, so a pin is a genuine guarantee rather than a delay — it holds across both the decay and retention systems.
The general principle: automatic forgetting needs a manual override, and the override must be honoured by every subsystem that deletes things. A pin that decay respects but garbage collection ignores is worse than no pin at all, because it's a guarantee that silently isn't one.
Retention zones: the deletion pipeline
Decay lowers importance. Retention policy governs what ultimately happens to low-importance items, and it's deliberately staged:
Active → Archived → PurgeQueue
- Active — in regular use; returned by default search.
- Archived — below the importance threshold or past the retention window; excluded from default search, still retrievable with explicit filters.
- PurgeQueue — scheduled for deletion, no longer accessible. Items land here after the archive grace period expires.
Nothing is deleted in one step. Each transition has a configurable grace period, per-agent or global, which lets different agents run genuinely different policies: a coding agent might archive after 7 days and purge after 30, while a research agent keeps its archive for 180.
retention_sweep processes the purge queue, permanently deleting items past their grace period. Anchored items — including everything pinned — are exempt regardless of age.
The multi-stage design exists because deletion is the one irreversible operation in the system. Two grace periods and an anchor flag mean an item has to survive several independent checks before anything is destroyed.
Reclaiming space
memory_gc is the separate housekeeping step: it removes items from the purge queue, cleans up orphaned graph nodes left behind by merges and deletions, and reclaims disk space. It's safe to run at any time.
Orphaned graph nodes are the subtle part. Deduplication merges two memories into one; the graph edges pointing at the discarded version now reference nothing. Individually harmless, but they accumulate and make graph traversal progressively slower and noisier. Garbage collection is where that gets cleaned up.
Promotion: moving between layers
Context and long-term memory are separate stores with separate lifecycles, and the boundary needs to be crossable in both directions.
memory_promote elevates a context item directly into long-term memory, optionally adjusting its importance. This is how an insight from the current session gets locked in before working context decays away — you don't wait for a heuristic to notice it mattered, you say so.
For content that shouldn't decay with conversation turns at all — user preferences, style guides, stable environment facts — memory blocks are the right home: named, durable items that live outside the decay cycle entirely and can be shared across agents by reference rather than by copying.
A working maintenance policy
- Run consolidation on a schedule — nightly is a reasonable default for an active agent.
- Set the decay half-life to match your session rhythm. Hours for a fast-moving coding agent; days or weeks for a long-horizon research agent.
- Pin aggressively. Anything a user explicitly asked to be remembered should be pinned at write time, not left to importance heuristics.
- Preview before purging. Run
context_decay_previewbefore the firstretention_sweepon a store you care about. - Keep grace periods generous. Disk is cheap; a memory you deleted is gone.
Further reading
The Core Features reference documents consolidation, decay, retention zones and memory blocks in full. What Is AI Agent Memory? covers where these stages sit in the wider lifecycle.
pip install phorvec