Skip to content

Emma memory

Emma's memory is tiered: fast and disposable at the top, durable and governed at the bottom. The durable tier is backed by the Postgres store on inva-local-01; see Data layer & RAG for the schema and isolation model.

Memory tiers

Tier Backing Lifetime Content
Transient context In-request working set Single turn / request Prompt-window state; never persisted
Session-ephemeral redis-cache (allkeys-lru, 2 GB) Session / LRU-evicted Conversation state, scratch, cache; disposable
Durable memory Postgres memory_items Persistent, governed Classified facts with full provenance

Nothing crosses from an upper tier into durable memory implicitly — promotion is an explicit, governed step.

Promotion to durable memory

A candidate is only written to memory_items when it carries all of:

  • classification — data sensitivity label;
  • scope — org / personal_private (drives isolation);
  • source_ref — provenance pointer to the originating source;
  • confidence — how strongly the item is asserted;
  • approval — an explicit promotion gate.

This keeps durable memory auditable and prevents unlabelled or unsourced facts from becoming "truth."

Storage & isolation

Durable memory shares the RAG store's schema and guarantees:

  • memory_items — dual-indexed like the corpus: ts tsvector (GIN, FTS) and embedding vector(768) (HNSW cosine), so memory is retrievable by keyword and by similarity.
  • knowledge_chunks — the durable RAG corpus, retrieved by the same hybrid pipeline.
  • Row-level security (enabled + forced): org isolation plus personal_private owner-only. The app connects as the non-owner emma_app role and sets app.user_id/org_id/role GUCs per transaction; it cannot bypass RLS.

Every read/write flows through the RLS-enforced RAG pipeline, and material actions land in the append-only audit_events table alongside the transactional outbox.