Agent Memory Primitives
Spectral runs one production agent — the World Agent — with its own memory system. This page names the underlying questions any agent’s memory answers as primitives: the axes an agent’s memory parameterizes. The framing is deliberately agent-general so that test-agents and any future agent parameterize against the same template.
The primitives doctrine is: every agent’s memory chooses an explicit value for each foundational primitive, and either accepts the typology-implied default for each behavioral primitive or documents a deviation. New agent memories follow the same template. The Memory System page and the World Agent memory specification read as parameterizations of this page.
Foundational primitives
Section titled “Foundational primitives”These five primitives are structural. Every agent’s memory makes an explicit choice on each.
1. Anchor entity
Section titled “1. Anchor entity”The scope tuple that keys an agent’s memory. Every other decision cascades from this choice — tier boundaries, retention semantics, visibility, conflict resolution, and promotion criteria all resolve differently depending on what anchors the persistent tier.
The anchor entity is the agent’s tenancy model expressed as a key tuple. Mature systems make this
a required primitive (LangGraph’s BaseStore requires a namespace argument; Mem0 exposes
user_id / agent_id / run_id as first-class scoping keys).
What an agent’s memory specifies: the full scope tuple, which keys are required at write time, and which are nullable for cross-scope queries. The persistent tier’s anchor is the most consequential — it determines what survives across sessions and what gets garbage-collected at session-end.
Example anchor for Spectral’s production agent:
| Agent | Persistent-tier anchor |
|---|---|
| World Agent | (org_id, domain_id) — world_model_version is contextual provenance per ADR-058 D5, not a version pin |
2. Memory typology
Section titled “2. Memory typology”The distribution of episodic / semantic / procedural memory across an agent’s tiers. This typology is the field-converged framing (CoALA paper; Mem0; Zep facts-vs-episodes; CrewAI entity memory) and most behavioral primitives’ values follow from it.
- Episodic — what happened, tied to time and interaction context. “During this code-gen pass, the operator asked for a tighter threshold check after the inline-test failed.”
- Semantic — facts about the domain or world the agent operates in, time-invariant within their validity window. “The conformity gate requires authoritative-source citations for Authoritative-tier promotion.”
- Procedural — how to do things; behavioral preferences and patterns. “This operator prefers concise distillation outputs over exhaustive ones.”
What an agent’s memory specifies: the typology mix at each tier. Most agents’ transient tiers (interaction, session, conversation) are episodic by nature — that part is the floor. The persistent tier is where typology diverges and where cross-agent differences live.
Example typology distribution:
| Agent | Transient tiers | Persistent tier |
|---|---|---|
| World Agent | Episodic | Semantic + procedural about the world’s domain (exploration patterns, code-generation patterns, discovery observations) |
3. Tier model
Section titled “3. Tier model”The number of tiers, what defines a tier boundary, and what each tier holds. Field convergence is two to four tiers; some are time-scoped (cycle / run), some scope-anchored (domain / operator / world).
What an agent’s memory specifies: tier count; per-tier name; the lifecycle event or scope change that defines each boundary; which tier is the persistent (top) tier.
A tier boundary is one of:
- Lifecycle event — interaction-end, session-end, run-end. The boundary is temporal.
- Scope change — entering a different domain, operator, or world. The boundary is the anchor change.
- Anchor escalation — moving from a more-scoped anchor to a broader one (e.g., session-scoped to operator-scoped at promotion).
4. Persistence backend
Section titled “4. Persistence backend”The physical home of memory state. Convention follows LangGraph’s two-axis split:
- Checkpointer / short-term — interaction state, framework-managed, append-mostly. Spectral
uses the LangGraph
AsyncPostgresSaverin a dedicatedlanggraphschema. Every agent shares this backend for its conversation/session checkpointer. - Store / long-term — application-managed memory, queryable, embedding-indexed, lives in
the agent’s owning context (
worlds.*for World Agent memory).
What an agent’s memory specifies: the schema(s) each tier lands in; whether tiers share a backend or split across checkpointer + store; cross-context read access patterns where applicable.
5. Retrieval model
Section titled “5. Retrieval model”How memory enters the agent’s reasoning. Hybrid is the field default — vector + structured tag + recency, fused via Reciprocal Rank Fusion (RRF) or weighted score. Embedding choice is part of this primitive and is pinned globally to BGE-small-en-v1.5 with the retrievable-table convention.
What an agent’s memory specifies: the signal mix (which retrieval signals contribute); the scoring method (RRF k=60 is the default); per-tier retrieval scope (one tier? all tiers? weighted by tier?); whether a reranking layer sits on top.
The World Agent uses a three-signal RRF retrieval over its tiers (structured envelope match + semantic search + time decay). Per-agent specifications may deviate where typology requires (e.g., procedural-dominant memory may weight recency higher than semantic similarity).
Behavioral primitives (typology-driven defaults)
Section titled “Behavioral primitives (typology-driven defaults)”These primitives have typology-implied defaults. Each agent picks a typology mix at each tier, and these primitives’ values follow. Documented deviations require justification on the per-agent memory page.
6. Lifecycle / retention
Section titled “6. Lifecycle / retention”What dies, what archives, what stays.
| Typology | Default lifecycle |
|---|---|
| Episodic (transient) | Drop at scope-end unless promoted at the tier boundary. |
| Episodic (persistent) | Forcing-function decay toward disposition: promote, mark exempt, or archive (see Time decay). |
| Semantic | Persist with corroboration tracking. Archive when invalidated by canonical-source change or by N consecutive failed corroborations. |
| Procedural | Persist indefinitely. Decay-exempt by default. Archive on explicit invalidation only. |
The persistent tier registers a RetentionPolicy directly per the four-state model in
data retention (ACTIVE / REFERENCED / ORPHANED / TOMBSTONED).
Transient tiers (interaction, session) inherit lifecycle from their enclosing scope —
interaction → chat thread; session → operator session — rather than registering a literal TTL.
The persistent-vs-transient axis is about the durability of the memory itself, not “ephemeral
by construction.”
7. Time decay model
Section titled “7. Time decay model”What pressure decay creates on stored memory.
| Typology | Default decay model |
|---|---|
| Episodic (persistent) | Forcing-function — entries must dispose toward an outcome (promote / mark exempt / archive). Decay weight in retrieval scoring increases as time passes, creating pressure toward continued evaluation rather than fade-into-irrelevance. |
| Semantic | Validity-window decay — entries carry validity-as-of timestamps; decay reflects diminishing confidence in still-current state. Re-corroboration extends validity. |
| Procedural | Decay-exempt by default — preferences and workflow patterns are durably true unless invalidated by a contradicting write. |
The World Agent’s “forcing-function” decay on its persistent-tier semantic memory (per Memory System) is the episodic-persistent default inherited at the semantic boundary — typology-consistent for a semantic-leaning persistent tier.
8. Write policy
Section titled “8. Write policy”When and how memory rows are written.
| Typology | Default write policy |
|---|---|
| Episodic | Auto-write at observation events (interaction turn, tool-call completion). Volume controlled by sampling and promotion gates. For the World Agent, interaction-tier writes during code-generation passes flow through the agent’s memory gateway. |
| Semantic | Explicit-write through a promotion engine; never directly written by the agent. The promotion gate enforces corroboration. |
| Procedural | Mixed — explicit-write for operator-stated preferences; auto-extract from interaction patterns with high-confidence threshold. |
9. Promotion semantics
Section titled “9. Promotion semantics”What triggers an entry’s move up a tier.
| Source → Target | Default promotion criteria |
|---|---|
| Episodic (transient) → Episodic (persistent) | Compounding pass at tier boundary; embedding-similarity dedup against existing persistent entries |
| Episodic (persistent) → Semantic | Corroboration across ≥ N independent observations; sanitization-gate pass; cross-context validity |
| Semantic → meta-semantic (cross-version / cross-anchor) | ≥ 2-version persistence; non-empty surviving canonical-reference set; recurrence threshold |
| Procedural | No promotion — procedural memory is the durable form |
Spectral’s compounding engine (per Memory System) implements the episodic→semantic gate. The records-vs-memory boundary blocks records-verbatim writes at the gateway; only value-added reasoning about canonical records (audit-chain entries, override-pattern signals, operator-action audit rows) is admitted.
10. Conflict resolution
Section titled “10. Conflict resolution”What happens when a new memory contradicts an existing one. Convention follows
Mem0’s ADD / UPDATE / DELETE / NOOP decisions and Zep’s temporal-validity invalidation.
| Typology | Default conflict resolution |
|---|---|
| Episodic | NOOP — episodes accumulate; contradictions are themselves observations |
| Semantic | UPDATE with temporal validity — old fact gets invalid_at = now(); new fact gets valid_at = now(). Both retained for audit |
| Procedural | UPDATE with supersession — the latest preference wins; the prior is archived for audit, never hard-deleted |
11. Consolidation / summarization
Section titled “11. Consolidation / summarization”How multiple observations merge into fewer, richer entries.
| Typology | Default consolidation |
|---|---|
| Episodic | Periodic compounding at tier boundaries; embedding-similarity dedup at promotion |
| Semantic | LLM-based merge on contradicting or overlapping facts (ADD/UPDATE per Mem0 pattern) |
| Procedural | Append-with-supersession; the latest valid preference replaces the prior in the active set |
12. Injection semantics + token budget
Section titled “12. Injection semantics + token budget”How memory enters the agent’s prompt + per-block token accounting. Field convergence:
per-memory-block token budgets with priority-based eviction (LlamaIndex MemoryBlock.token_limit)
and retrieval-on-demand for lower-priority tiers (MemGPT paged-in core memory for highest
priority).
What an agent’s memory specifies: per-tier token budget; eviction priority within budget; whether each tier is retrieved-on-demand or always-present-in-prompt; reranking layer if any.
Static budgets and priorities are the default; tune when measured retrieval quality or context-window pressure justifies it. Persistent-tier retrieval is on-demand via the retrieval model (primitive 5); transient tiers are always-present within their lifecycle.
Discipline primitives (cross-cutting invariants)
Section titled “Discipline primitives (cross-cutting invariants)”These primitives are not typology-driven. Each agent’s memory answers each independently.
13. Reference-only invariants
Section titled “13. Reference-only invariants”What canonical state the agent’s memory must not duplicate. Each agent declares a non-mirror list — concrete categories of state that live elsewhere as a single source of truth and may only be referenced (never copied).
| Agent | Non-mirror list |
|---|---|
| World Agent | World-model rule content; audit-chain entries; customer PII; override-pattern signal row bodies |
Schema-level enforcement preferences:
- No wide text columns on memory tables. Memory rows hold structured envelopes, FK references, and bounded-length reasoning notes — never canonical-source bodies.
- Junction tables for canonical references. When a memory row references rules or other canonical entities, use a junction table with real foreign keys (with version pinning where the canonical entity is versioned), not arrays of UUIDs.
- Views for reference resolution. Where the agent needs to present canonical content alongside memory, use a database view that joins to the canonical source at query time rather than materializing the content.
14. Sanitization gates
Section titled “14. Sanitization gates”Where content is transformed when it crosses a tenant, context, or trust-scope boundary. Sanitization is distinct from access control: access control gates who can read; sanitization changes what they read.
| Boundary crossing | Gate |
|---|---|
| Override-pattern signal aggregation → rule-candidate proposal | Strip deployment-specific identifiers; preserve the world model’s by-pattern correlation |
| World Agent memory → operator chat surface | Hedge-mapping to provenance tier; “I don’t know” as first-class output where the world model has unknown coverage |
| World Agent memory → customer chat surface (post-release per ADR-081 D5) | Auth-scoped read-only tool subset; no operator-mode tools exposed; no cross-domain leakage |
The override-pattern aggregation gate is the canonical example: a pattern expressed without deployment-specific detail routes into the candidate-proposal flow; one that requires deployment specificity to be meaningful stays at the customer-side flagging surface.
15. Visibility / access scope
Section titled “15. Visibility / access scope”Who can read what. Access enforcement uses the layering per ADR-033: app-layer tenancy primary, RLS as backstop. Reads across contexts do not use SQL grants — per ADR-063, call flow between contexts goes through DI-injected protocols composed at the framework-layer entrypoint (see Contract Surfaces).
| Agent | Read access pattern |
|---|---|
| World Agent memory | Internal to worlds, anchored on (org_id, domain_id); operator read via direct operator-mode chat; customer-mode access (post-release per ADR-081 D5) is auth-scoped read-only over the customer’s own world; no direct DB read from another context |
Audit and immutability (universal default)
Section titled “Audit and immutability (universal default)”The audit posture is action-linkage-based, not blanket-tier-based:
- No hard
DELETEon persistent-tier memory. Persistent memory is durable by definition. - No hard
DELETEon any-tier memory load-bearing for audit. When a memory was the basis of a downstream action — a rule promotion, a change-set acceptance, a published decision — the linkage from the action back to the memory rows that justified it stays intact. The memory cannot be removed from beneath the action, regardless of which tier it lives in. - Transient-tier memory without action-linkage can be removed when its scope ends. Interaction-tier memory tied only to a conversation can be discarded when the chat thread closes; session-tier memory tied only to an operator session can be discarded when the session closes.
- Soft-supersession. When a memory is no longer surfaced by retrieval (archived, decayed,
invalidated, superseded), a state column records the transition (
archived_at,superseded_at,invalidated_at) but the row stays.
This posture supports Explainability and the regulatory posture on auditability of agentic actions.
Implementation note (per-agent specificity)
Section titled “Implementation note (per-agent specificity)”The universal default scopes which tiers are transient and which carry action-linkage-bearing memory by agent. Per ADR-058 D10:
- World Agent. Interaction and session tiers are transient; session-tier memory is
retained within the interaction window per ADR-058 D12
and then inherits scope-close lifecycle. The persistent tier (anchored on
(org_id, domain_id)) carries action-linkage-bearing memory (code-generation patterns, rule-revision signals, contradictions surfaced to operators, promoted candidates).
The action-linkage rule overrides the tier-transience default: any-tier memory load-bearing for audit (rule promotion, version publication, override-pattern triage) is retained regardless of which tier it lives in.
Per-agent leak-defense calibration
Section titled “Per-agent leak-defense calibration”Per-agent memory leak defense is calibrated to memory consumption pattern, not assumed uniform across agents.
- World Agent (semantic-leaning over rules). The trigram trigger against
worlds.rules.body_textis the primary defense — the agent reasons OVER rules to produce semantic claims, so rule-shadow risk is structurally close to the write path. Where an agent instead reasons with canonical content via tools (procedural-dominant memory), the same-shape trigram trigger is a defense-in-depth backstop and primary defense is agent-design discipline (workshop framing — see Reference-only invariants).
When a new agent is parameterized against these primitives, the calibration question is: does the agent reason OVER canonical content (trigger as primary defense) or WITH canonical content via tools (trigger as backstop with workshop discipline as primary)?
Parameterizing a new agent’s memory
Section titled “Parameterizing a new agent’s memory”When introducing a new agent (or revising an existing agent’s memory spec), work the primitives in this order:
- Anchor entity — pick the scope tuple. Every other decision flows from it.
- Memory typology — distribute episodic / semantic / procedural across tiers. Most behavioral primitives’ defaults follow from this.
- Tier model — count, names, boundary events.
- Persistence backend — which schemas; checkpointer / store split.
- Retrieval model — signal mix and scoring.
- Behavioral primitives — accept typology defaults or document each deviation.
- Discipline primitives — declare the agent’s non-mirror list, sanitization gates, visibility/access scope. Each is an explicit, per-agent choice.
- Audit posture — universal default unless a specific exemption is justified (none currently exist).
The result is a per-agent memory spec that reads as a parameterization of this page rather than as a standalone design.