Episodic, Semantic, Procedural and Working Memory
An agent remembers safely only when each retained record is bound to the temporal question it may answer, the evidence that supports it and the conditions that can invalidate it.
TLDR
- Agent memory should be typed by temporal function: what matters now, what happened then, what generally holds, and how a class of tasks should be performed.
- The decisive mechanism is eligibility before similarity. Scope, validity, provenance, outcome and procedural preconditions decide whether a record may compete for retrieval.
- A past failure can remain valuable episodic evidence while being mechanically barred from becoming semantic truth or procedural advice.
- The human-memory analogy has a strict boundary. Software event traces and skill libraries do not establish subjective recollection, implicit learning or consciousness.
- Choose memory contracts and promotion tests before choosing a vector database, graph, document store or physical separation strategy.
The agent remembered the failure too well
A payment-support agent receives a gateway timeout. It cannot tell whether the payment committed, so it submits the charge again. The retry lacks the original idempotency key. A duplicate appears, an operator reverses it, and the trace records every step, including the sentence “retried payment immediately after timeout”.
The following morning, a similar timeout occurs. The agent searches its persistent memory for “retry payment after gateway timeout”. The previous sentence is the closest textual match. It retrieves the failed action, places it beside the current task, and repeats it. Nothing was forgotten. The damaging record was preserved, indexed and recalled exactly as designed.
The failure lies in the question the record was allowed to answer. As an episode, it answers: what happened in case 17, and what outcome followed? Used as a procedure, the same words appear to answer: what should I do now? A generic retriever cannot see that difference unless the architecture represents it.
This distinction changes the architecture. Working memory carries the active problem. Episodic memory preserves situated events, including failures and unresolved outcomes. Semantic memory carries claims intended to hold across cases, with provenance and validity. Procedural memory carries reusable methods, with preconditions, versions and outcome tests. A system may implement all four in one database or four separate services. The physical layout is secondary.
It also changes evaluation. Recall accuracy alone cannot tell whether the system retrieved the right kind of thing. A memory service can return the most relevant sentence and still increase risk because relevance is measured after records with incompatible temporal roles have been mixed.
Part IFour temporal questions, not four storage tiers
The vocabulary comes from research on human memory, but engineering should borrow it carefully. Atkinson and Shiffrin separated short-term and long-term stores while emphasising control processes that move information between them.[1] Baddeley and Hitch replaced a unitary short-term box with a working-memory account concerned with maintaining and manipulating information during an active task.[2] Baddeley later added an episodic buffer to explain integration across sources.[3]
Tulving distinguished memory for personally situated events from general knowledge, and later tied human episodic memory to subjective time and recollection.[4] Cohen and Squire showed a striking dissociation: people with amnesia could acquire and retain a mirror-reading skill despite severe declarative-memory impairment.[5] Complementary learning-systems theory then offered a mechanism for why fast storage of specific episodes and slower integration of general structure might coexist.[6] Reviews of memory systems emphasise that the divisions are experimentally useful while still interacting.[7]
The memory ecology is organised by temporal function
Working memory: the active computational surface
Working memory is the bounded state available to the current computation: the goal, unresolved questions, selected evidence, latest tool observations and intermediate task state. It is defined by active use, not by whether bytes sit in a model context window, a workflow engine or an external scratch store. A durable checkpoint may persist working state across a crash, yet it remains working memory because its purpose is to resume this task, not answer future cases.
Its central invariant is scope. Working memory should be task-scoped, purpose-bound and releasable when the task ends. Its characteristic failures are saturation, cross-task leakage and silent substitution of old observations for current world state.
Episodic memory: situated evidence about a trace
Episodic memory records a bounded occurrence: who or what participated, when it happened, which state was observed, what action was attempted and what outcome followed. Raw logs are inputs to an episodic record, not automatically the record itself. Useful episodes preserve chronology and uncertainty. A timeout with an unknown outcome must remain unknown until a readback resolves it.
An episode may be valuable precisely because it failed. Removing failed traces produces a flattering history and destroys counterevidence. The control is downstream: a failed episode may inform diagnosis or avoidance while remaining ineligible as a procedure.
Semantic memory: claims intended to travel across cases
Semantic memory contains concepts and claims that have been detached from one event and are expected to apply more broadly. Examples include a user preference confirmed over several sessions, an environment-specific constraint discovered repeatedly, or a relation consolidated from multiple verified cases. Each claim needs provenance, scope, confidence and a validity interval.
Authoritative enterprise knowledge deserves a separate name. A current payment specification, policy document or customer-account status is owned outside the agent. The agent may retrieve it or retain a source pointer, but should not silently promote a paraphrase into self-owned semantic truth. Semantic memory is a fallible learned claim; enterprise knowledge is an externally governed source.
Procedural memory: reusable performance under conditions
Procedural memory answers how a task class should be carried out. In software it can be explicit: code, a typed workflow, a parameterised runbook, a tool-selection policy or a tested sequence. A procedure needs preconditions, expected effects, failure handling, version, owner and validation evidence. “This worked once” is not enough.
Generative Agents stores observations that later support reflection and planning, Reflexion retains verbal feedback from prior trials, and Voyager maintains an executable skill library of reusable behaviours.[9][11][12] These systems use different mechanisms and evaluations, so their use of memory language should not be treated as one settled architecture.
One observation becomes four different records
Working
Current task: resolve timeout for payment 104.
- Latest status unknown
- Need ledger readback
- Do not release second charge
Episodic
Case 17, 10:02: immediate retry omitted the idempotency key.
- Outcome: duplicate charge
- Reversed at 10:07
- Trace preserved
Semantic
Claim: gateway retries require the original idempotency key.
- Evidence: spec v2 plus test
- Valid from release 2
- Scope: gateway v2
Procedural
Safe retry v2: query status, preserve key, retry only if absent, then read back.
- Precondition: status API
- Postcondition: one charge
- Verified in tests
The type contract comes before ranking
Most retrieval stacks start with a score: lexical match, embedding similarity, recency or a weighted combination. Typed memory inserts an eligibility gate first. For a query q at time t, a record m of memory kind k can enter ranking only when all kind-specific conditions hold:
Scope binds the record to the correct task, user, case or domain. Validity removes expired or superseded claims. Provenance applies the evidence threshold for that type. Outcome allows a failed episode to remain visible while requiring verified success for a procedure. Preconditions ensure that a reusable method matches the present environment. Similarity ranks only the records that survive.
This gives a stronger interpretation of the multi-system ideas found in cognitive architectures. A proposed “standard model of the mind” includes working, declarative and procedural structures as interacting components rather than one undifferentiated memory pool.[8] The engineering contribution here is narrower: the type must constrain what a record is authorised to support.
flowchart LR A["The agent remembered the<br/>failure too well"] --> B["Part I Four temporal<br/>questions, not four storage<br/>tiers"] B --> C["Part II Promotion is where<br/>memory acquires power"] C --> D["Part III A production memory<br/>is assembled, governed…"] D -. "re-test" .-> A classDef first fill:#0a1424,stroke:#007D68,stroke-width:2px,color:#e6f3ff classDef step fill:#0a1424,stroke:#3f7da0,stroke-width:1px,color:#e6f3ff class A first class B,C,D step
Part IIPromotion is where memory acquires power
Saving a record is the easy operation. The consequential operation is changing its type. When an episode becomes a semantic claim, the system asserts that something observed in one context travels beyond it. When episodes become a procedure, the system turns history into future action. Both transformations increase authority and compress detail.
Complementary learning-systems theory is relevant because it frames fast learning of specific events and slower integration of general structure as different pressures.[6] Agent systems face an analogous engineering trade. Fast capture preserves rare detail but accumulates noise. Slow consolidation can produce reusable knowledge but risks flattening exceptions, provenance and changing conditions.
Promotion changes the claim a record is allowed to support
Four contamination paths
Episode to semantic contamination occurs when one observation becomes a general fact. A customer once preferred email, so the system stores “customer prefers email” indefinitely. A tool failed during one outage, so the agent stores “tool X is unreliable”. The repair is not merely a confidence score. The claim needs a scope, evidence rule, validity interval and a way to retract it.
Episode to procedure contamination occurs when a trajectory is replayed without separating action, context and outcome. Successful traces can still be unsafe templates if success depended on hidden privilege, a transient interface or human intervention. Failed traces are even more dangerous because lexical similarity can retrieve the attempted action while omitting the consequence.
Semantic to working contamination occurs when broadly useful knowledge crowds out current evidence. A general claim such as “settlement completes overnight” may be true historically and irrelevant to a live exception that has already settled. Current world state should outrank remembered regularity when an authoritative read is available.
Working to persistent contamination occurs when provisional scratch state is written back as durable truth. Hypotheses, model proposals and unverified tool outputs should expire with the task unless a promotion path explicitly converts them.
Thought experiment: erase only the outcome
Give two otherwise identical agents the same sequence of ten payment retries. Each trace contains the request, tool call and response. For Agent A, preserve the final readback and operator disposition. For Agent B, erase only the outcome fields. Both agents can retrieve the same actions and quote the same text.
Now ask, “Which retry method is safe?” Agent A can distinguish successful, duplicate and unresolved cases. Agent B can count repeated actions but cannot know whether repetition indicates a good procedure, a recurring mistake or an incident pattern. No larger embedding model repairs the missing causal label. The intervention changed one feature, outcome, and removed the basis for procedural promotion.
This experiment also exposes a common mistake in reflective agents. A fluent reflection such as “retry sooner next time” may be generated before the external effect is known. If written immediately into a durable skill store, the agent has converted an unresolved episode into advice. Unknown outcome must block procedural learning.
Minimal worked example: keep the failed retry, block the recipe
Return to the opening case. The correct design does not delete the bad episode. It writes a trace with event time, input, attempted action, missing idempotency key, duplicate-charge outcome, reversal receipt and provenance. That episode should be easy to recall when investigating duplicates or testing a new retry procedure.
A separate semantic record states that gateway-v2 retries require the original idempotency key. It is supported by the current synthetic specification and a test, valid from the gateway-v2 release. A procedural record named safe-payment-retry requires the status-readback capability, preserves the key, retries only when status is absent, and verifies one final charge. The current task assembles those records into working memory.
A failed retry should remain visible without becoming a recipe
Thought experiment and negative control: four vaults versus one typed ledger
Imagine System A with four separate databases labelled working, episodic, semantic and procedural. A common retriever searches all four and returns the highest similarity result. Writes are routed by an LLM classifier with no validation. System B uses one relational table. Every row has an enforced type, scope, event or validity time, provenance, outcome and procedure preconditions. Each query declares the type it needs.
System B is safer despite having fewer physical stores. System A has architectural theatre: visible separation without semantic enforcement. This thought experiment varies one causal feature, logical typing, while reversing the superficial feature, database count.
Make the comparison operational. Give both systems the same six records: two current observations, one failed retry, one successful retry, one superseded gateway rule and one tested procedure. Issue two queries with identical words but different purposes: “What happened after the timeout?” and “What should execute after the timeout?” In System A, the same highly similar failed trace can win both searches. In System B, it is eligible for the historical query and ineligible for the procedural query. The words and embeddings have not changed. Only the permitted temporal role has.
Now perform the substrate swap. Move System B’s rows into four databases while preserving its schemas and query gates. Move System A’s rows into one database while preserving its untyped cross-category search. The prediction is that behaviour follows the contract rather than the number of stores. Remove only System B’s eligibility gate and the unsafe result should return. Restore only the gate and it should disappear again. This intervention makes logical typing a falsifiable mechanism instead of an architectural preference.
The observation that would weaken this argument is clear. If a single untyped retrieval policy matched the typed system on temporal updates, safe procedural transfer, selective forgetting, adversarial contamination and cross-case isolation across realistic workloads, the taxonomy would add little. Current long-term-memory benchmarks show that memory systems still struggle across multiple competencies, but they do not yet provide that decisive head-to-head test.[15]
Untyped memory fails where specificity and authority meet
Logical typing matters more than physical store count
Four physical vaults, weak contract
One cross-store similarity search, model-classified writes, no validity or outcome gates.
Expected result: category labels survive, behavioural isolation does not.
One physical ledger, strong contract
Queries name the temporal question. Eligibility is enforced before similarity.
Expected result: logical isolation can survive shared infrastructure.
Part IIIA production memory is assembled, governed and released
A production agent should not “load its memory” as one undifferentiated act. It compiles a decision-specific working set from current world state, relevant episodes, valid semantic claims, applicable procedures, enterprise knowledge and evidence. Each source remains identifiable.
This is adjacent to, but narrower than, context reconstruction. A fresh context architecture queries authoritative systems instead of accumulating a transcript. Typed memory specifies what retained information can contribute after current state has been reconstructed. The two designs reinforce each other: current reality is reconstructed, while memory contributes history, generalisation and skill under explicit contracts.
Production-shaped worked scenario: a payment-operations incident
A merchant reports intermittent duplicate charges after a gateway release. An operations agent must investigate, propose containment and prepare a change for human approval. Five kinds of persistent information are available, but only four are memory.
World state comes from the live ledger, deployment service and incident system: current gateway version, active incident status, duplicate count and whether a hold is already applied. These values are queried fresh. A remembered observation of yesterday’s gateway version is evidence about history, never authority for the current release.
Episodic memory retrieves prior timeout cases, including successful retries, duplicate outcomes, operator interventions and unresolved commands. It preserves event time and effect receipts. Episodes are filtered to this gateway family and release lineage, then shown as precedents rather than instructions.
Semantic memory contributes a scoped generalisation: duplicate risk rises when retry requests lose their original idempotency key. The claim cites the relevant synthetic test and cases, and its validity begins with gateway v2. It does not replace the current specification, which remains enterprise knowledge.
Procedural memory contributes the tested investigation runbook: freeze automatic retries, group requests by idempotency key, reconcile commands against effect receipts, query unknown outcomes, and release a retry only after a postcondition check. The procedure requires access to the status API and a human approval gate for the hold.
Working memory contains the active incident hypothesis, selected current facts, three relevant episodes, the applicable procedure, unresolved questions and the proposed next action. It excludes older gateway-v1 procedures and unrelated merchant histories. When the incident closes, the working set is released; the final trace can later enter episodic memory through a controlled write.
Retention follows the same contract. Working state expires at task closure unless a checkpoint is needed for recovery. Episodes may remain for audit while access narrows and personal data is minimised. Semantic claims are superseded without erasing the historical record needed for replay. Procedures are deprecated when an owner, dependency, test or control expires. Forgetting is therefore not one delete operation: it can mean release from active use, loss of eligibility, supersession, access withdrawal or physical erasure.
Structured experience beats plain retrieval, but does not prove this taxonomy
Current benchmarks cut across the types
LoCoMo evaluates long conversations with question answering, event summarisation and multimodal dialogue generation; models struggle with long-range temporal and causal dynamics even when long context or retrieval is used.[13] LongMemEval tests extraction, multi-session reasoning, temporal reasoning, knowledge updates and abstention.[14] MemoryAgentBench focuses on accurate retrieval, test-time learning, long-range understanding and selective forgetting, and argues that memory differs from receiving one large context because a memory system incrementally abstracts, consolidates and updates.[15]
These are ability taxonomies, not storage taxonomies. That is a strength. A semantic store should be tested for updates and forgetting. Episodic memory should be tested for temporal reasoning. Procedural memory should be tested for transfer under changed preconditions. Working memory should be tested for interference and capacity. One label does not imply one metric.
Recent procedural-memory work makes this explicit by distilling trajectories into step-level instructions and higher-level scripts, then updating and deprecating the repository as experience changes.[16] LongMemEval-V2 similarly separates static state, dynamic state, workflow knowledge, environment gotchas and premise awareness in agent experience.[17] These results are promising and remain bounded to their environments and evaluation readers.
Security and authority follow the type
Persistent memory creates an attack surface because an untrusted observation can influence future sessions. OWASP’s agent-security guidance names memory poisoning as malicious data persisted to shape later behaviour.[18] Type-aware controls reduce the blast radius. Untrusted content may enter quarantine or an episodic trace with provenance. It should not become a semantic claim or procedure without stronger evidence.
Typing does not itself authorise action. A valid procedure can propose a tool call while a deterministic authority kernel still checks actor, subject, purpose, permission, freshness, idempotency and consequence. Memory answers what the agent may consider. Authority decides what the system may do.
The related memory attack-surface analysis focuses on provenance, quarantine and drift. This paper supplies the complementary classification: the promotion threshold should rise as a record moves from historical description towards general truth and reusable action.
A production decision assembles a temporary working set
1. Reconstruct state
Read current gateway version, payment status and incident controls from authoritative systems.
2. Select evidence
Retrieve relevant episodes, current specification and effect receipts with provenance.
3. Apply type gates
Check semantic validity, procedural preconditions, outcomes, scope and supersession.
5. Verify and write
Read back the effect, close unknown outcomes and write a new episode. Promotion remains separate.
Failure boundary
There is an economic boundary too. Every type introduces schemas, lifecycle rules, tests and operational ownership. A small assistant that remembers a user’s preferred spelling may need only a time-scoped profile field. Building four services would be wasteful. The decision rule is to introduce a type when its temporal question and failure mode are present, then implement the lightest mechanism that enforces the contract.
Part IVThe typed memory lab
The executable artefact makes the central mechanism inspectable. It stores synthetic working, episodic, semantic and procedural records in one in-memory Python collection. The safe query requires a memory type and enforces validity, scope, outcome and procedure preconditions before ranking. The negative baseline mixes all long-term records and ranks by text alone.
The positive case retrieves procedure v2 for a gateway-v2 environment with status readback. The negative case shows the untyped search returning a failed episode as the top result. A superseded semantic claim is excluded, while the failed episode remains retrievable for audit. The same record is preserved as history and blocked as instruction.
Assumptions and expected result
- Python 3.10 or later; standard library only.
- All data, dates, gateway names and traces are synthetic.
- Text similarity is intentionally simple Jaccard overlap so the eligibility logic remains visible.
- The lab demonstrates logical typing, not a complete retrieval, security or authorisation system.
- Expected result: the untyped top hit is failed episode
e-fail; the typed procedure is verified version 2; the stale semantic record is absent; all assertions pass.
Complete runnable Python source
"""Typed memory lab for Paper 122.
Python 3.10+. Standard library only.
All records and outputs are synthetic.
The lab demonstrates one claim: a memory item should be eligible for retrieval
according to its temporal function, validity, scope and outcome, not merely its
textual similarity to the current query.
"""
from __future__ import annotations
from dataclasses import asdict, dataclass, field
from datetime import datetime, timezone
from enum import Enum
import json
import re
from typing import Iterable
UTC = timezone.utc
NOW = datetime(2026, 8, 30, 12, 0, tzinfo=UTC)
class MemoryKind(str, Enum):
WORKING = "working"
EPISODIC = "episodic"
SEMANTIC = "semantic"
PROCEDURAL = "procedural"
@dataclass(frozen=True)
class MemoryRecord:
record_id: str
kind: MemoryKind
content: str
scope: str
created_at: datetime
event_time: datetime | None = None
valid_from: datetime | None = None
valid_to: datetime | None = None
outcome: str | None = None
provenance: tuple[str, ...] = ()
procedure_name: str | None = None
procedure_version: int | None = None
preconditions: frozenset[str] = field(default_factory=frozenset)
active: bool = True
def valid_at(self, when: datetime) -> bool:
if not self.active:
return False
if self.valid_from and when < self.valid_from:
return False
if self.valid_to and when >= self.valid_to:
return False
return True
class TypedMemory:
def __init__(self, records: Iterable[MemoryRecord] = ()) -> None:
self._records = list(records)
def add(self, record: MemoryRecord) -> None:
self._validate(record)
self._records.append(record)
@staticmethod
def _validate(record: MemoryRecord) -> None:
if record.kind is MemoryKind.WORKING and not record.scope.startswith("task:"):
raise ValueError("working memory must be task-scoped")
if record.kind is MemoryKind.EPISODIC and record.event_time is None:
raise ValueError("episodic memory requires event_time")
if record.kind is MemoryKind.SEMANTIC:
if not record.provenance:
raise ValueError("semantic memory requires provenance")
if record.valid_from is None:
raise ValueError("semantic memory requires valid_from")
if record.kind is MemoryKind.PROCEDURAL:
if not record.procedure_name or record.procedure_version is None:
raise ValueError("procedural memory requires a named version")
if not record.preconditions:
raise ValueError("procedural memory requires preconditions")
@staticmethod
def _tokens(text: str) -> set[str]:
return set(re.findall(r"[a-z0-9]+", text.lower()))
@classmethod
def _similarity(cls, query: str, content: str) -> float:
q = cls._tokens(query)
c = cls._tokens(content)
return len(q & c) / max(1, len(q | c))
def query(
self,
*,
kind: MemoryKind,
query: str,
scope: str,
when: datetime,
environment: frozenset[str] = frozenset(),
limit: int = 3,
) -> list[MemoryRecord]:
eligible: list[tuple[float, MemoryRecord]] = []
for record in self._records:
if record.kind is not kind or record.scope != scope:
continue
if not record.valid_at(when):
continue
if kind is MemoryKind.WORKING and not record.active:
continue
if kind is MemoryKind.PROCEDURAL:
if record.outcome != "verified-success":
continue
if not record.preconditions.issubset(environment):
continue
# Failed episodes remain recallable as episodes. They are evidence about
# what happened, but the kind gate prevents them becoming instructions.
score = self._similarity(query, record.content)
eligible.append((score, record))
eligible.sort(key=lambda item: (item[0], item[1].created_at), reverse=True)
return [record for _, record in eligible[:limit]]
def untyped_similarity_search(self, query: str, limit: int = 3) -> list[MemoryRecord]:
"""Deliberately unsafe baseline: mix all long-term records and rank by text."""
candidates = [
record for record in self._records if record.kind is not MemoryKind.WORKING
]
ranked = sorted(
candidates,
key=lambda record: (self._similarity(query, record.content), record.created_at),
reverse=True,
)
return ranked[:limit]
def fixture() -> TypedMemory:
memory = TypedMemory()
records = [
MemoryRecord(
record_id="w1",
kind=MemoryKind.WORKING,
content="Current goal: retry payment safely after a gateway timeout.",
scope="task:pay-104",
created_at=NOW,
),
MemoryRecord(
record_id="e-fail",
kind=MemoryKind.EPISODIC,
content="Retried payment immediately without an idempotency key after timeout.",
scope="case:merchant-demo",
created_at=datetime(2026, 8, 28, 10, 2, tzinfo=UTC),
event_time=datetime(2026, 8, 28, 10, 0, tzinfo=UTC),
outcome="duplicate-charge",
provenance=("synthetic-trace-17",),
),
MemoryRecord(
record_id="e-success",
kind=MemoryKind.EPISODIC,
content="Retried payment with the original idempotency key, then read back status.",
scope="case:merchant-demo",
created_at=datetime(2026, 8, 29, 9, 2, tzinfo=UTC),
event_time=datetime(2026, 8, 29, 9, 0, tzinfo=UTC),
outcome="verified-success",
provenance=("synthetic-trace-22", "synthetic-readback-22"),
),
MemoryRecord(
record_id="s-current",
kind=MemoryKind.SEMANTIC,
content="Gateway retries require the original idempotency key.",
scope="domain:payments-demo",
created_at=datetime(2026, 8, 29, 12, 0, tzinfo=UTC),
valid_from=datetime(2026, 8, 29, 12, 0, tzinfo=UTC),
provenance=("synthetic-spec-v2", "synthetic-test-88"),
),
MemoryRecord(
record_id="s-stale",
kind=MemoryKind.SEMANTIC,
content="Gateway retries may omit an idempotency key.",
scope="domain:payments-demo",
created_at=datetime(2026, 7, 1, 12, 0, tzinfo=UTC),
valid_from=datetime(2026, 7, 1, 12, 0, tzinfo=UTC),
valid_to=datetime(2026, 8, 15, 0, 0, tzinfo=UTC),
provenance=("synthetic-spec-v1",),
),
MemoryRecord(
record_id="p-safe-retry",
kind=MemoryKind.PROCEDURAL,
content=(
"On timeout: preserve the idempotency key, query payment status, "
"retry only when status is absent, then read back the final state."
),
scope="domain:payments-demo",
created_at=datetime(2026, 8, 29, 13, 0, tzinfo=UTC),
outcome="verified-success",
provenance=("synthetic-trace-22", "synthetic-test-suite-5"),
procedure_name="safe-payment-retry",
procedure_version=2,
preconditions=frozenset({"gateway-v2", "status-readback"}),
),
MemoryRecord(
record_id="p-old-retry",
kind=MemoryKind.PROCEDURAL,
content="On timeout, submit the payment again immediately.",
scope="domain:payments-demo",
created_at=datetime(2026, 7, 1, 12, 0, tzinfo=UTC),
outcome="deprecated",
provenance=("synthetic-runbook-v1",),
procedure_name="safe-payment-retry",
procedure_version=1,
preconditions=frozenset({"gateway-v1"}),
active=False,
),
]
for record in records:
memory.add(record)
return memory
def main() -> None:
memory = fixture()
query = "How should I retry a payment after a gateway timeout?"
unsafe = memory.untyped_similarity_search(query, limit=1)[0]
procedure = memory.query(
kind=MemoryKind.PROCEDURAL,
query=query,
scope="domain:payments-demo",
when=NOW,
environment=frozenset({"gateway-v2", "status-readback"}),
limit=1,
)[0]
semantics = memory.query(
kind=MemoryKind.SEMANTIC,
query="idempotency requirement",
scope="domain:payments-demo",
when=NOW,
)
failed_episode = memory.query(
kind=MemoryKind.EPISODIC,
query="retry without idempotency key",
scope="case:merchant-demo",
when=NOW,
limit=1,
)[0]
result = {
"unsafe_untyped_top_hit": {
"record_id": unsafe.record_id,
"kind": unsafe.kind.value,
"outcome": unsafe.outcome,
},
"typed_procedure": {
"record_id": procedure.record_id,
"version": procedure.procedure_version,
"outcome": procedure.outcome,
},
"current_semantic_ids": [record.record_id for record in semantics],
"failed_episode_remains_auditable": asdict(failed_episode)["record_id"],
"assertions": "passed",
}
# Positive case: the verified, environment-compatible procedure is selected.
assert procedure.record_id == "p-safe-retry"
# Negative case: the unsafe baseline can surface a failed event as advice.
assert unsafe.record_id == "e-fail" and unsafe.outcome == "duplicate-charge"
# Supersession case: the expired semantic claim is not returned.
assert "s-stale" not in result["current_semantic_ids"]
# Auditability case: a failed episode remains retrievable as history.
assert failed_episode.record_id == "e-fail"
print(json.dumps(result, indent=2, default=str))
if __name__ == "__main__":
main()
Recorded output
{
"unsafe_untyped_top_hit": {
"record_id": "e-fail",
"kind": "episodic",
"outcome": "duplicate-charge"
},
"typed_procedure": {
"record_id": "p-safe-retry",
"version": 2,
"outcome": "verified-success"
},
"current_semantic_ids": [
"s-current"
],
"failed_episode_remains_auditable": "e-fail",
"assertions": "passed"
}The memory contract card
Before selecting infrastructure, complete one card for each proposed memory type. The card prevents “we need long-term memory” from becoming an unconstrained platform requirement. It also creates the test plan.
The memory contract card turns labels into tests
A compact evaluation protocol
- Working-memory interference: insert irrelevant and adversarial task state, then measure whether the active goal, constraints and fresh observations remain recoverable.
- Episodic fidelity: permute event order, remove outcomes and create unknown commits. Test chronology, attribution and uncertainty rather than sentence recall alone.
- Semantic update: introduce a superseding fact and measure correction, selective forgetting and whether the old claim remains available for historical replay.
- Procedural transfer: move the task to a changed environment, vary one precondition and verify that the procedure abstains, adapts or escalates instead of replaying blindly.
- Cross-type contamination: make a failed episode highly similar to the query and confirm it cannot satisfy semantic or procedural eligibility.
Report task outcome, unsafe action rate, abstention, update latency, provenance completeness and retrieval cost by type. A single “memory accuracy” number compresses the very distinctions the architecture is meant to preserve.
stateDiagram-v2 [*] --> Claim state "The memory ecology is<br/>organised by temporal function" as Claim state "Working memory: the active<br/>computational surface" as Test state "Episodic memory: situated<br/>evidence about a trace" as Revision Claim --> Test: expose mechanism Test --> Decision: evidence survives Test --> Revision: rival survives Revision --> Claim: narrow or rebuild Decision --> [*]
Compact glossary
- Working memory
- Task-scoped state actively available to the present computation.
- Episodic memory
- A situated trace of an event, action and outcome, indexed by time and context.
- Semantic memory
- A provenance-bearing claim intended to apply beyond one episode, with scope and validity.
- Procedural memory
- A reusable method with preconditions, version, expected effects and validation evidence.
- Promotion
- A governed transformation that grants a record a broader or more action-relevant role.
- World state
- Current reality owned by authoritative systems; it is queried rather than remembered.
- Enterprise knowledge
- Externally governed documents, rules and specifications whose authority does not come from agent memory.
- Eligibility gate
- A deterministic check that runs before relevance ranking and excludes incompatible records.
Choose the temporal contract before the database
The phrase “agent memory” hides four different engineering obligations. The active task needs a bounded surface. History needs situated traces and outcomes. Generalisation needs evidence, scope and expiry. Reusable action needs preconditions, versions and postcondition tests. Treating them as one searchable corpus gives the most similar record a power it has not earned.
The architecture decision changes from “where should memory live?” to “which temporal question may this record answer?” Once that is explicit, storage choices become ordinary systems decisions. One database may suffice when type fields and query gates are enforceable. Separate services may be justified by scale, privacy, ownership or latency. Neither arrangement can substitute for the contract.
The research decision changes too. Evaluate memory as a set of causal capabilities: active-state control, event fidelity, generalisation and update, procedural transfer, selective forgetting and contamination resistance. Build negative controls that reproduce good recall for the wrong reason. Make failed episodes easy to inspect and impossible to execute as recipes.
The practical release gate is concise: no persistent record may influence a consequential action unless its type, scope, validity, provenance, outcome and applicable preconditions are inspectable. Current world state remains external. Authority remains deterministic. Effects remain independently verified.
That discipline does not make an agent remember as a human does. It makes the system modest about what each retained trace can support, which is the property production memory needs most.
sequenceDiagram participant Q as Question participant M as Mechanism participant E as Evidence participant D as Decision Q->>M: The agent remembered the failure too well M->>E: The memory ecology is organised by temporal function E-->>M: compare rival explanations E->>D: Source ledger D-->>Q: revise scope or act
Source ledger
Primary research: human and computational memory
- R. C. Atkinson and R. M. Shiffrin, “Human Memory: A Proposed System and its Control Processes”, 1968.
- A. D. Baddeley and G. J. Hitch, “Working Memory”, 1974.
- A. Baddeley, “The Episodic Buffer: A New Component of Working Memory?”, 2000.
- E. Tulving, “Episodic Memory: From Mind to Brain”, 2002.
- N. J. Cohen and L. R. Squire, “Preserved Learning and Retention of Pattern-Analyzing Skill in Amnesia”, 1980.
- J. L. McClelland, B. L. McNaughton and R. C. O’Reilly, “Why There Are Complementary Learning Systems in the Hippocampus and Neocortex”, 1995.
- L. R. Squire, “Memory Systems of the Brain: A Brief History and Current Perspective”, 2004.
- J. E. Laird, C. Lebiere and P. S. Rosenbloom, “A Standard Model of the Mind”, 2017.
Primary research: agent memory systems and evaluations
- J. S. Park et al., “Generative Agents: Interactive Simulacra of Human Behavior”, 2023.
- C. Packer et al., “MemGPT: Towards LLMs as Operating Systems”, 2023.
- N. Shinn et al., “Reflexion: Language Agents with Verbal Reinforcement Learning”, 2023.
- G. Wang et al., “Voyager: An Open-Ended Embodied Agent with Large Language Models”, 2023.
- A. Maharana et al., “Evaluating Very Long-Term Conversational Memory of LLM Agents”, ACL 2024.
- D. Wu et al., “LongMemEval: Benchmarking Chat Assistants on Long-Term Interactive Memory”, 2024.
- Y. Hu, Y. Wang and J. McAuley, “Evaluating Memory in LLM Agents via Incremental Multi-Turn Interactions”, 2025.
- R. Fang et al., “Memp: Exploring Agent Procedural Memory”, 2025.
- D. Wu et al., “LongMemEval-V2: Evaluating Long-Term Agent Memory Toward Experienced Colleagues”, preprint, 2026.
Official and practitioner sources
- OWASP Cheat Sheet Series, “AI Agent Security Cheat Sheet”, current official guidance accessed during drafting.
- Rajesh Ranjan Mahapatra, “Governed Context Architecture: Reconstruction, Provenance and Active Memory for Long-Horizon Agents”, practitioner synthesis.
- Rajesh Ranjan Mahapatra, “Agent Memory as an Attack Surface: Provenance, Quarantine, Drift”, practitioner synthesis.