How the Decay Policy Works for Different Memory Tiers in ai-memory

The decay policy applies a four-tier retention strategy where working memory remains permanently pinned, episodic memory decays based on a mathematical retention score, and semantic/procedural memory persists long-term through elevated salience values.

In the akitaonrails/ai-memory system, every unit of knowledge is stored as a page (a markdown file) assigned to one of four distinct tiers defined in the Tier enum. The decay policy governs how these pages age out of the system using the configurable DecayParams struct, allowing projects to balance storage constraints against knowledge retention requirements.

The Four Memory Tiers

The Tier enum in crates/ai-memory-core/src/page.rs (lines 22-30) categorizes knowledge into four groups, each with specific decay behaviors enforced by the retention engine.

Working Memory

Working memory contains short-lived session data that must remain available for the active context. When the slot-page writer creates pages in this tier, it automatically sets pinned = true, causing the decay sweep to skip them entirely. As implemented in crates/ai-memory-wiki/src/wiki.rs (lines 721-734), any page carrying the pinned flag is excluded from eviction regardless of its age or access patterns.

Episodic Memory

Episodic memory stores per-session summaries and concepts and is subject to active decay. The periodic forget-sweep calls Reader::decay_candidates in crates/ai-memory-store/src/reader.rs (lines 3294-3318) to fetch all non-pinned pages. For each candidate, the system calculates a retention score using retention_score or retention_score_with_breadth from crates/ai-memory-store/src/decay.rs (lines 48-74). If the score falls below the cold_threshold (default 0.20), the page becomes an eviction candidate and may be soft-deleted via Writer::soft_delete_for_decay_if_latest in crates/ai-memory-store/src/writer.rs (lines 1432-1451).

Semantic Memory

Semantic memory holds long-term factual and wiki pages that are generally immune to decay. While the sweep still evaluates these pages, they typically maintain scores above the cold_threshold due to higher default salience values or manual pinning. This design ensures critical reference material persists indefinitely while still allowing administrators to force removal when necessary.

Procedural Memory

Procedural memory contains reusable patterns extracted from episodic clusters. The decay policy treats these pages identically to semantic memory, assigning higher base salience that resists standard retention decay. Like semantic pages, they rely on elevated initial salience or explicit pinning to remain above eviction thresholds.

How the Retention Score Is Calculated

The retention_score function in crates/ai-memory-store/src/decay.rs (lines 48-74) computes a floating-point value between 0.0 and 1.0 that determines whether a page survives the next sweep. The calculation combines three mathematical factors:

  1. Age decay: salience * exp(-λ * age_days) — The base salience fades exponentially over time using the decay constant λ (lambda).
  2. Access reinforcement: σ * log(1 + access_count) * exp(-μ * days_since_access) — Recent access patterns boost retention, but this bonus itself decays based on the access decay constant μ (mu).
  3. Breadth weighting: When breadth_weight > 0, the retention_score_with_breadth function (lines 77-102) adds a bonus proportional to distinct_actors, rewarding pages accessed by many different operators.

The parameters λ (lambda), σ (sigma), μ (mu), and default salience values are configurable per project via the [decay] section in config.toml and injected through Builder::with_decay_params in crates/ai-memory-mcp/src/server.rs (lines 382-388).

The Decay Sweep Process

The decay sweep operates as a background maintenance routine with three distinct phases:

  1. Candidate selection: The Reader::decay_candidates method queries for all pages where pinned is false, returning the entire corpus of evictable knowledge.
  2. Score evaluation: Each candidate's retention score is computed against the project's DecayParams. Pages scoring below cold_threshold (0.20) are marked as cold.
  3. Graduated deletion: Cold pages are soft-deleted immediately via soft_delete_for_decay_if_latest. After hard_delete_after_days (default 180 days), these entries are permanently purged from storage.

Pinning and Configuration

You can override the tier-based decay logic for any individual page by setting pinned: true in the page metadata. This flag takes precedence over all scoring calculations, making it useful for preserving critical episodic data that would otherwise age out.

use ai_memory_store::decay::{DecayParams, retention_score};
use ai_memory_core::page::Tier;

// Initialize default decay parameters
let params = DecayParams::default(); // lambda=0.02, sigma=0.6, cold_threshold=0.20

// Calculate retention for a 6-month-old episodic page with 12 accesses
let score = retention_score(&params, 180.0, 12, Some(2.0), None);

if score < params.cold_threshold {
    println!("Page qualifies for decay");
}

To pin a page permanently:

let new_page = NewPage {
    workspace_id,
    project_id,
    path,
    title,
    body,
    tier: Tier::Episodic,
    pinned: true, // Decay sweep will ignore this page
    ..Default::default()
};
wiki.write_page(new_page).await?;

Summary

  • Working memory pages are automatically pinned and never decay.
  • Episodic memory pages calculate retention scores based on age, access frequency, and breadth, expiring when scores drop below 0.20.
  • Semantic and procedural memory tiers rely on high base salience to remain immune from standard decay sweeps.
  • The pinned flag overrides all tier logic, granting permanent immunity to any page.
  • Configuration occurs through DecayParams in config.toml, controlling lambda, sigma, mu, and deletion thresholds.

Frequently Asked Questions

How do I prevent specific episodic pages from decaying?

Set the pinned field to true when creating or updating the page. This flag causes the decay sweep to skip the page entirely, regardless of its tier or retention score, as implemented in the filter logic of crates/ai-memory-wiki/src/wiki.rs (lines 721-734).

What happens when a page's retention score drops below the cold threshold?

The page is marked as a decay candidate and soft-deleted via Writer::soft_delete_for_decay_if_latest in crates/ai-memory-store/src/writer.rs (lines 1432-1451). It remains recoverable until hard_delete_after_days (180 days by default) elapses, at which point it is permanently removed from the store.

Can I adjust how aggressively episodic memory decays?

Yes. Modify the lambda (age decay rate), sigma (access weight), and mu (access decay rate) values in the [decay] section of your config.toml. These parameters are injected into the store via Builder::with_decay_params in crates/ai-memory-mcp/src/server.rs (lines 382-388) and directly influence the retention score calculation in crates/ai-memory-store/src/decay.rs.

Why does working memory not use the retention scoring system?

Working memory is designed for ephemeral session data that should persist only for the active context. The slot-page writer automatically sets pinned = true for all working tier pages, effectively excluding them from the decay_candidates query and ensuring they remain available until explicitly removed or the session ends.

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 →