How Does Episodic Memory Tier Decay Work in ai-memory?

Episodic memory decay uses a retention-score formula combining exponential time decay, access frequency, and actor breadth to evict short-term session pages after ~30 days hot, ~180 days cold.

The Episodic tier in akitaonrails/ai-memory represents short-term, per-session memory that naturally degrades over time. Understanding its decay mechanism is essential for tuning memory retention in production AI applications. This article examines the three-phase decay process implemented in the Rust codebase.

The Three-Phase Episodic Decay Lifecycle

According to the architecture documentation, Episodic pages follow a strict temperature-based progression: 30 days hot, ~180 days cold, then eviction if retention scores fall below threshold.

Phase 1: Retention Score Calculation

The core decay logic resides in crates/ai-memory-store/src/decay.rs. When a forget sweep runs, each Episodic page's score is recomputed using the retention_score and retention_score_with_breadth functions.

The formula combines three weighted factors:


score = salience·exp(‑λ·age_days)
        + σ·log(1 + access_count)·exp(‑μ·days_since_access)
        × (1 + breadth_weight·ln(1 + max(distinct_actors‑1,0)))

Parameter breakdown:

  • salience — Page-specific importance (or default from DecayParams)
  • λ (lambda) — Exponential decay rate for time elapsed
  • μ (mu) — Decay rate for recency of access
  • age_days — Days since last update
  • access_count / days_since_access — Read frequency tracking
  • breadth_weight — Multiplier for pages touched by many distinct actors

Default decay parameters (λ ≈ 0.03, μ ≈ 0.1) are configurable via [decay] section in ai_memory.toml.

Phase 2: Decay Candidate Selection

The Reader::decay_candidates function in crates/ai-memory-store/src/reader.rs identifies pages eligible for eviction. It filters for:

  • Tier must be Episodic
  • Page must not be pinned
  • Either: older than hot period (30 days) with zero accesses, or retention score below configured threshold

This dual criteria prevents premature eviction of actively accessed pages while catching dormant ones.

Phase 3: Tombstone Creation and Hard Deletion

Selected candidates undergo two-step removal:

  1. Soft deleteWriter::soft_delete_for_decay_if_latest sets superseded_at timestamp, creating a decay tombstone
  2. Hard deleteWriter::hard_delete_decayed_page_chain permanently removes tombstone and ancestry chain

Both operations reside in crates/ai-memory-store/src/ops.rs.

The curator component in crates/ai-memory-consolidate/src/curator.rs orchestrates this sweep, logging "cold episodic" pages and triggering retention-based decisions.

Configuring Decay Parameters

Create or modify ai_memory.toml to tune Episodic decay behavior:

[decay]
lambda = 0.03           # Time decay rate (higher = faster decay)

mu = 0.1                # Access recency decay rate

salience_default = 1.0  # Base importance for unmarked pages

breadth_weight = 0.5    # Boost for multi-actor pages

threshold = 0.1         # Score floor for eviction eligibility

Practical Example: Simulating Episodic Decay

use ai_memory_core::Tier;
use ai_memory_store::Store;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut store = Store::open("memory.db").await?;
    
    // Create episodic session memory
    let page_id = store
        .write_page(
            "sessions/chat-2024-01-15.md",
            Tier::Episodic,
            "User asked about Rust async patterns...",
        )
        .await?;
    
    // Simulate access pattern
    store.record_access(page_id).await?;
    
    // Fast-forward 45 days (testing utility)
    store.advance_time_by_days(45).await?;
    
    // Trigger decay sweep (normally background scheduled)
    let decayed = store.run_decay_sweep().await?;
    println!("Evicted {} episodic pages", decayed.len());
    
    Ok(())
}

Key Implementation Files

Summary

  • Episodic decay combines exponential time decay, access frequency, and actor breadth into a single retention score
  • Hot period (30 days) protects recent pages; cold period (~180 days) allows recovery before final eviction
  • Two-phase deletion (tombstone → hard delete) preserves auditability while reclaiming storage
  • All parameters configurable via TOML without code changes

Frequently Asked Questions

How is the retention score different from simple TTL expiration?

TTL expires pages at fixed timestamps regardless of usage. The retention score dynamically adjusts based on access patterns—frequently-read pages survive longer, while untouched pages decay faster. The log(1 + access_count) and exp(‑μ·days_since_access) terms create this adaptive behavior.

Can pinned Episodic pages ever be evicted?

No. The decay_candidates query explicitly excludes pinned pages. Pinning overrides the entire decay mechanism, making it suitable for preserving critical session context across arbitrary time periods.

What happens to decayed page relationships and ancestry?

The hard_delete_decayed_page_chain function removes not just the tombstoned page but its entire ancestry chain. This prevents orphaned references and ensures referential integrity within the memory graph.

How do I monitor which Episodic pages are being decayed?

The curator component emits structured logs for "cold episodic" pages at INFO level. Enable logging in your application and filter for ai_memory_consolidate::curator to observe sweep decisions in real time.

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 →