Memory
Pluggable long-term memory for agents — store, search, and recall knowledge across sessions
Memory
A3S Code uses a two-layer memory architecture. The storage layer (a3s-memory) owns the MemoryStore trait and its default implementations. The agent layer (a3s-code) owns the three-tier session memory (AgentMemory) and context injection (MemoryContextProvider).
a3s-memory a3s-code
────────────────────────────── ──────────────────────────────
MemoryStore (trait) AgentMemory
InMemoryStore ├── working (Vec, max 10)
FileMemoryStore ├── short_term (VecDeque, max 100)
MemoryItem └── long_term (→ MemoryStore)
MemoryType
RelevanceConfig MemoryConfig
MemoryContextProviderThis separation means you can swap the storage backend without touching any agent code.
Quick Start
use a3s_code_core::{Agent, SessionOptions};
let agent = Agent::new("agent.hcl").await?;
// File-backed long-term memory (persists across restarts)
let session = agent.session(".", Some(
SessionOptions::new()
.with_file_memory("./memory")
))?;
let result = session.send("Remember: this project deploys to AWS us-east-1").await?;const agent = await Agent.create('agent.hcl');
const session = agent.session('.', {
fileMemory: './memory',
});
const result = await session.send('Remember: this project deploys to AWS us-east-1');agent = Agent("agent.hcl")
session = agent.session(".", SessionOptions(
file_memory="./memory",
))
result = session.send("Remember: this project deploys to AWS us-east-1")Memory Types
Prop
Type
Failures are stored as Episodic with importance 0.9 — higher than successes so the agent avoids repeating them.
Three-Tier Session Memory
Working memory — active context, auto-trimmed by relevance when over capacity (max 10)
Short-term — current session, FIFO trim when over capacity (max 100)
Long-term — persisted via MemoryStore, survives session restartsremember() writes to both long-term and short-term simultaneously.
let memory = session.memory().unwrap();
// Store a fact
memory.remember(
MemoryItem::new("Project uses PostgreSQL 15")
.with_importance(0.8)
.with_tag("database")
.with_type(MemoryType::Semantic)
).await?;
// Convenience methods
memory.remember_success("Deployed via `just release`").await?;
memory.remember_failure("Direct `cargo publish` fails without fmt check").await?;MemoryItem
Every memory is a MemoryItem. The builder API makes construction ergonomic:
use a3s_memory::{MemoryItem, MemoryType};
let item = MemoryItem::new("Prefer write_all over write for file I/O")
.with_importance(0.8) // 0.0–1.0, clamped
.with_tag("rust")
.with_tag("io")
.with_type(MemoryType::Semantic)
.with_metadata("source", "code-review");Prop
Type
Relevance Scoring
When the agent needs context, memories are ranked by a score that combines importance and recency:
score = importance × importance_weight + exp(−age_days / decay_days) × recency_weightDefault config: importance_weight = 0.7, recency_weight = 0.3, decay_days = 30.
Configure via HCL:
memory {
relevance {
decay_days = 30.0
importance_weight = 0.7
recency_weight = 0.3
}
max_short_term = 100
max_working = 10
}Or in code:
use a3s_memory::RelevanceConfig;
use a3s_code_core::memory::MemoryConfig;
SessionOptions::new()
.with_memory_config(MemoryConfig {
relevance: RelevanceConfig {
decay_days: 7.0, // faster decay for short-lived sessions
importance_weight: 0.9,
recency_weight: 0.1,
},
max_short_term: 100,
max_working: 10,
})Storage Backends
FileMemoryStore
The default persistent backend. One JSON file per item, plus a compact index for fast search:
memory/
index.json ← lightweight index (id, tags, importance, timestamp)
items/
{uuid}.json ← full item content, written atomicallyKey properties:
- Atomic writes via
.tmp→ rename — no corruption on crash - Index loaded into memory on init for fast
search()andsearch_by_tags() - Path traversal prevention on memory IDs
rebuild_index()recovers from index corruption by scanning item files
InMemoryStore
Ephemeral, zero-config. Useful for testing and short-lived sessions:
use a3s_memory::InMemoryStore;
SessionOptions::new()
.with_memory(Arc::new(InMemoryStore::new()))Custom Backend
Implement MemoryStore to use any storage system — SQLite, Redis, a vector DB:
use a3s_memory::{MemoryItem, MemoryStore};
struct MyVectorStore { /* ... */ }
#[async_trait::async_trait]
impl MemoryStore for MyVectorStore {
async fn store(&self, item: MemoryItem) -> anyhow::Result<()> {
// embed item.content and upsert into vector DB
todo!()
}
async fn search(&self, query: &str, limit: usize) -> anyhow::Result<Vec<MemoryItem>> {
// embed query, ANN search, return top-k
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!() }
}
SessionOptions::new().with_memory(Arc::new(MyVectorStore::new()))FileMemoryStore uses substring matching for search(). A vector store replaces this with semantic similarity — no other changes needed.
Context Injection
MemoryContextProvider is registered automatically when memory is active. On each turn:
- Retrieves up to 5 relevant memories by substring match against the current prompt
- Injects them into the system prompt as structured context blocks
- After turn completion, stores the interaction as a
Proceduralmemory
System Prompt
├── Base instructions
├── [memory] User prefers TypeScript ← MemoryContextProvider
├── [memory] Deploy via `just release` ← MemoryContextProvider
├── [resource] Related code snippets ← FileSystemContextProvider
└── Tool definitionsEvents
Prop
Type
API Reference
SessionOptions
Prop
Type
MemoryStore trait
Prop
Type
a3s-memory is a standalone crate. Add it directly if you need the storage layer without the full agent framework: cargo add a3s-memory