Memory
Remember what matters.
Remember, recall, improve, and forget on an auditable log. Add a vector backend or reranker when recall should search by meaning.
Built for
Assistants that remember users, agents that learn
How it works
laser.memory(namespace) creates durable agent memory. Every remember, improve, and forget operation writes a log message under a conversation id. Any process with a connection can recall that memory. Its history remains versioned and auditable.
- Default recall ranks by recency. It reads the managed key-value read view - the source of truth, not a search index.
.folded()reads the memory topic in process instead, so recall works against standalone VSR-enabled Apache Iggy with no managed capability. This is what the quick example below uses. All three SDKs carry it.- Semantic recall needs a ranking backend. Rust uses
memory_with(namespace, MemoryBackend::Vector).embedder(..). Python usesMemory.vector(embedder). TypeScript usesMemoryHandle.vector(embedder). Rust and TypeScript can add a reranker. Plain log memory treats.semantic(..)as recent recall.
.limit(n) caps how many hits come back. The token-budget framing in the ELI5 refers to trimming a recall result set to fit a downstream LLM call's budget, the same concern Context applies to conversation assembly.
Recall is four strategies, not one. Each sets the ranking, the sugar call carries the query text:
.recent()- the most recent items, no query text needed..semantic(text)- ranked by embedding similarity. Honored by an embedding backend, the plain log backend falls back to most recent..keyword(text)- exact-term matching, for identifiers and names an embedding blurs..hybrid(text)- fuses the semantic and keyword signals by reciprocal rank. Each fused item keeps its per-signal attribution insignals.
A memory has a kind. remember(..) defaults to Fact. Other kinds are Message, Summary, Entity, Feedback, and Procedure. They distinguish events, distilled content, graph nodes, ranking signals, and reusable workflows. Set the kind with .kind(..).
Dedup is content-addressed. .dedup() on a remember derives the id from the owner, kind, and body instead of minting a random one, so remembering the same fact twice stores it once. This is the same content-addressing the graph uses for node ids.
Named facts skip recall entirely: set_named(key, body), fetch_named(key), update_named(key, patch), and forget_named(key) treat memory as a keyed store for the facts you address directly instead of searching for.
From recall to prompt. Rust's memory.context(conversation, token_budget) recalls relevant items and renders one prompt-ready block. It estimates tokens at roughly 4 bytes each to avoid a tokenizer dependency. When the budget is full, it drops the remaining items and appends an omission marker.
Consolidation limits scope growth. consolidate(scope, max_items) keeps the newest items, prunes the rest, and returns a report. DefaultConsolidator can summarize pruned items into a Summary. prune_summarized() removes items covered by that summary.
Quick example
const memory = laser.memory("customer:42")
const conversation = ConversationId.new()
const id = await memory
.remember(utf8("Prefers aisle seats, travels monthly"))
.conversation(conversation)
.send()
const hits = await memory
.recall()
.conversation(conversation)
.recent()
.limit(5)
.folded()
.fetch()
for (const hit of hits) {
console.log(decodeUtf8(hit.payload))
}
await memory.improve({ conversation }, { target: id, weight: 1 })
await memory.forget({ conversation }, id)let memory = laser.memory("customer:42");
let scope = MemoryScope::builder().conversation(conversation).build();
let fact = memory
.remember("Prefers aisle seats, travels monthly".as_bytes())
.scope(conversation)
.send()
.await?;
let hits = memory
.recall(conversation)
.recent()
.limit(5)
.folded()
.fetch()
.await?;
for hit in &hits {
println!("{}", String::from_utf8_lossy(&hit.payload));
}
memory.improve(&scope, Feedback::new(fact, 1.0)).await?;
memory.forget(&scope, fact).await?;memory = laser.memory("customer:42")
fact_id = await memory.remember(
"Prefers aisle seats, travels monthly",
conversation=conversation,
)
hits = await memory.recall(
limit=5,
conversation=conversation,
strategy="recent",
folded=True,
)
print([hit.text for hit in hits])
await memory.improve(fact_id, 1.0, conversation=conversation)
await memory.forget(fact_id, conversation=conversation)Full runnable example: Rust · Python · TypeScript
The full durable-memory-plus-knowledge-graph deep dive: memory
Key operations
| Verb | What it does |
|---|---|
laser.memory(namespace) | Scope memory to a namespace, log-backed and versioned |
remember(payload) | Store a fact under a conversation scope |
.kind(k) / .dedup() / .agent(id) | Memory kind, content-addressed dedup, per-agent scoping on a remember |
recall(..) + .recent() / .semantic(t) / .keyword(t) / .hybrid(t) | The four recall strategies |
.folded() | Read the memory topic in process, no managed capability needed |
.embedder(..) / .reranker(..) | Attach an embedding function or a reranking pass |
limit(n) | Cap how many hits come back |
improve(id, weight, ..) | Adjust a remembered item's standing with feedback |
forget(id, ..) | Remove a remembered item |
set_named(key, body) / fetch_named(key) | Keyed facts you address directly instead of searching for |
context(conversation, budget) | Recall and render one prompt-ready block (Rust) |
consolidate(scope, max_items) | Prune a scope with the default keep-newest policy |
Client differences: All three SDKs support the four verbs, recency-based managed reads, folded reads, and four recall strategies.
TypeScript includes kind, dedup, hybrid, and consolidate in camelCase.
Python uses Memory.vector(embedder) for similarity ranking. It supports named facts through set, fetch, update, and remove. It does not support kind= or dedup on remember. It also lacks the combined context and consolidate calls.
Running it
Memory records use the agent audit topic. Run bootstrap(partitions) once per stream before the first write. The example uses .folded(), so it runs on every VSR target. Default recall reads the managed KV view from laser-plane.