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 fromDecayParams)λ(lambda) — Exponential decay rate for time elapsedμ(mu) — Decay rate for recency of accessage_days— Days since last updateaccess_count/days_since_access— Read frequency trackingbreadth_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:
- Soft delete —
Writer::soft_delete_for_decay_if_latestsetssuperseded_attimestamp, creating a decay tombstone - Hard delete —
Writer::hard_delete_decayed_page_chainpermanently 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
crates/ai-memory-store/src/decay.rs—retention_score,DecayParamsstruct, salience updatescrates/ai-memory-store/src/reader.rs—Reader::decay_candidatesfilter logiccrates/ai-memory-store/src/ops.rs—soft_delete_for_decay_if_latest,hard_delete_decayed_page_chaincrates/ai-memory-consolidate/src/curator.rs— Sweep orchestration and loggingdocs/ARCHITECTURE.md— High-level tier lifecycle specification
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →