How ai-memory Handles Memory Decay Across Tiers
ai-memory applies a nightly retention sweep that calculates a composite score combining exponential time decay and access frequency, then applies tier-specific rules: working memory stays pinned indefinitely, episodic content faces eviction when scores drop below 0.20, semantic knowledge persists longer through elevated salience, and procedural patterns remain indefinite until frequency thresholds fail.
The ai-memory project implements a sophisticated forgetting mechanism that mimics human memory by organizing content into four distinct tiers. This article examines how the system calculates memory decay through its retention scoring algorithm and applies different survival rules based on whether content lives in working, episodic, semantic, or procedural storage.
The Retention Score Formula
At the heart of the decay system lies the retention_score function defined in crates/ai-memory-store/src/decay.rs. This pure function computes a value between 0 and 1 determining whether a page survives the nightly M8 retention sweep.
The calculation combines two distinct psychological principles:
Exponential Time Decay
The time term applies exponential decay based on page age: salience × exp(−λ × age_days). With the default lambda (λ) of 0.02 defined in the DecayParams struct, content exhibits approximately a 35-day half-life unless other factors intervene.
Access Frequency Boost
The access term rewards recent interactions: σ × log(1 + access_count) × exp(−μ × days_since_access) × breadth. This logarithmic scaling prevents highly accessed pages from dominating indefinitely while still offering protection against decay. The optional breadth factor rewards pages read by many distinct operators.
Tier-Specific Decay Policies
The Tier enum defined in crates/ai-memory-core/src/page.rs establishes four distinct survival strategies. The system checks the tier column during the sweep to apply these rules:
Working Tier: Pinned Indefinitely
Pages in the working tier possess a pinned = true flag in the database. According to the reader implementation in crates/ai-memory-store/src/reader.rs (around line 1116), the sweep explicitly excludes pinned pages, and tests in the wiki module verify this with assert!(candidates[0].pinned). Working memory represents the active session context and never decays.
Episodic Tier: Eviction on Cold Threshold
Episodic memory stores recent session logs and operational history. After calculating the retention score, the system compares it against cold_threshold (default 0.20 from DecayParams). Pages scoring below this threshold receive a decay-tombstone—setting superseded_at to a non-null timestamp—marking them as eviction candidates without immediate deletion.
Semantic Tier: Extended Longevity
Semantic pages contain long-term knowledge and benefit from higher default salience values. As documented in docs/design-decisions.md, semantic content follows a "30 days hot, 180 days cold" policy. The elevated salience multiplier in the time decay formula allows semantic memories to persist well beyond episodic content before facing eviction.
Procedural Tier: Indefinite Retention
Procedural memory stores extracted patterns from repeated episodic content. Unlike other tiers, procedural pages are indefinite and ignore the cold threshold entirely. According to the design documentation, these entries persist until a separate frequency-decay mechanism removes them only after remaining unobserved for a configurable duration.
The Decay Sweep Process
The M8 retention sweep orchestrates the actual forgetting mechanism through coordinated database operations in crates/ai-memory-store/src/ops.rs.
Soft Deletion via Tombstones
When a page's score falls below its tier threshold, the sweep calls soft_delete_for_decay_if_latest. This creates a decay-tombstone row that preserves the content for hard_delete_after_days (default 180 days) while marking it as superseded.
Permanent Hard Deletion
After the grace period expires, the background job hard_delete_decayed_page_chain permanently removes the tombstone and all ancestry records. This prevents unbounded database growth while maintaining a short-term audit trail of forgotten content.
Computing Individual Retention Scores
Before the nightly sweep runs, you can manually calculate retention scores using the pure function exported from decay.rs:
use ai_memory_store::{DecayParams, retention_score};
let params = DecayParams::default(); // λ=0.02, σ=0.6, μ=0.04
let score = retention_score(
¶ms,
90.0, // age_days
12, // access_count
Some(3.0), // days_since_access
None, // salience (uses default 1.0)
);
println!("Retention score = {}", score);
Configuring Decay Parameters
Developers can customize decay behavior through the DecayParams struct. The following example demonstrates tuning for aggressive forgetting:
use ai_memory_store::DecayParams;
use ai_memory_mcp::Server;
let mut params = DecayParams::default();
params.lambda = 0.04; // ~17-day half-life
params.cold_threshold = 0.15; // Evict earlier
params.hard_delete_after_days = 90; // Shorter grace period
let server = Server::new().with_decay_params(params);
For collaborative environments, enable breadth weighting to slow decay for pages accessed by multiple distinct operators using the retention_score_with_breadth function:
// access_term × (1 + breadth_weight × ln(distinct_actors + 1))
let mut params = DecayParams::default();
params.breadth_weight = 0.5; // Reward multi-user pages
Querying Decay Candidates
The reader module exposes methods to preview which pages face eviction before the sweep executes:
// Returns DecayCandidate structs containing path, tier, and current score
let candidates = store.reader.decay_candidates(ws, proj).await?;
for c in candidates {
println!("{} – tier: {} – score: {}", c.path, c.tier, c.score);
}
Summary
- ai-memory calculates memory decay using a composite score combining exponential age decay and logarithmic access frequency in
crates/ai-memory-store/src/decay.rs. - Working tier pages remain pinned indefinitely and bypass the retention sweep entirely.
- Episodic tier content faces eviction when retention scores drop below the
cold_threshold(default 0.20), creating tombstoned records for 180 days. - Semantic tier knowledge persists longer through elevated salience values, following documented hot/cold period policies.
- Procedural tier patterns enjoy indefinite retention until explicit frequency-decay thresholds trigger removal.
- Hard deletion occurs via
hard_delete_decayed_page_chaininops.rsafter the configurable grace period expires.
Frequently Asked Questions
How is the retention score calculated for a specific page?
The retention_score function in crates/ai-memory-store/src/decay.rs computes a value based on two terms: a time decay component (salience × exp(−λ × age_days)) and an access frequency component (σ × log(1 + access_count) × exp(−μ × days_since_access)). These combine to produce a score between 0 and 1 that determines eviction eligibility during the nightly sweep.
Can working memory ever be deleted by the decay process?
No. Working tier pages carry a pinned = true flag in the database that explicitly excludes them from the retention sweep, as enforced in crates/ai-memory-store/src/reader.rs. This ensures active session context remains available regardless of age or access patterns.
What happens to episodic memories that fall below the cold threshold?
When episodic pages score below cold_threshold (default 0.20), the system creates a decay-tombstone by setting superseded_at to a timestamp via soft_delete_for_decay_if_latest in ops.rs. The content remains queryable for hard_delete_after_days (default 180 days) before hard_delete_decayed_page_chain permanently removes it.
How does procedural memory differ from semantic memory in decay behavior?
Procedural memory remains indefinite and ignores the cold threshold eviction rule, persisting until frequency-decay detects extended unobserved periods. Semantic memory, while using the same scoring formula, typically carries higher salience values that delay decay, following documented retention windows (30 days hot, 180 days cold) before potential eviction.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →