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(
    &params,
    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_chain in ops.rs after 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →