Skip to content

Architecture

A memory system, not a vector store with a nice wrapper.

This page is written for the engineer deciding whether to integrate Smara. It covers what each pillar stores, how retrieval combines vectors with graph traversal, what the consolidation worker actually does, and the guarantees around provenance, time and deletion.

Shape of the system

Two planes, four stores.

The data plane is what your agents call: assemble context, search memory, traverse the graph, append episodes. It authenticates with a per-tenant API key. The control plane is what humans call: tenants, members, keys. It authenticates with a Firebase ID token. They share a tenant boundary and nothing else.

Underneath, each pillar is stored in the engine that fits its access pattern rather than in one general-purpose database asked to be good at everything.

Spanner

Semantic + graph + episodic

Facts, entities, typed edges and the append-only episodic ledger live in one database, with a vector index and a property graph over the same rows — so similarity search, traversal, and the provenance walk from any fact back to its source events never disagree about what exists.

Firestore

Skill registry

Doc-shaped metadata for procedural skills: version pointers and approval state. Small, cheap, and separate from the artifact bytes it points at.

Memorystore (Valkey)

Working memory

Per-session scratchpad and assembled context cache. Deliberately volatile: nothing here is authoritative, and losing it costs a re-assembly, not a memory.

Cloud Storage

Procedural artifacts

Versioned skill and playbook bodies, content-addressed. The pointer and its approval state live in the control plane; the bytes live here, immutable per version.

Runs on Google Cloud: Cloud Run for the API and the consolidation worker pool, Pub/Sub between them, Vertex AI for embeddings and extraction.

The four pillars

Separated by lifetime and by write path.

Ephemeral · per request

Working memory

  • POST /v1/context
  • POST /v1/context/scratchpad

Working memory is the assembly step, not a store. For each request Smara composes a context window from the system prompt, the agent's scratchpad, the recent turns of the session, and the long-term memory retrieved for this query — then trims to the token budget you specify.

Everything in it is a copy. If a fact only exists in working memory it is not remembered; it will be gone on the next call unless it was written to episodic memory or promoted to semantic memory. Keeping that boundary strict is what stops an agent's context window from quietly becoming an undocumented database.

Versioned · human-approved

Procedural memory

  • GET /v1/skills
  • POST /v1/skills/{id}/versions
  • POST /v1/skills/{id}/versions/{v}/approve

Procedural memory holds behaviour — the reusable skills, standard operating procedures, playbooks and conditional policies an agent follows. It is the part of memory most likely to cause damage if it changes silently, so it is the part with the strictest write path.

Edits produce a new immutable version rather than mutating the live one. Promotion from draft to active requires an explicit human approval, and every activation records who approved it and when. Rolling back is selecting an older version, not restoring a backup.

Durable · typed · queryable

Semantic memory + knowledge graph

  • POST /v1/memory/search
  • GET /v1/graph/entities/{id}
  • POST /v1/graph/traverse

Facts are stored with embeddings for similarity search and as nodes and typed edges in a property graph. Neither alone is enough: vector search finds text that looks relevant, graph traversal finds the things that are actually connected to it. Smara runs both and merges the results.

Every fact and every edge carries temporal validity (valid_from / valid_to), a confidence score, and provenance back to the sessions it was derived from. A fact is never edited in place — a newer fact supersedes an older one, and the old one keeps its validity window so you can still answer questions about the past.

Append-only · ledger

Episodic memory

  • POST /v1/episodes
  • GET /v1/sessions/{id}/episodes

Episodic memory is an append-only ledger of events — turns, tool calls and their results, outcomes, errors. Writes are cheap and unconditional; the agent does not have to decide at runtime whether something is worth remembering, because deciding is consolidation's job.

Because nothing is rewritten, the ledger doubles as the audit trail: when a semantic fact looks wrong, its provenance points back at the exact episodes it came from. Retention is policy-driven — episodes can be pruned on a schedule after the facts derived from them have been consolidated.

Hybrid retrieval

Vectors find candidates. The graph finds consequences.

Similarity search is good at “find text that looks like this question” and bad at “and what does that imply?” A query about a renewal date will happily match a paragraph containing the word renewal while missing the contract that actually governs it.

Smara runs both passes over the same records. Vector search returns the top candidates by cosine distance over 768-dimension embeddings; the graph then expands one to three hops from those candidates along typed edges, pulling in the entities and facts they are connected to. Results are merged, de-duplicated, filtered by scope and confidence, and packed into the token budget the caller asked for.

Because both passes read the same rows, there is no sync job between an index and a graph and no window where they disagree.

hybrid search
POST /v1/memory/search
{
  "scope":       { "tenant_id": "…", "user_id": "user:8871" },
  "query":       "when does this account renew?",
  "vector":      { "top_k": 20, "distance": "COSINE" },
  "graph":       { "min_hops": 1, "max_hops": 3 },
  "as_of":       "2026-07-27T00:00:00Z",
  "min_confidence": 0.6
}

Defaults: top_k 20 · cosine · 1–3 hops · embeddings from gemini-embedding-001, truncated to 768 dimensions.

Consolidation pipeline

The part that runs while nobody is waiting.

New episodes publish to Pub/Sub as they land. A worker pool picks them up on its own schedule, batches by session and scope, and runs extraction over the batch — pulling out candidate facts, candidate entities and candidate typed relationships, each with a confidence score and a provenance record naming the sessions and the model that produced it.

Reconciliation is where the work actually is. A candidate that matches an existing fact reinforces it. A candidate that refines one supersedes it, closing the incumbent’s validity window instead of deleting the row. A candidate that flatly contradicts a high-confidence incumbent does not win by being newer — it opens a conflict for review. New entities and edges are merged into the graph under the same rules.

None of this is on the request path. Consolidation getting slower because you have a lot of history does not make your agent slower; it makes consolidation lag, which is the correct thing to trade.

The knowledge graph

Not a byproduct of extraction. The product.

Most memory systems stop at “we also build a graph.” Smara treats the graph as a first-class retrieval surface, which means it has to stay clean, connected, and inspectable as it grows.

Entity resolution

Exact-name and vector matching that ignores type-spelling drift, so "Claude Code" is one node, not four. Retroactive merges are supersessions — the graph consolidates without losing its history.

Entity pages

"Everything about X" as one call: the entity, its facts, its relationships, its timeline. The portal renders it as a page; agents get it as JSON.

Entity-fused retrieval

Retrieval follows the entities a query links to and pulls their facts alongside vector hits, so an answer about a person includes what is known about them, not just text that resembles the question.

Community summaries

Related entities cluster into communities, each distilled into a summary fact that gives broad questions a place to land. Refreshed nightly, superseded as the graph moves.

A canvas you can walk

The portal renders the whole graph in WebGL — search, community colors, recency dimming — because a memory you cannot inspect is a memory you cannot trust.

Dreaming

Every night, the memory sleeps on it.

Human memory does its hardest work offline. So does Smara: a nightly dream cycle runs only for tenants with enough new experience to be worth consolidating, and does the maintenance no one should do on a request path.

The difference from every other “dreaming” feature shipping this year: Smara’s dreams are auditable. A dream never deletes — every merge and resolution is a supersession with the dream as its actor, reviewable in the fact’s belief history the morning after.

  1. 01

    Sweep

    Same-entity, high-similarity fact pairs are adjudicated by a model: keep both, merge, or supersede. Contradictions resolve while nobody is waiting on a request.

  2. 02

    Re-form

    Communities are re-detected and their summaries rewritten against the graph as it now stands, so the big picture keeps up with the details.

  3. 03

    Report

    The cycle writes a wake report into the ledger. The portal greets you with "While you slept…" — and your assistants can cite the dream itself.

Guarantees

What you can promise your own compliance team.

Temporal validity

Every fact and edge carries valid_from and an optional valid_to. Superseding a fact closes the old window rather than deleting the row, so “what did we believe in March?” stays answerable. Pass as_of on a query to read the graph as it stood at any point in time.

Provenance and audit

Consolidated records point back at the exact source sessions, the extraction model that produced them, and the timestamp. When a fact looks wrong you can walk from the answer to the transcript that caused it, without guessing.

Confidence, not certainty

Extraction produces a score, and retrieval takes a floor. Low-confidence candidates can be surfaced for review instead of being silently promoted into the graph — and a genuine contradiction opens a conflict rather than overwriting the incumbent.

Controlled forgetting

Retention is a policy, not an accident. Episodes can be pruned on a schedule once the facts derived from them are consolidated; facts can be expired, superseded, or deleted outright for a subject-erasure request — and the deletion propagates through the graph edges that referenced them.

Human-in-the-loop for behaviour

Facts can be written automatically because a wrong fact is a retrieval problem. Procedures cannot, because a wrong procedure is an incident. Skill versions require explicit approval before they go live, and every activation is attributed.

Isolation you cannot misconfigure

Scope — tenant, user, agent — is a required field on every long-term record, not a filter applied at query time. Keys resolve to exactly one tenant, and there is no endpoint that reads across tenants.

Benchmarks

Measured on the live service, not a lab rig.

On LoCoMo — the standard benchmark for very-long-term conversational memory (10 multi-session conversations, 1,540 scored questions) — Smara answers 74.7% correctly by LLM-judge, run against production api.smara.dev through the same API every agent uses.

Overall

74.7%

1,150 / 1,540

Single-hop

85.1%

841 questions

Temporal

70.7%

321 questions

Multi-hop

58.2%

282 questions

Open-domain

44.8%

96 questions

Run 2026-09-04. Answer model gemini-2.5-flash, distinct judge gemini-2.5-pro, adversarial category excluded per convention. Numbers published elsewhere (Mem0 ~66–68%, Zep low-70s, others self-reported higher) use different answer/judge models and are not directly comparable. Full methodology, per-question records and the reproducible harness live in the repository's benchmarks/locomo/. We re-run and update this table as the product evolves — this is the re-measured number after we fixed a retrieval bug our own first run exposed — we publish the latest run even when it lands lower. Multi-hop aggregation is the stated current improvement target.

The reference is the contract.

Read the full endpoint list, then issue a key and try it against your own tenant.