Skip to content

Memory units & lifecycle

MemoryUnit {
id, logicalKey, content, contentType
state, createdAt, ttlSecs, namespace
metadata?, embedding?, embeddingModel?
}
Field Meaning
id unique identifier (UUID)
logicalKey stable dedup / supersession key — the identity rule lives here
contentType MIME type — the extension point (text/plain, text/x-typescript, …)
state lifecycle state (below) — the only filter retrieval cares about
ttlSecs time-to-live for the expiry sweep (null = never expires; code units are TTL-exempt)
namespace logical partition (multi-tenancy, code-vs-message separation)
metadata extensible JSON blob with a typed overlay (topics, sourceType, confidence, affordances, language, codeVersion)
embedding / embeddingModel the vector + which model produced it

get/forget/updateEmbedding accept a UUID or a logical key (id-first, key fallback) — keys are the human-facing handles.

active current working truth — the ONLY state retrieval returns
superseded historically true, no longer the current answer
archived retained for audit/recovery, excluded from retrieval
forgotten physically removed after retention (sweep)

Supersession is the truth mechanism. A confirmed memory_supersedes edge flips the old memory to superseded in the same transaction as the edge insert — the old memory stops ranking entirely, the moment the claim is visible. There is no “demoted ghost” state: confirmed supersede ⇒ gone from search.

Contradiction is not supersession. memory_contradicts surfaces on both endpoints and requires resolution before either side becomes current truth — no conflicting memory is silently stored as current truth.

ttlSecs (or the config defaultTtlSecs) schedules expiry; a sweep pass runs on sweepIntervalMs and moves expired memories active → archived → forgotten over two TTL windows, writing lifecycle events to memory_events (an append-only journal) as it goes.