A3S Docs
A3S CodeExamples

Memory

Practical examples for file memory, custom backends, and memory events

Memory Examples

File-Backed Memory

Memories persist across session restarts. Point multiple sessions at the same directory to share long-term knowledge.

use a3s_code_core::{Agent, SessionOptions};

let agent = Agent::new("agent.hcl").await?;

let session = agent.session(".", Some(
    SessionOptions::new()
        .with_file_memory("./memory")
))?;

// First session — agent stores a fact
session.send("Remember: we deploy to AWS us-east-1 via GitHub Actions").await?;

// Later session (same memory dir) — agent recalls it automatically
let session2 = agent.session(".", Some(
    SessionOptions::new()
        .with_file_memory("./memory")
))?;
let result = session2.send("Where do we deploy?").await?;
// Agent answers from memory without being told again
const agent = await Agent.create('agent.hcl');

// First session
const s1 = agent.session('.', { fileMemory: './memory' });
await s1.send('Remember: we deploy to AWS us-east-1 via GitHub Actions');

// Later session — same memory dir
const s2 = agent.session('.', { fileMemory: './memory' });
const result = await s2.send('Where do we deploy?');
agent = Agent("agent.hcl")

s1 = agent.session(".", SessionOptions(file_memory="./memory"))
s1.send("Remember: we deploy to AWS us-east-1 via GitHub Actions")

s2 = agent.session(".", SessionOptions(file_memory="./memory"))
result = s2.send("Where do we deploy?")

Storing Memories Directly

Use session.memory() to store and query memories from your own code:

use a3s_memory::{MemoryItem, MemoryType};

let memory = session.memory().unwrap();

// Store with full control
memory.remember(
    MemoryItem::new("Auth uses JWT with 24h expiry")
        .with_importance(0.9)
        .with_tag("auth")
        .with_tag("security")
        .with_type(MemoryType::Semantic)
).await?;

// Convenience wrappers (set importance and tags automatically)
memory.remember_success("Refactored auth module — tests pass").await?;
memory.remember_failure("Deploying without running fmt check breaks CI").await?;

// Query
let results = memory.recall("auth", 5).await?;
for item in results {
    println!("[{:.2}] {}", item.importance, item.content);
}

Custom Backend

Implement MemoryStore from a3s-memory to use any storage system:

use a3s_memory::{MemoryItem, MemoryStore};
use async_trait::async_trait;
use std::sync::Arc;

struct SqliteMemoryStore {
    pool: sqlx::SqlitePool,
}

#[async_trait]
impl MemoryStore for SqliteMemoryStore {
    async fn store(&self, item: MemoryItem) -> anyhow::Result<()> {
        sqlx::query!(
            "INSERT OR REPLACE INTO memories (id, content, importance, tags, timestamp)
             VALUES (?, ?, ?, ?, ?)",
            item.id, item.content, item.importance,
            serde_json::to_string(&item.tags)?,
            item.timestamp.to_rfc3339(),
        )
        .execute(&self.pool).await?;
        Ok(())
    }

    async fn search(&self, query: &str, limit: usize) -> anyhow::Result<Vec<MemoryItem>> {
        // Full-text search or semantic similarity here
        todo!()
    }

    async fn retrieve(&self, id: &str) -> anyhow::Result<Option<MemoryItem>> { todo!() }
    async fn search_by_tags(&self, tags: &[String], limit: usize) -> anyhow::Result<Vec<MemoryItem>> { todo!() }
    async fn get_recent(&self, limit: usize) -> anyhow::Result<Vec<MemoryItem>> { todo!() }
    async fn get_important(&self, threshold: f32, limit: usize) -> anyhow::Result<Vec<MemoryItem>> { todo!() }
    async fn delete(&self, id: &str) -> anyhow::Result<()> { todo!() }
    async fn clear(&self) -> anyhow::Result<()> { todo!() }
    async fn count(&self) -> anyhow::Result<usize> { todo!() }
}

let store = Arc::new(SqliteMemoryStore { pool });
let session = agent.session(".", Some(
    SessionOptions::new().with_memory(store)
))?;

Memory Events

Subscribe to memory lifecycle events via the streaming API:

let (mut rx, _handle) = session.stream("What do you know about this project?", None).await?;

while let Some(event) = rx.recv().await {
    match event {
        AgentEvent::MemoryStored { memory_id, memory_type } => {
            println!("stored {} ({:?})", memory_id, memory_type);
        }
        AgentEvent::MemoryRecalled { memory_id, .. } => {
            println!("recalled {}", memory_id);
        }
        AgentEvent::MemoriesSearched { query, count } => {
            println!("searched '{}' → {} results", query, count);
        }
        _ => {}
    }
}

Relevance Tuning

Adjust scoring for your use case:

use a3s_memory::RelevanceConfig;
use a3s_code_core::memory::MemoryConfig;

// Long-lived assistant: slow decay, weight importance heavily
let config = MemoryConfig {
    relevance: RelevanceConfig {
        decay_days: 365.0,
        importance_weight: 0.9,
        recency_weight: 0.1,
    },
    max_short_term: 200,
    max_working: 20,
};

// Short-lived coding session: fast decay, weight recency heavily
let config = MemoryConfig {
    relevance: RelevanceConfig {
        decay_days: 1.0,
        importance_weight: 0.3,
        recency_weight: 0.7,
    },
    max_short_term: 50,
    max_working: 5,
};

SessionOptions::new().with_memory_config(config)

Index Rebuild

If FileMemoryStore's index is corrupted or deleted, recover without data loss:

use a3s_memory::FileMemoryStore;

let store = FileMemoryStore::new("./memory").await?;

// Scans items/ directory and rebuilds index.json from item files
let recovered = store.rebuild_index().await?;
println!("Recovered {} memories", recovered);

For the full API reference, see Memory.

On this page