Memory Fabric Spec
Status: Canonical · Date: October 2026 Implements: Core Principles Principle 5 (Shared context with scoped access) and Principle 7 (Explainability and audit by design) Authority for: Memory tiers, the memory record envelope, the memory lifecycle, the recall and promotion contracts, retention classes, decay and erasure, and the memory governance invariants Decided by: ADR-OS-002 — Memory Fabric Control Plane
Overview
Synedrix OS has always had a memory substrate. This document gives it a memory architecture.
Layer 7 owns the seven-store memory fabric — working memory (Redis), canonical memory (Supabase PG17), temporal memory (QuestDB), graph memory (Neo4j), semantic memory (Qdrant), LLM trace memory (Langfuse) and behavioural memory (PostHog). Those seven names answer one question: where does a byte live. This specification adds the two questions the OS has to govern but has never defined:
- What kind of memory is this? — the tier axis (§3)
- How does it come to exist, move, age and end? — the lifecycle axis (§5)
Open item. The canon does not agree on how many platforms Layer 7 owns. This document’s Overview, above, says “Layer 7 owns the seven-store memory fabric,” naming Redis, Supabase PG17, QuestDB, Neo4j, Qdrant, Langfuse and PostHog as the seven stores, and §2’s reconciliation table treats the Vocabulary “memory fabric” glossary entry — which lists the identical seven stores — as “authoritative for store names.” Against that,
canonical/architecture.yaml’splatform_mapping— the machine-readable facts layer, the generator source of truth, and the same tie-breaker the Grafana LGTM Stack platform page already uses to settle a naming dispute — assigns only Redis, Supabase PG17, QuestDB, Neo4j and Qdrant tolayers: [7], and assigns Langfuse ("LLM tracing and prompt engineering") and PostHog ("Behavioural analytics") tolayers: [10]. Tech Stack’s Layered Truth Summary agrees with the facts layer: it lists five Layer 7 substrate rows (Supabase PG17, Neo4j, QuestDB, Qdrant, Redis) and a separate “LLM eval / observability” row for Langfuse whose “Memory tiers it backs” column reads “none — traces are not a system of record.” Layer Taxonomy Table’s Platform mapping table places the same five platforms at “7 (Memory)” and Langfuse and PostHog at “10 (Observability).” These are not two names for one fact. “Seven-store memory fabric” is a broader, defensible framing under which LLM traces and behavioural events are themselves a kind of memory — this document’s own §3.5 makes exactly that argument, that Langfuse and PostHog “remain in the seven-store fabric” as readable memory that is not a memory tier — while “Layer 7 owns” is the narrower, platform-mapping claim that a reader citing this Overview as a Layer 7 platform count would get wrong per the facts layer. This document keeps “seven-store memory fabric” here because that is its own established terminology, carried forward from ADR-OS-002 §1 and the Vocabulary entry this document elsewhere treats as authoritative for store names, and changing it would mean silently picking a winner between two legitimate but incompatible framings — what counts as memory, against what a layer’s platform-mapping row contains — without an explicit decision to do so. Reconciling the other documents requires an explicit decision and edits to those documents. It is not resolved here.
Together with the substrate axis, these three define the memory control plane: the part of Layer 7 that owns memory as a governed process rather than as a set of databases.
Three rules give the control plane its shape. Each generalises something the canon already asserted for exactly one case:
- No memory crosses a tier boundary without a governed promotion event (§7).
- Recall is a tool call, not ambient context (§6).
- Forgetting is an approved action that leaves a tombstone (§8).
Scope
| In scope | Out of scope |
|---|---|
| Tier taxonomy and tier→substrate mapping | Which physical database is deployed where — Deployment Model Spec |
| The memory record envelope and its lineage fields | The event envelope — Event Taxonomy Standard |
| The lifecycle state machine and legal transitions | Context assembly for a specific agent run — Layer 4, LangGraph Runtime Implementation Guide |
| Recall, promotion and erasure contracts | Concrete retention values and thresholds — Layer 12, business instance |
| Retention classes and tombstone semantics | Domain-specific memory content — Layer 11, domain packs |
| The memory governance invariants | The runtime binding — Memory Runtime Integration Guide |
What Layer 7 owns, before and after
| Before | After | |
|---|---|---|
| Owns | Transactional DBs, vector stores, graph stores, caches, audit state | The above, plus the memory lifecycle: formation, consolidation, reflection, promotion, recall mediation, decay and erasure |
| Must not own | Workflow sequencing, UI logic | The above, plus retention policy (Layer 12 sets the values) and context assembly (Layer 4 decides what a given run needs to know) |
The layer count is unchanged. Memory cognition is a control plane over persistence, in the same relationship Governance (Layer 9) has to execution — not a peer layer beside it. See ADR-OS-002 §5.1.
1. Terminology
This document uses the canonical forms fixed in Vocabulary and adds to them. The umbrella term remains memory fabric. The forbidden forms remain forbidden: never write memory layer, data layer, storage layer or database layer.
| Term | Meaning |
|---|---|
| memory fabric | The whole of Layer 7: the seven stores and the control plane over them. |
| memory control plane | The part of the fabric that owns the lifecycle — formation, consolidation, reflection, promotion, recall mediation, decay, erasure. |
| memory tier | What kind of memory a record is (§3). Orthogonal to the store it lives in. |
| memory record | A single governed unit of memory, carrying the envelope in §4. |
| memory substrate | The store a tier is physically written to or projected into. |
| write-authoritative | The one store that is right when two stores disagree. Every other copy is a projection. |
| promotion | A governed transition of a record from one tier to a longer-lived tier. |
| consolidation | Merging or summarising several records into one derived record of the same or higher tier. |
| reflection | Deriving a higher-order assertion (a profile trait, a distilled skill) from consolidated records. |
| decay | Scheduled reduction of a record’s availability — expiry of validity_interval, or demotion. |
| tombstone | The durable marker left behind when a record’s content is erased. |
2. Reconciliation of the existing taxonomies
Four memory tables exist across the canon. They are not contradictory so much as partial — all four describe the substrate axis, and none describes tier or lifecycle. This document is authoritative for the tier model; each prior table remains valid as a projection of it.
| Source | What it enumerates | Status after this document |
|---|---|---|
| Tech Stack § Layered Truth Summary — 6 truth classes | Substrate, by kind of truth | Retained. A substrate view; each truth class maps to one or more tiers in §3.2. |
| Vocabulary § memory fabric — 7 stores | Substrate, by store | Retained and authoritative for store names. Tier names are additive, not replacements. |
| Taxonomy Spec §8 — 5 memory types | Substrate + partial scope | Superseded by §3 of this document. That table is replaced by the tier table when Taxonomy Spec is bumped. |
| Academy 02.8 — 5 kinds | Cognitive, non-normative | Reconciled. The five kinds map onto tiers in §3.3; the chapter becomes teaching material for this specification. |
Rule: where any other document’s memory table disagrees with §3 of this document, §3 wins. Where a document names a store, the Vocabulary’s canonical store names win.
3. Tier taxonomy
3.1 The eight tiers
| Tier | Question it answers | Owner | Scope | Lifetime |
|---|---|---|---|---|
working | What is true right now, inside this run? | OS | run / session | TTL-bound, never a source of truth |
episodic | What happened, and when? | OS | cross-session | Durable, decays by policy |
semantic | What is true, independent of when it was learned? | OS | cross-session | Durable |
procedural | How is this task done well? | OS | cross-session | Durable, versioned |
profile | Who is this actor and what do they prefer? | OS | subject-scoped | Durable, supersession-based |
relational | What is the canonical business state? | OS / domain | persistent | Durable, transactional |
graph | What is connected to what, and what caused what? | OS | cross-session | Durable, append-oriented |
temporal | How has a measured quantity moved over time? | OS | persistent | Durable, retention-windowed |
Tier definitions in full:
working— hot state for an in-flight run: task graph position, iteration counters, dedup windows, idempotency keys, in-session conversation buffer. Explicitly not a source of truth. A run that cannot be reconstructed from durable tiers after working memory is lost is non-compliant.episodic— a record of something that occurred: an interaction, a decision, a tool call outcome, an approval. Episodic records are the raw material every other durable tier is derived from, and they carry the strongest lineage obligation.semantic— a durable assertion abstracted away from the episode that produced it (“this customer’s billing entity is X”). Alwaysderived_fromat least one episodic record.procedural— a reusable method: a distilled skill, a task recipe, a validated tool sequence. Versioned rather than overwritten, so a run can be replayed against the procedure that was current at the time.profile— durable assertions about a subject (a user, an operator, a counterparty, an agent). Governed by supersession, never in-place mutation, so the profile at any past instant remains reconstructible.relational— canonical business entities and their transactional state. The only tier a domain pack co-owns, and the tier with the strongest consistency requirements.graph— relationships, entity links, and causal lineage: which agent influenced which outcome, which reasoning step touched which entity. This is the tier that Academy 02.8 identifies as having no framework home; §3.4 gives it one.temporal— time-series measurements and their aggregations, consumed by the intelligence agents.
3.2 Tier → substrate mapping
Tier and substrate are orthogonal. One tier may be written to one store and projected into others; one store may serve several tiers. Neither may be inferred from the other.
| Tier | Write-authoritative store | Projections / indexes | Notes |
|---|---|---|---|
working | Redis (working memory) | LangGraph checkpointer | TTL-bound. The checkpointer is a projection of run state, not of business truth. |
episodic | Supabase PG17 (canonical memory) | Qdrant (semantic memory) | Content in Postgres, embedding + payload in Qdrant. |
semantic | Supabase PG17 | Qdrant | Same split. Qdrant is the retrieval index, never the record of truth. |
procedural | Supabase PG17 | Qdrant | Versioned rows; the index points at the current version. |
profile | Supabase PG17 | Qdrant, Neo4j (subject node) | Supersession chain lives in Postgres. |
relational | Supabase PG17 | Neo4j (entity projection) | The existing canonical-memory role, unchanged. |
graph | Supabase PG17 (lineage links) · Neo4j (entities and edges, via NAMS) | Neo4j | Lineage remains Postgres-write-authoritative and synced to Neo4j, per the existing rule. Entity/relationship memory is NAMS-owned in Neo4j. |
temporal | QuestDB (temporal memory) | — | Unchanged. |
Two invariants follow directly and are restated in §10:
- Supabase PG17 is write-authoritative for every audit-bearing tier. Qdrant, Neo4j and the LangGraph store are projections. Wiping any projection and rebuilding it from Supabase must produce identical behaviour.
- Qdrant is the single semantic vector substrate. No second vector store enters Layer 7. NAMS’s own vector index is scoped to entity resolution inside the graph tier and is not a general retrieval path.
3.3 Mapping from the prior taxonomies
| Academy 02.8 kind | Tech Stack truth class | Taxonomy Spec type | Tier(s) here |
|---|---|---|---|
| Hot | Ephemeral / hot state | operational | working |
| Transactional | Canonical relational | relational | relational |
| Semantic | Semantic / similarity | semantic | episodic, semantic, procedural, profile |
| Graph | Graph / lineage | graph | graph |
| Audit | Canonical relational | — | episodic (retention class audit, §8.1) |
| — | Temporal | — | temporal |
| — | LLM eval / observability | — | not a tier — see §3.5 |
| — | — | conversation | working (session-scoped, TTL-bound) |
3.4 Where graph and audit memory finally live
Academy 02.8 observes that two of the five memory kinds it teaches have no framework primitive: neither LangChain nor LangGraph offers a home for graph memory or audit memory. This specification supplies both.
- Graph memory is the
graphtier, implemented on Neo4j through the NAMS client (see Memory Runtime Integration Guide §5). Its reasoning-to-entity edges give the OS a concrete representation of which agent step touched which entity — the missing link between an Outcome Envelope and the business state it moved. - Audit memory is not a separate tier. It is the
episodictier under retention classaudit(§8.1), which makes it append-only, exempt from decay, and erasure-resistant except through the tombstone path in §8.4. Modelling audit as a retention class rather than a tier is deliberate: an audit record is an episode, and duplicating it into its own tier would create two records of the same fact with different retention.
3.5 What is not a tier
Observability stores are not memory tiers. Langfuse (LLM trace memory) and PostHog (behavioural memory) remain in the seven-store fabric and remain readable, but no memory record is write-authoritative in either. Traces are not a system of record: they are sampled, they expire on an observability schedule, and they are not transactionally consistent with business state. An agent that needs a durable fact must recall it from a tier, never reconstruct it from a trace.
3.6 Domain-owned operational stores
A domain pack may keep a Qdrant collection or a Neo4j graph that is not memory. It is a domain-owned operational store: a derived, query-optimised index over data the domain pack already holds in its own write-authoritative schema, built so that a workflow can run a similarity match or a graph traversal at the latency the domain needs. It sits outside the eight tiers, and writes to it by a domain workflow are not memory commits, so invariant 4 does not apply to them.
A store qualifies only if all four conditions hold:
- Not recalled as agent memory. It is read by a workflow step as a bound domain tool, such as
qdrant-queryorneo4j-query. It is never exposed through the recall contract (§6), never injected as ambient context, and never offered to an agent as a way to retrieve what it or another agent “remembers”. - Rebuildable. Every record in it is derived from a source the store does not own: a retained, replayable source: the domain pack’s own write-authoritative store (its Postgres domain schema, or its time-series data), or an external feed whose history the pack retains and names with the model version used to derive the records. A live external feed that the pack does not retain does not qualify, because losing the store would lose the history permanently. Wiping the store and rebuilding it from that source must produce identical behaviour. It is never the record of truth for anything, which is invariant 6 applied to a domain pack.
- Tenant-namespaced. Every collection, point payload, node and edge that holds tenant content carries
tenant_idas the leading key or label, per invariant 12 and the Tenancy Spec. Cross-tenant reads fail closed. - No silent formation. Nothing in it becomes a memory record by being read or copied. A fact that an agent wants the fabric to keep (a lesson learned, a durable observation about a subject) is proposed through
tool:memory-proposeand committed byos-agt-010as a newrawrecord with amemory.record.formedevent, like any other formation (§5.2). The operational store is not a tier, so this is formation, not promotion:memory.record.promotedis reserved for the later transition of the resulting record between tiers.
A store that fails any condition is governed memory, whatever the domain pack calls it. It must be written through os-agt-010 into memory_records (Group G), with Qdrant and Neo4j as its projections, and the agent’s memory_profile must say so.
Qdrant remains the single semantic vector substrate (invariant 7): a domain-owned collection is another collection in that same Qdrant, not a second vector store. Its naming, point identity, authorization and rebuild rules differ from the tier collections and are set in the Memory Runtime Integration Guide §2.3 (operational collections).
A fact that is already OS-owned lineage is never an operational store, whatever the domain pack calls it. Agent-to-outcome causal and contribution edges are the graph tier: the domain workflow writes the Postgres source record (agent_lineage_links, Group F) and the system projector writes the Neo4j edge. A domain agent holds no Neo4j write for it.
An operational store’s source of truth is committed first, and the store never gates it. The workflow commits the domain-schema record, then projects to the operational store asynchronously with retry, so losing the store cannot suppress the canonical record. A domain pack that declares such a store must say so in its Data and Memory Usage section, name the write-authoritative source each collection or graph is rebuilt from, and use the term operational store in the agent’s required_memory_layers rather than semantic_memory or graph_memory, so the two are not confused. The Trading domain pack is the worked example.
4. The memory record envelope
Every governed memory record carries this envelope. It deliberately mirrors the structure of the
common event envelope so
memory lineage and event lineage compose without translation. The event envelope gained a required tenant_id at v1.0, which a memory record already carries as scope.tenant_id.
| Field | Type | Required | Description |
|---|---|---|---|
memory_id | string (UUID) | Yes | Globally unique record identifier. Stable across supersession. |
tier | string | Yes | One of the eight tiers in §3.1. |
scope | object | Yes | Ownership and visibility. See §4.1. |
content | object | Yes | The memory payload. Shape is tier-specific and, for domain tiers, pack-defined. |
content_hash | string | Yes | Hash of content, used for dedup and for tombstone verification after erasure. |
provenance | object | Yes | What produced this record. See §4.2. |
derived_from | array[string] | Yes | memory_ids this record was consolidated or reflected from. Empty for a directly formed record. |
confidence | number (0–1) | Yes | Extraction or inference confidence. Recall filters and promotion thresholds read this. |
validity_interval | object | Yes | { valid_from, valid_until } (ISO 8601 UTC; valid_until nullable = open-ended). When the assertion is true, not when the row was written. |
consolidation_state | string | Yes | raw | consolidated | reflected | superseded | tombstoned. See §5. |
supersedes | string | null | Yes | The memory_id this record replaces, or null. |
retention_class | string | Yes | One of the classes in §8.1. Determines decay and erasure behaviour. |
compliance_labels | array[string] | No | Regulatory tags (e.g. pii, pci, gdpr-subject) inherited from the source event and honoured by erasure. |
version | string (SemVer) | Yes | Record schema version. |
4.1 scope — tenant first, always
"scope": {
"tenant_id": "acme",
"subject_id": "user-8842",
"agent_id": "com-agt-003",
"session_id": "sess-1f9c",
"visibility": "tenant"
}tenant_id is mandatory and always first in every scope tuple and every store namespace. This is a
fail-safe ordering, not a stylistic one: a namespace assembled in the wrong order under-matches and returns
nothing, rather than over-matching and returning another tenant’s memory. visibility is one of session,
agent, subject, tenant — and there is no cross-tenant visibility value. Cross-tenant recall is not a
scope setting; it is a promotion that requires policy approval (§7.3).
tenant_id is the tenant: the contracting organisation that owns one or more business instances (ADR-OS-008, Tenancy Spec). It is not a business instance, and the acme in these examples is a tenant. The reserved value platform marks shared reference data in other tables and is never a valid tenant_id for a memory record. visibility: tenant means visible across all of the tenant’s business instances. Whether memory needs a narrower business-instance visibility level is not decided here. The memory tables are tenant-owned, with composite same-tenant keys, as the Synedrix OS - Agent DB Schema defines.
4.2 provenance — every record traces to an event
"provenance": {
"source_event_id": "evt-7b21...",
"correlation_id": "corr-9d4a...",
"causation_id": "evt-7b1f...",
"formed_by": "os-agt-010",
"formation_method": "extraction"
}formation_method is one of extraction (an LLM or rule derived it from content), declaration (an agent or
human asserted it directly), consolidation (merged from derived_from), reflection (higher-order inference)
or import (migrated from an external system, in which case source_event_id names the import event).
A memory record with no provenance.source_event_id is non-compliant. There is no path by which memory
enters the fabric without an event having caused it.
4.3 Worked example
A consolidated semantic assertion derived from three episodes:
{
"memory_id": "mem-4c8e1a72-...",
"tier": "semantic",
"scope": {
"tenant_id": "acme",
"subject_id": "user-8842",
"agent_id": null,
"session_id": null,
"visibility": "tenant"
},
"content": {
"assertion": "Primary billing entity is Acme Logistics BV (NL).",
"entity_ref": "org-2231"
},
"content_hash": "sha256:9f2c...",
"provenance": {
"source_event_id": "evt-7b21c4d0-...",
"correlation_id": "corr-9d4a83f1-...",
"causation_id": "evt-7b1f0a92-...",
"formed_by": "os-agt-010",
"formation_method": "consolidation"
},
"derived_from": [
"mem-11d0...","mem-2a7f...","mem-93be..."
],
"confidence": 0.94,
"validity_interval": { "valid_from": "2026-07-02T09:14:00Z", "valid_until": null },
"consolidation_state": "consolidated",
"supersedes": "mem-0aa4...",
"retention_class": "durable",
"compliance_labels": ["pii"],
"version": "1.0.0"
}4.4 Why derived_from and validity_interval are mandatory
These two fields are the direct answer to the strongest published failure mode. EverMemBench reports that current memory systems handle evolving decisions inadequately “without explicit versioning systems”, and score 26% on cross-speaker reasoning even when handed perfect information — the information was present and still unusable, because nothing recorded who asserted it, when it became true, or what it replaced.
derived_from makes a consolidated assertion traceable to the episodes that produced it, so a contested claim
can be audited back to its speakers. validity_interval separates when a fact was true from when the row was
written, so a superseded assertion remains correct for its own interval instead of becoming silently wrong.
Neither is optional, because a record missing either one cannot participate in §9’s conflict resolution.
5. The memory lifecycle
5.1 State machine
flowchart TD
S([source event]):::term -- capture --> P[proposed: any agent may reach here]:::agent
P --> V{os-agt-012 validates scope}:::check
V -- deny --> X[memory.recall.denied / proposal rejected]:::warn
V -- allow, formation, os-agt-010 commits --> R[raw]:::agent
R -- consolidation, os-agt-011 recommends, os-agt-010 commits --> C[consolidated]:::agent
C -- reflection --> RF[reflected]:::agent
RF -- supersession --> SU([superseded]):::term
RF -- decay --> EXP([expired]):::term
RF -- erasure --> T([tombstoned]):::warn
PR[promotion, tier change may occur from raw / consolidated / reflected — see §7]:::check
R -.-> PR
C -.-> PR
RF -.-> PR
5.2 Stages and authority
| Stage | What happens | Who may trigger | Who commits | Event emitted |
|---|---|---|---|---|
| capture | A source event carries content eligible to become memory. | Any workflow or agent | — | (the source event) |
| formation | Content becomes a raw memory record with a full envelope. | Any agent (as a proposal) | os-agt-010 | memory.record.formed |
| consolidation | Several records merge into one derived record. | os-agt-011 (recommends) | os-agt-010 | memory.record.consolidated |
| reflection | A higher-order assertion is inferred — a profile trait, a distilled skill. | os-agt-011 (recommends) | os-agt-010 | memory.reflection.completed, memory.skill.distilled |
| promotion | A record moves to a longer-lived tier. | os-agt-011 or a workflow | os-agt-010, gated by os-agt-012 (and os-agt-002 where §7.3 requires) | memory.record.promoted |
| recall | A record is read into an agent’s context. | Any agent, as a tool call | — (read) | memory.recall.requested / .served / .denied |
| decay | validity_interval expires or a retention window closes. | Scheduler | os-agt-010 | memory.record.expired |
| demotion | A record’s tier or visibility is reduced. | os-agt-011 | os-agt-010 | memory.record.demoted |
| erasure | Content is destroyed; a tombstone remains. | Human or compliance workflow | os-agt-010, approved by os-agt-002 | memory.record.forgotten |
The separation of authority is the point. os-agt-011 recommends, os-agt-010 executes, os-agt-012
approves access. No agent both proposes and commits durable memory — the same shape the OS already uses to keep
Policy Guard in front of side effects.
5.3 Hot path versus background
| Stage | Path | Rationale |
|---|---|---|
| capture, formation proposal, recall | Hot path, inside the agent run | The agent needs the result now; latency counts against its budget. |
| formation commit, consolidation, reflection, decay, demotion | Background, scheduled | LLM-backed, latency-tolerant, and must not block a reasoning step. |
| erasure | Out of band, approval-gated | A compliance action with its own workflow and SLA. |
Background stages run as a scheduled orchestration workflow (WF-OS-MEMORY-CONSOLIDATE) invoking os-agt-011,
not as a side effect of an agent run. See
Memory Runtime Integration Guide §4.
6. The recall contract
6.1 Recall is a tool call
Ambient memory injection is non-compliant. A memory read is a tool call bound in the agent’s
active_tool_set, resolved through the three-layer tool authorization model in
Agent Runtime Policy Spec, traced to Langfuse, and
rejectable with agent.tool.unauthorized like any other tool.
This is a deliberate divergence from both EverOS and NAMS, which return memory to the agent without an authorization boundary. It buys three things the OS cannot do without: recall appears in the audit trail, recall scope is enforceable per agent rather than per deployment, and recall becomes measurable — the existing retrieval quality and groundedness metric families apply to it unchanged.
The canonical tool identifiers are tool:memory-recall (read) and tool:memory-propose (write proposal). An
agent with neither in its resolved active set has no memory access.
6.2 Request
{
"correlation_id": "corr-9d4a83f1-...",
"causation_id": "evt-7b1f0a92-...",
"requesting_agent": "com-agt-003",
"tiers": ["semantic", "profile"],
"scope": { "tenant_id": "acme", "subject_id": "user-8842" },
"query": "billing entity and invoicing preferences",
"filters": {
"min_confidence": 0.7,
"valid_at": "2026-08-16T10:00:00Z",
"compliance_labels_excluded": ["pci"]
},
"limit": 8
}6.3 Resolution rules
- Scope is resolved before retrieval, never after. The broker intersects the requested
scopewith the agent’smemory_profile.recall_scopeand pushes the result into the store query as a filter. Retrieving broadly and filtering in the agent is non-compliant — it means out-of-scope memory entered the process. - Tier access is checked per tier. A request naming a tier the agent may not read is not silently dropped;
the whole request is denied with
memory.recall.deniedand a reason. valid_atfilters onvalidity_interval, not on write time. Absentvalid_at, the broker defaults to now. Records whose interval does not containvalid_atare not returned.- Superseded and tombstoned records are never returned by a normal recall. Reconstructing a past state is a
separate, audit-scoped read available only to
os-agt-008. - Filters push down to the store.
min_confidence,valid_at, scope and compliance exclusions are translated into Qdrant payload filters, Postgres predicates or Cypher constraints — not applied post-hoc.
Rule 5 is a retrieval-quality mechanism as much as a security one. Beyond the Needle’s Illusion shows that semantic interference, not context length, is the binding constraint on evidence access — systems that score well on needle-in-a-haystack “degrade sharply in evidence access under semantic interference”. Narrowing the candidate set before ranking is therefore the single highest-leverage retrieval decision, and it happens to be the same seam as authorization.
6.4 Response
{
"correlation_id": "corr-9d4a83f1-...",
"status": "served",
"records": [ { "memory_id": "mem-4c8e...", "tier": "semantic", "content": { }, "confidence": 0.94,
"validity_interval": { }, "provenance": { } } ],
"truncated": false,
"scope_applied": { "tenant_id": "acme", "subject_id": "user-8842", "visibility": "tenant" },
"tiers_denied": []
}status is served, partial (some tiers denied, tiers_denied populated) or denied. Records are always
returned with their provenance and validity interval attached — an agent that receives a memory without
knowing where it came from or when it was true cannot ground its output, and groundedness is measured.
7. The promotion contract
7.1 The rule
No memory record crosses a tier boundary without a memory.record.promoted event carrying the record’s
correlation_id and causation_id unchanged.
This generalises the rule the OS already held for exactly one case — that conversation memory is never promoted
to long-term semantic memory without an explicit handoff event — to every tier pair.
7.2 Legal promotions
| From | To | Typical trigger | Gate |
|---|---|---|---|
working | episodic | Session handoff, run completion | os-agt-012 scope check |
episodic | semantic | Consolidation over ≥ N corroborating episodes | Confidence threshold + os-agt-012 |
episodic | procedural | Skill distillation from repeated successful trajectories | Confidence threshold + os-agt-012 |
episodic | profile | Reflection over subject-scoped episodes | os-agt-012 + subject consent labels |
semantic | relational | An assertion becomes canonical business state | os-agt-002 policy approval |
| any | any, with widened visibility | Broadening from session → agent → subject → tenant | os-agt-012 per step |
Demotion is always legal and always logged (memory.record.demoted). Narrowing scope needs no approval;
widening it does.
7.3 Promotions that require policy approval
approval_required.policy: true applies to:
- Any promotion into
relational— this writes canonical business state. - Any promotion that would widen
visibilitybeyondtenant. There is no cross-tenant visibility value, so this is by construction an exceptional, policy-gated act. - Any promotion of a record carrying a regulated
compliance_labelsvalue into a longer-retention class. - Any erasure (§8.4).
7.4 Thresholds are business-instance configuration
The mechanism — that a threshold is consulted before promotion — is OS-owned and specified here. The values (minimum corroborating episodes, minimum confidence, minimum successful trajectories before a skill is distilled) are business-instance configuration, per the rule of inclusion. A domain pack may declare defaults; only the instance may set them.
8. Retention, decay and erasure
8.1 Retention classes
| Class | Decay behaviour | Erasable | Typical tiers |
|---|---|---|---|
ephemeral | TTL, hard expiry | n/a — expires | working |
session | Expires at session close unless promoted | Yes | working |
operational | Windowed retention, then aggregation | Yes | temporal, episodic |
durable | No automatic expiry; decays only by supersession | Yes | semantic, procedural, profile |
audit | Never decays. Append-only. | Only via §8.4 tombstone | episodic (audit records), graph (lineage) |
regulated | Retention floor and ceiling set by compliance | Mandatory at ceiling | any, driven by compliance_labels |
8.2 The Layer 7 / Layer 12 boundary
Layer 7 owns the retention mechanism: what a retention class means, how decay executes, what a tombstone is.
Layer 12 (business instance) owns the retention values: how long operational is, what the regulated
floor and ceiling are for a given jurisdiction, how long a checkpoint is kept.
One cross-layer constraint is load-bearing and must be validated at instance configuration time:
Checkpoint retention must exceed the longest approval timeout. A checkpoint that expires before its approval does leaves an approved action with no run to resume — an approval that cannot be honoured.
8.3 Decay
Decay is scheduled, never opportunistic. Two mechanisms:
- Interval expiry —
validity_interval.valid_untilpasses. The record stops being returned by recall with avalid_atafter that point, but remains readable for audit and remains inderived_fromchains. - Retention window closure — the retention class’s window closes.
operationalrecords may be aggregated into atemporalsummary before removal, so the shape of the history survives its detail.
Both emit memory.record.expired. Neither destroys lineage.
8.4 Erasure and the tombstone rule
Forgetting is an approved action that leaves a tombstone.
When a tenant exercises a right to erasure, or a regulated retention ceiling is reached:
- The request is approved by
os-agt-002and executed byos-agt-010. contentis destroyed in the write-authoritative store and in every projection — Qdrant points deleted, Neo4j property values cleared, checkpoints purged.- A tombstone is written in canonical memory retaining:
memory_id,tier,scope.tenant_id,content_hash,provenance,derived_from,validity_interval, the erasure approval reference, and the erasure timestamp.consolidation_statebecomestombstoned. - The lineage edges in graph memory survive — the shape of what happened remains, with the content gone.
memory.record.forgottenis emitted.
The rule this protects: a deletion must never silently punch a hole in the audit trail. After erasure it
remains provable that a record existed, what produced it, what was derived from it, and that it was destroyed
under an approval — while the erased content itself is unrecoverable. content_hash is retained so a later
claim about what the record contained can be checked without the content being present.
Records with derived_from pointing at a tombstoned record are not cascaded automatically. They are flagged
for review by os-agt-011, because a derived assertion may or may not itself be personal data — that is a
judgement, not a mechanical consequence.
9. Conflict and contradiction
Two records may assert incompatible things. The fabric resolves by supersession, never by silent deletion.
| Situation | Resolution |
|---|---|
| New assertion contradicts an existing one, same subject and scope | New record sets supersedes; old record’s consolidation_state → superseded and its validity_interval.valid_until closes at the new record’s valid_from. Both remain readable for audit. |
Two records overlap in validity_interval and disagree | memory.conflict.detected is emitted. Neither is returned as authoritative until os-agt-011 proposes a resolution. Recall returns both with their confidences, flagged. |
| Confidences are close and provenance differs | Higher confidence wins only if the margin exceeds the instance’s threshold; otherwise it escalates as above. declaration outranks extraction at equal confidence. |
A record’s derived_from chain contains a superseded record | The derived record is flagged for re-consolidation, not invalidated. Its own validity interval still stands. |
The design commitment: the fabric never resolves a contradiction by destroying evidence. A superseded record is still true for its own interval, and the transition itself is a fact worth keeping.
10. Governance invariants
These are enforced and must never be violated.
- No memory record crosses a tier boundary without a
memory.record.promotedevent carryingcorrelation_idandcausation_idunchanged. - Recall is a tool call. Memory reads are bound in
active_tool_setand pass the three-layer tool authorization model. Ambient memory injection is non-compliant. - Every memory record has
provenance.source_event_id. Memory never enters the fabric uncaused. - Only
os-agt-010commits durable memory. Every other agent proposes. Writes toepisodic,semantic,proceduralandprofilefrom any other agent are non-compliant. os-agt-012is on the path of every recall and every write proposal. Scope resolution happens before retrieval, never after.- Supabase PG17 is write-authoritative for every audit-bearing tier. Qdrant, Neo4j and the LangGraph store are projections; wiping and rebuilding a projection must not change behaviour.
- Qdrant is the single semantic vector substrate. No second vector store enters Layer 7.
- Erasure leaves a tombstone; lineage in graph memory survives erasure of content.
workingmemory is never a source of truth. A run that cannot be reconstructed from durable tiers after working memory is lost is non-compliant.- Contradictions are resolved by supersession, never by deletion.
os-agt-008(Audit & Lineage) remains read-only and must never appear in any agent’stools_allowedlist, including as a memory tool.tenant_idis first in every scope tuple and every store namespace, so a malformed scope fails closed.- A domain-owned operational store is never memory. It must be rebuildable from a retained source it does not own, tenant-namespaced, never recalled as agent memory, and never turned into a memory
record except through
memory-propose, which forms it as a new record (§3.6). A store that fails any of these is governed memory and routes throughos-agt-010.
11. Deployment modes
Every tier must be satisfiable in Mode 3 (air-gapped). Nothing in this specification requires an external service.
| Concern | Mode 1 (cloud-connected) | Mode 2 (self-hosted hybrid) | Mode 3 (air-gapped) |
|---|---|---|---|
| Stores | All self-hosted | All self-hosted | All self-hosted |
| Extraction / consolidation inference | Cloud model APIs permitted | Per-agent split, declared in runtime policy | Local only (Ollama / vLLM) |
| Embeddings for the Qdrant index | Cloud embedding APIs permitted | Per-agent split | Local only |
| NAMS | Self-hosted bolt against the OS Neo4j | Same | Same. MEMORY_LLM / MEMORY_EMBEDDING must resolve to local URIs |
| NAMS hosted service | Not permitted in any mode | — | — |
Air-gapped invariant. A business instance declared deployment_mode: air-gapped must not contain any memory
control-plane configuration with a cloud model or embedding URI. This is a configuration validation error, not a
warning — the same rule the deployment model spec already applies to agent runtime policy, extended to the
memory control plane.
Consolidation compute budget. In Mode 3, background consolidation and reflection compete with agent inference for the same local GPUs. The scheduling window and compute budget are business-instance configuration; the control plane must degrade by deferring background stages, never by skipping the governance path.
12. Adopted and rejected external systems
Recorded here for reference; decided in ADR-OS-002.
| System | Position | Reason |
|---|---|---|
NAMS (neo4j-labs/agent-memory, Apache 2.0) | Adopted as a library over the existing Neo4j | Runs on infrastructure the OS already operates; supplies the graph tier’s ontology and reasoning-to-entity edges. Not a platform row — the LangChain precedent. |
| NAMS hosted service | Rejected | Proprietary SaaS; breaks Principle 11 and Mode 3 — the LangSmith precedent. |
| EverOS model (episode → consolidation → profile/skill distillation) | Adopted as the canonical lifecycle | Implemented on the existing fabric in §5. |
| EverOS runtime (Markdown + SQLite + LanceDB) | Rejected from canon | LanceDB duplicates Qdrant; SQLite duplicates Supabase; Markdown-as-truth contests Supabase’s write-authoritative role. Evaluated under the governed lab lane as LAB-001 in the stack repository. |
LangGraph BaseStore | Interface adopted, implementation OS-owned | The compliance seam where authorization, lineage and retention are enforced. Stock implementations are not canonical. |
| EverMemBench / EverMemBench-S / LoCoMo / LongMemEval | Adopted as the memory evaluation harness | Hooked into the existing Agent Evaluation Spec rather than replaced by a bespoke suite. |
13. Open items
Neo4j Community Edition vector-index support.Resolved. Vector indexes are available in Community Edition per the Operations Manual’s per-edition feature table, so NAMS’s 5.20+ requirement is met and thegraphtier is deployable on Community in all three modes. Community’s actual limits for this tier are a single standard database, uniqueness-only constraints and offline-only backup — all absorbed by the control plane. See Memory Runtime Integration Guide §5.4.- NAMS project maturity. Experimental Neo4j Labs project, community-supported, no SLA. Version pinning and an exit path are required before production use.
- Licence verification. EverOS and NAMS both read Apache 2.0 from their repositories; re-verify at source per the platform-page convention before recording a licence position.
- Procedural memory evaluation. Whether a distilled skill improved outcomes is an evaluation question the Agent Evaluation Spec does not yet cover. Needs a promotion gate of its own.
Versioning
- Version: 0.4
- Supersedes: synedrix-os-memory-fabric-spec-v0.3.md
- Related: ADR-OS-002, Memory Runtime Integration Guide
Related Documents
Decision and runtime binding
- Synedrix OS ADR-OS-002 — Memory Fabric Control Plane — The decision this specification implements; the EverOS and NAMS evaluation.
- Synedrix OS Memory Runtime Integration Guide — How Layer 4 binds to this specification:
SynedrixMemoryStore, the NAMS client, the compliance checklist.
Architecture and principles
- Synedrix OS Core Principles — Principle 5 (Shared context with scoped access) and Principle 7 (Explainability and audit by design).
- Synedrix OS Layer Taxonomy Table — Layer 7 definition and the “memory is shared, access is scoped” layer principle.
- Synedrix OS Taxonomy Spec — §8 memory types, superseded by §3 here.
- Synedrix OS Vocabulary — Canonical store names and the memory-fabric terminology this document extends.
Agents and contracts
- Synedrix OS - Agent Registry —
os-agt-010,os-agt-011andos-agt-012implement the control plane. - Synedrix OS - Agent Spec —
memory_profileis the per-agent security boundary this specification scopes. - Synedrix OS Event Taxonomy Standard — The
memory.*catalog and the envelope this record envelope mirrors. - Synedrix OS - Agent Runtime Policy Spec — The three-layer tool authorization model recall passes through.
- Synedrix OS - Agent DB Schema — Relational persistence for memory records and profiles.
Platform reference
- Supabase PG17 — Write-authoritative for every audit-bearing tier.
- Qdrant — The single semantic vector substrate.
- Neo4j — The
graphtier and the NAMS binding. - Redis — The
workingtier. - QuestDB — The
temporaltier.
Deployment
- Synedrix OS Deployment Model Spec — The three modes and the air-gapped validation rule §11 extends.
Teaching material
- Synedrix OS Academy — Chapter 02.8 (context engineering and the memory taxonomy) and chapter 04.4 (short-term state versus canonical store) teach the reasoning behind §3, §6 and §10. Teaching material, not normative: where a chapter disagrees with this specification, this specification wins.
Synedrix OS · August 2026