How memory_feedback Signals Influence Page Salience and Decay Thresholds

The memory_feedback mechanism allows agents to directly adjust a page's salience score by raising or lowering it by SALIENCE_STEP, or resetting it to the floor when marked stale, which indirectly determines whether the page's retention score falls below the cold_threshold and becomes eligible for eviction.

The akitaonrails/ai-memory repository implements a semantic memory store for AI agents where content naturally decays over time. The memory_feedback signal serves as the critical interface for agents to communicate content utility, directly manipulating the salience value that acts as a multiplier in the retention formula to control eviction priorities.

The Feedback-to-Salience Pipeline

When an agent submits a memory_feedback signal, the store executes a three-phase transaction in crates/ai-memory-store/src/ops.rs to translate subjective utility into an objective retention score.

Looking Up Current Salience

First, the system locates the target page and retrieves its current salience value. In crates/ai-memory-store/src/ops.rs at lines 51–57, the record_page_feedback function queries the latest page version, falling back to the default salience if no prior feedback exists.

Computing the New Salience

Next, the pure helper salience_after_feedback in crates/ai-memory-store/src/decay.rs (lines 41–53) calculates the adjusted value based on the FeedbackKind:

  • Helpful → increases salience by SALIENCE_STEP
  • NotHelpful → decreases salience by SALIENCE_STEP
  • Stale or Wrong → immediately drops salience to SALIENCE_MIN (the floor value)

The result is clamped between SALIENCE_MIN (0.25) and SALIENCE_MAX (2.0) as defined in crates/ai-memory-store/src/decay.rs at lines 22–30.

Persisting Changes

Finally, the transaction appends a record to the page_feedback table and updates the salience column in the pages table (defined in crates/ai-memory-store/src/page.rs at lines 250–260). This occurs in crates/ai-memory-store/src/ops.rs at lines 86–92, ensuring the new salience is immediately available to the retention calculator.

Salience Bounds and Calculation Constants

The salience adjustment operates within strict bounds to prevent runaway values:

// From crates/ai-memory-store/src/decay.rs
pub const SALIENCE_MIN: f64 = 0.25;
pub const SALIENCE_MAX: f64 = 2.0;
pub const SALIENCE_STEP: f64 = 0.25; // Typical step size

A Helpful signal increments salience by the step size, making the page more resistant to time-based decay. Conversely, NotHelpful decrements it, accelerating the page's path toward the eviction threshold.

From Salience to Retention Score

Salience directly influences the retention score computed in crates/ai-memory-store/src/decay.rs (lines 13–30). The formula treats salience as a multiplier on the time-decay term:


retention_score = salience × exp(-λ × age) + access_reinforcement

Where:

  • salience is the current value stored in the page row
  • λ (lambda) is the decay coefficient from DecayParams
  • age is the time since creation

Because the time term is multiplicative, raising salience lifts the overall score above the cold_threshold (default 0.20), protecting the page from the forget-sweep job. Lowering salience (via negative feedback) reduces the score and can push the page below the threshold, marking it for eviction.

Recording Feedback in Practice

Using the Rust API

The low-level record_page_feedback function in crates/ai-memory-store/src/ops.rs provides direct access:

use ai_memory_store::{
    ops::record_page_feedback,
    decay::DecayParams,
};
use ai_memory_core::{FeedbackKind, UserId, PagePath, WorkspaceId, ProjectId};

fn give_feedback(
    conn: &mut rusqlite::Connection,
    ws: WorkspaceId,
    proj: ProjectId,
    path: &PagePath,
) -> anyhow::Result<()> {
    // Mark the page as helpful with a short reason
    let (page_id, new_salience) = record_page_feedback(
        conn,
        ws,
        proj,
        path,
        FeedbackKind::Helpful,
        Some("the answer was spot-on"),
        Some(UserId::new()),        // author (optional)
        &DecayParams::default(),    // tuned decay coefficients
    )?
    .expect("page must exist");
    
    println!("Page {page_id} now has salience {new_salience}");
    Ok(())
}

Using the CLI

The ai-memory binary exposes feedback functionality to shell scripts and manual curation:


# Record a "not helpful" feedback on a page

ai-memory memory_feedback \
    --workspace my_ws \
    --project my_proj \
    --path docs/quickstart.md \
    --kind not_helpful \
    --reason "out-of-date example"

The CLI forwards the request to the MCP server, which executes the same record_page_feedback logic against the SQLite backing store.

Measuring the Impact on Decay

You can observe how feedback alters retention priorities by comparing scores before and after salience adjustments:

use ai_memory_store::{decay::{RetentionScore, DecayParams}, decay::retention_score};

let params = DecayParams::default();
let age_days = 30.0;
let access_count = 5;
let days_since_access = Some(1.0);

// No feedback (salience = default)
let score_no_fb = retention_score(&params, age_days, access_count, days_since_access, None);

// After a "Helpful" feedback (salience increased by SALIENCE_STEP)
let elevated_salience = params.salience_default + 0.25; // SALIENCE_STEP
let score_helpful = retention_score(&params, age_days, access_count, days_since_access, Some(elevated_salience));

println!("Score before feedback: {score_no_fb}");
println!("Score after helpful feedback: {score_helpful}");

The second score will be higher because the elevated salience boosts the time-decay component, keeping the page above the cold_threshold longer than unhelpful or neutral content.

Summary

  • The memory_feedback signal directly modifies the salience column in crates/ai-memory-store/src/page.rs via the record_page_feedback transaction.
  • Salience adjustments are computed by salience_after_feedback in decay.rs, clamped between 0.25 and 2.0.
  • Helpful feedback increases salience by SALIENCE_STEP, while Stale or Wrong feedback resets it to the floor value.
  • Salience acts as a multiplier in the retention formula (salience × exp(-λ × age)), directly influencing whether the score remains above the cold_threshold (0.20).
  • Pages falling below the threshold become eligible for eviction during the forget-sweep job.

Frequently Asked Questions

What happens to salience when a page is marked as Stale or Wrong?

When feedback is submitted with FeedbackKind::Stale or FeedbackKind::Wrong, the salience_after_feedback function immediately sets the page's salience to SALIENCE_MIN (0.25) regardless of its previous value. This aggressive penalty ensures outdated or incorrect information is rapidly deprioritized for eviction.

How does salience interact with the time-decay formula?

Salience multiplies the exponential time-decay term in the retention calculation. According to the implementation in crates/ai-memory-store/src/decay.rs, the formula uses salience · exp(-λ · age) as the time component. A higher salience offsets the decay effect, while a lower salience accelerates the score's decline toward the cold_threshold.

What are the maximum and minimum salience values?

The system enforces hard bounds defined in crates/ai-memory-store/src/decay.rs: SALIENCE_MIN is set to 0.25 and SALIENCE_MAX is 2.0. The salience_after_feedback function clamps all computed values to this range, preventing extreme outliers in retention scoring.

Is a user ID required when submitting memory feedback?

No, the author parameter is optional. The record_page_feedback function signature accepts Option<UserId> for the author field, allowing automated agents or anonymous processes to submit feedback without attribution. The feedback record is still appended to the page_feedback table with a null author if none is provided.

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 →