Agent Memory
Agents that rely on context windows for memory forget everything when the window closes. Agents that write to a plain vector store have no governance: no audit trail, no access control, no way to know who stored what or why, and no way to correct a wrong belief without losing its history.
Relata is the governed memory layer: cognitive verbs that store, retrieve, and manage beliefs as bi-temporal, provenance-tracked rows — the same storage model as everything else in the database. Every memory item carries who wrote it, when it was believed to be true, what purpose was declared, and a confidence score. Old beliefs are not deleted — they are superseded, so the full belief history is always queryable.
What lives where. This page is the concept — why governed memory, what the model is, and how recall ranks results. For every verb, argument, response shape, and curl/JSON example, see the Agent memory reference; for the tool schemas, the MCP tools reference.
The verb model (conceptual)
The surface is a small set of cognitive verbs rather than free-form CRUD. Conceptually they fall into three groups:
- Store & correct —
remembera belief,consolidate(supersede) a belief that changed,forgetunder a retention policy (never a hard delete — obeys legal holds). - Retrieve & inspect —
recallby hybrid BM25 + vector search (optionallyAS OFa past moment),recognizewhether an identity is known,justifythe full provenance chain behind a belief. - Relate & summarise —
associatetwo items,resolveconflicting beliefs by policy,summarisea session/topic, andepisodes_into walk a session's narrative.
Five canonical types back them: MemoryItem (one belief), AgentSession, ToolCall, DecisionRecord, and Episode — all ordinary bi-temporal rows. For the full verb/argument/type reference, see Agent memory reference.
Why governed memory (vs. convenience-memory)
Most agent-memory products (Mem0, RushDB, Zep) optimize for convenience: push JSON, get semantic recall, schema-free. Relata optimizes for accountability — the memory must answer "what did the agent know, when, and why — and who was allowed to see it?"
| Concern | Relata answer |
|---|---|
| Bi-temporal recall | Every memory carries valid_from/to (when it was true) and system_from/to (when Relata learned it). Query "what did the agent believe at T?" exactly. |
| Tamper-evident audit | Hash-chained commit manifests — any deletion or mutation leaves a forensic trail. |
| Provenance chain | Every MemoryItem links back to the ToolCall and AgentSession that produced it; justify replays exactly how a decision was reached. |
| Governed access | Cedar-inspired ABAC + PURPOSE restrict which agents can read which memories; multi-tenant isolation is enforced at the query-planner level. |
| Finite context window | recall injects only a bounded, ranked slice per turn (LIMIT N BUDGET T) — unbounded memory, bounded prompts. |
| Hallucination / memory poisoning | PROV-O per row + hash chain; no source = not a memory. Every result is justify-able. |
How recall ranking works
recall runs three steps:
- Hybrid retrieval — BM25 over text fields, vector similarity over the stored embedding, fused via reciprocal-rank fusion (RRF). Results that score in both signals rank higher than results that score in only one.
- Temporal filter — if
as_ofis supplied, only beliefs that werevalidat that point in time are considered. This lets an agent reconstruct what it "knew" at a given past moment. - Re-scoring — the fused relevance is blended additively with recency and the forgetting curve (
0.70·relevance + 0.15·recency + 0.15·forget), then multiplicatively gated byconfidence × class_weight. The additive blend prevents a single near-zero lifecycle factor from collapsing the whole score — a high-confidence belief from yesterday outranks a low-confidence belief from a minute ago, but an old but highly-relevant memory is no longer dropped just because its recency is near zero.
Unlimited memory, bounded prompts
Relata gives an agent unbounded memory with bounded prompts by separating what the agent knows (unlimited) from what it sees per turn (bounded):
- Capacity is unbounded — durable storage is object-store (S3 / self-hosted S3-compatible), not RAM-bound like a vector DB. You run out of bucket, not memory.
- The agent never loads it all — each turn,
recallreturns only the small, relevant, ranked slice, capped byLIMIT N BUDGET T. A 10-year, billion-row memory and a 1 MB memory cost the same prompt budget. - Cold vs hot — cold history lives on object storage; active-case data is promoted into RAM/SSD via the tiered cache.
Fast on constrained hardware (no GPU)
- No LLM on the hot path. Ingest canonicalizes + validates declared identities (deterministic, cheap). Since v1.1 embeddings are caller-supplied — see LLM & Embedding configuration — so the ingest hot path is pure throughput.
- Early-pruned retrieval. IdentityIndex bloom filters + graph pushdown + a BM25 shortlist mean the vector path scans a tiny candidate set.
- Single binary, embedded
freeprofile — one process alongside the agent's own loop; no separate vector server, Redis, and graph DB to operate.
Agent-framework adapters
Drop-in governed memory backends for every major Python agent framework. Each wraps the memory verbs, so purpose tracking and ACL stay on. None imports its framework at module load, so they are safe to install without the framework present.
| Framework | Import path | Interface shape |
|---|---|---|
| LangChain | relata_adapters.langchain.RelataMemory | BaseMemory |
| LlamaIndex | relata_adapters.llamaindex.RelataMemory | BaseMemory |
| CrewAI | relata_adapters.crewai.RelataStorage | Storage |
| AutoGen v0.2 | relata_adapters.autogen.RelataMemory | Memory (async) |
| AG2 (v0.4+) | relata_adapters.ag2.RelataAG2Memory | MemoryProtocol |
| Pydantic-AI | relata_adapters.pydantic_ai.RelataMemoryBackend | memory backend |
| smolagents | relata_adapters.smolagents.RelataTool | tool callable |
| LangGraph | relata_langgraph.RelataCheckpointer | checkpointer |
| Auto-detect | relata_adapters.registry.get_memory_adapter() | picks installed framework |
from relata_adapters.langchain import RelataMemory
mem = RelataMemory(
base_url="http://localhost:9090",
bearer_token=token,
purpose="customer-support-agent",
)
# chain = ConversationChain(llm=llm, memory=mem)Querying memory as SQL
Because memory items are ordinary rows, you can query them with SQL — including bi-temporal operators:
-- All beliefs about "Alice" stored in the last 30 days, newest first
SELECT content, confidence, valid_from
FROM MemoryItem
WITH PROVENANCE
WHERE MATCH(content, 'Alice')
AND system_from >= now() - INTERVAL '30 days'
ORDER BY confidence DESC, system_from DESC
LIMIT 20
-- What did the agent believe about Alice on 1 June?
SELECT content, confidence
FROM MemoryItem
AS OF '2026-06-01T00:00:00Z'
WHERE MATCH(content, 'Alice')
ORDER BY confidence DESCSee also
- Agent memory reference — every verb, argument, response shape, and curl/JSON example
- MCP Tools Reference — full tool schemas for all memory verbs
- Hybrid Search —
recallruns on the same BM25 + vector pipeline - Provenance —
justifyreturns the full lineage chain for any memory item - Governance — ACL and PURPOSE apply to every cognitive verb
- Python SDK —
Memory,A2AClient, framework adapters