AI Agent Memory: schema-gestuurde state en provenance
Automatische vertaling Dit artikel is automatisch vertaald vanuit de oorspronkelijke Engelse versie.
Long-running agents halen vaak verouderde feiten op, omdat gewone semantic memory geen regel heeft om te bepalen welke waarde actueel is.
Wanneer een gebruiker een paspoortdeadline wijzigt van 15 juli naar 30 juni, kan vector search beide uitspraken ophalen. Een stateful memory-laag moet vastleggen dat de waarde van 30 juni de eerdere waarde vervangt.
Voor engineers die long-running of multi-tenant agents bouwen, is dit stale-fact-probleem precies waarom memory aparte runs moet overleven en tegelijk current state en tenant boundaries moet afdwingen. Het onderstaande ontwerp laat zien hoe je typed records schrijft en current versus point-in-time reads test, zonder vector recall als source of truth te behandelen.
De context-window-valkuil
De context window is de input die beschikbaar is voor één model call. Een applicatie kan messages meenemen naar latere calls, maar application policy moet bepalen welke oude feiten nog kloppen en wie ze mag zien.
Long-running agents moeten preferences, task status, customer facts, tool decisions, compliance notes en eerdere fouten onthouden. De eenvoudige aanpak is om summaries toe te voegen of oude notes in een vector store te dumpen. Dat werkt totdat een van die onthouden feiten verandert.
De agent heeft dan twee paspoortdeadlines, twee voorkeuren voor formats of twee projectbeslissingen. Semantic search kan ze allebei ophalen. Een summary kan er één overschrijven. Een lange context kan het verouderde feit naast het actieve feit bevatten. Deze ontwerpen halen tekst op, maar dwingen de current value niet af.
Het memory contract moet concrete vragen beantwoorden:
- Wat is nu waar?
- Wat was waar op 2 juni?
- Wie heeft het gezegd?
- Bij welke tenant hoort het?
- Welk ouder feit heeft dit feit vervangen?
- Kan ik het verwijderen of laten verlopen?
Schema-Guided Agent Memory (SGAM) slaat deze antwoorden op als fields en relations, in plaats van ze impliciet in prose te laten.
Wat SGAM betekent
Drie vergelijkbaar benoemde concepten bakenen de scope van SGAM af.
Schema-Guided Dialogue (SGD) is de 2019 Google task-oriented dialogue dataset. Het schema beschrijft service APIs, intents en slots, zodat een dialogue model state kan bijhouden voor services die het nog niet heeft gezien. Het is een nuttig precedent voor schema-based tracking, met een scope die beperkt blijft tot dialogue services.
Schema-Guided Memory (SGM) is de researchterm die Mei et al. gebruiken in According to Me: Long-Term Personalized Referential Memory QA. De paper vergelijkt free-text Descriptive Memory (DM) met fixed-schema key-value memory items. Beide representaties bevatten dezelfde broninformatie, maar in verschillende structuren.
In dit artikel gebruik ik Schema-Guided Agent Memory (SGAM) voor een engineering pattern waarin schemas writes, updates, retrieval en deletion aansturen. Het schema definieert application state en de lifecycle daarvan.
ATM-Bench laat zien waarom de representatie ertoe doet. De benchmark gebruikt ongeveer vier jaar aan persoonlijke data uit emails, images en videos. De vragen vereisen personal references, location, meerdere stukken evidence en updates door de tijd heen. Op de hard split rapporteert de paper dat SGM DM overtreft voor retrieval en question answering binnen de geteste setup. SGM maakt fields zoals time, source, location, entities en tags zichtbaar in een fixed representation. Ik beschouw die representatie en de gerapporteerde resultaten als de ondersteunde conclusie; de paper toont geen direct field-addressing mechanism aan.
SGM versus DM beantwoordt een storagevraag: moet memory free text blijven, of named fields gebruiken? Een production agent heeft vóór storage nog een ander probleem. Het moet een unstructured conversation omzetten in een voorgestelde memory update. Schema-Guided Reasoning (SGR) maakt die beoogde decision path inspectable: de response kan evidence, subject en attribute, een vergelijking met de current state en een candidate write bevatten. De model response dwingt geen dependencies of order tussen die fields af. Separate calls, validators en application policy handhaven die regels; SGAM past de storage- en lifecycle-regels toe na de model call.
Scheid model extraction van memory ownership
De memory write loopt over drie lagen. Structured Output (SO) handhaaft de shape van het candidate object. Schema-Guided Reasoning (SGR) maakt de intended fields en decision intent inspectable in een gestructureerde response. Schema-Guided Agent Memory (SGAM) beheert de candidate als durable state na de model call. Separate calls, validators en application policy handhaven dependencies, order en lifecycle.
Een verdict, route of plan verloopt meestal samen met de huidige request. Een andere run kan dagen later een memory candidate uitlezen of die gebruiken om een tool call te kiezen. Die langere levensduur vereist storage rules die SGR niet levert.
SGR structureert één model call rond een intended reasoning topology. Voor een memory write kan de response source evidence, een normalized subject en attribute, een vergelijking met current state en een proposed update bevatten. Pydantic of JSON Schema beschrijft die fields. Provider-native Structured Output of een guided decoding runtime zoals XGrammar houdt de response in die shape.
Die shape maakt de door het model gedeclareerde fields en intent inspectable. Ze garandeert geen correcte conclusie en bewijst niet dat het model die fields in de juiste volgorde heeft gebruikt. Separate calls, validators en application policy vormen de enforcement boundary voor dependencies, order en lifecycle.
SGAM bepaalt wat er gebeurt zodra dat object bestaat. Moet het worden opgeslagen? Vervangt het een ouder feit? Welke tenant mag het zien? Is het current of historical? Welke source episode ondersteunt het?
De tabel beschrijft het ownership en de failure mode van elke laag:
| Dimensie | SO | SGR | SGAM |
|---|---|---|---|
| Doel | Een object retourneren dat aan een schema voldoet | Intended fields en decision intent inspectable maken | Durable memory beheren na de model call |
| Scope | Eén generated response | Eén model response; cross-step policy kan meerdere calls omvatten | Records die tussen calls, sessions en runs worden gebruikt |
| Rol van het schema | Definieert output fields, types en toegestane waarden | Beschrijft evidence, intermediate fields en candidate decision | Definieert stored records, relations en lifecycle |
| Enforcement | Constrained decoding blokkeert schema-invalid output | Alleen shape; separate calls, validators en policy handhaven dependencies en order | Application validation, database constraints en conflict rules handhaven lifecycle |
| Levensduur | Huidige call, tenzij de applicatie het object opslaat | Reasoning trace wordt meestal na de decision verwijderd | Blijft bestaan totdat het wordt bijgewerkt, expired of verwijderd |
| Failure mode | Valide shape met de verkeerde betekenis | Fields zijn aanwezig, maar reasoning of dependency handling kan nog steeds verkeerd zijn | Stale, polluted, unscoped of unauditable state |
Op de write path is de volgorde:
SGR reasoning schema + Structured Output -> candidate write -> SGAM policy and persistence
Het volgende illustratieve fragment uit memory_models.py definieert het object dat van extraction naar de SGAM write service gaat. Dit block heeft Pydantic nodig en wordt daarom gemarkeerd als no-run in de example checks voor environments waarin die optional dependency niet is geïnstalleerd:
from datetime import datetime
from pydantic import BaseModel, Field
class MemoryDelta(BaseModel):
tenant_id: str = Field(description="Isolation boundary, e.g. acme")
subject: str = Field(description="Normalized entity ID, e.g. mira")
attribute: str = Field(description="Property being updated")
value: str = Field(description="New value")
valid_from: datetime
source_episode_id: str
MemoryDelta legt vast wat het model heeft geëxtraheerd. De SGAM write service bepaalt nog steeds of het object wordt rejected, merged of opgeslagen.
Write- en read paths hebben verschillende taken
Alleen de write path muteert opgeslagen state. De read path selecteert records voor de huidige request.
De ingestion flow is de write path:
- Leg een raw episode vast uit messages, tool results of business events.
- Extraheer typed candidates via structured output.
- Valideer het schema en reject malformed writes.
- Reconcile conflicts, sluit stale facts af en bewaar provenance.
- Commit het record naar de SGAM store.
De request flow is de read path:
- Begin met de user question.
- Bepaal of de vraag current state of point-in-time state nodig heeft.
- Filter op tenant, memory type, subject, attribute en validity window.
- Voeg vector- of graph-expansion alleen toe als de exacte state lookup niet volstaat.
- Stel de kleinste cited context voor het model samen.
Lees dat diagram van links naar rechts in twee lanes. De bovenste lane schrijft memory, de onderste leest het. Beide gebruiken dezelfde store.
Wat in een memory schema hoort
Een minimaal SGAM-record heeft meer nodig dan text.
tenant_id
memory_id
subject
attribute
value
memory_type
schema_version
valid_from
valid_to
supersedes_memory_id
source_episode_id
confidence
retention_policy
Met deze fields kan een nieuwe paspoortdeadline de vorige deadline sluiten zonder de history te wissen. Dezelfde tabel kan current en point-in-time queries beantwoorden en het resultaat vervolgens terugleiden naar de source episode. schema_version ondersteunt migrations, terwijl retention_policy deletion jobs vertelt wat ze nog meer moeten verwijderen.
Gebruik RAG om documents op te halen en SGAM om mutable state te beheren. Vector search hoort nog steeds in het systeem thuis voor fuzzy recall, clustering en expansion. De current value van mira.passport_deadline moet uit een scoped memory record komen, niet uit het chunk dat toevallig het hoogst gerankt werd.
Een stale-fact-voorbeeld
Beschouw een synthetische trace met twee episodes, weergegeven als een DM-baseline en een SGAM-ledger:
e1: Mira prefers concise answers. Her passport deadline is 2026-07-15.
e2: Mira corrected the deadline. It is now 2026-06-30.
Een DM-baseline bewaart beide episodes als free text, waardoor text search e1 kan retourneren omdat die de juiste woorden bevat. SGAM extraheert uit elke episode een typed fact, keyed by tenant, subject en attribute. Het moet e2 als current state retourneren en e1 bewaren voor een historical query.
Het volgende is een self-contained SQLite write path. Deze gebruikt ISO-8601 UTC-strings voor timestamps, configureert sqlite3.Row voordat er op column name wordt gelezen en representeert facts als half-open intervals: [valid_from, valid_to). De tabel reject invalid intervals en heeft een partial unique index voor één open fact per tenant, subject en attribute. replace_fact beheert één transaction; SQLite serializeert concurrent writers, dus callers moeten de volledige transaction retrien na een lock- of uniqueness error.
import sqlite3
from dataclasses import dataclass
@dataclass(frozen=True)
class MemoryFact:
tenant_id: str
subject: str
attribute: str
value: str
valid_from: str
source_episode_id: str
def open_db() -> sqlite3.Connection:
db = sqlite3.connect(":memory:")
db.row_factory = sqlite3.Row
db.executescript(
"""
create table memory_facts (
fact_id integer primary key,
tenant_id text not null,
subject text not null,
attribute text not null,
value text not null,
valid_from text not null,
valid_to text,
source_episode_id text not null,
check (valid_to is null or valid_from < valid_to)
);
create unique index one_open_fact
on memory_facts (tenant_id, subject, attribute)
where valid_to is null;
"""
)
return db
def replace_fact(db: sqlite3.Connection, fact: MemoryFact) -> None:
with db:
exact = db.execute(
"""
select fact_id
from memory_facts
where tenant_id = ? and subject = ? and attribute = ? and valid_from = ?
""",
(fact.tenant_id, fact.subject, fact.attribute, fact.valid_from),
).fetchone()
if exact:
raise ValueError("equal valid_from requires an application conflict policy")
containing = db.execute(
"""
select fact_id, valid_to
from memory_facts
where tenant_id = ?
and subject = ?
and attribute = ?
and valid_from < ?
and (valid_to is null or valid_to > ?)
limit 1
""",
(
fact.tenant_id,
fact.subject,
fact.attribute,
fact.valid_from,
fact.valid_from,
),
).fetchone()
if containing:
db.execute(
"update memory_facts set valid_to = ? where fact_id = ?",
(fact.valid_from, containing["fact_id"]),
)
successor_boundary = containing["valid_to"]
else:
successor = db.execute(
"""
select valid_from
from memory_facts
where tenant_id = ? and subject = ? and attribute = ? and valid_from > ?
order by valid_from
limit 1
""",
(fact.tenant_id, fact.subject, fact.attribute, fact.valid_from),
).fetchone()
successor_boundary = successor["valid_from"] if successor else None
db.execute(
"""
insert into memory_facts
(tenant_id, subject, attribute, value, valid_from, valid_to, source_episode_id)
values (?, ?, ?, ?, ?, ?, ?)
""",
(
fact.tenant_id,
fact.subject,
fact.attribute,
fact.value,
fact.valid_from,
successor_boundary,
fact.source_episode_id,
),
)
def fact_at(db: sqlite3.Connection, timestamp: str) -> sqlite3.Row:
return db.execute(
"""
select value, source_episode_id
from memory_facts
where tenant_id = ?
and subject = ?
and attribute = ?
and valid_from <= ?
and (valid_to is null or valid_to > ?)
limit 1
""",
("acme", "mira", "passport_deadline", timestamp, timestamp),
).fetchone()
db = open_db()
replace_fact(
db,
MemoryFact("acme", "mira", "passport_deadline", "2026-07-15", "2026-06-01T09:00:00Z", "e1"),
)
replace_fact(
db,
MemoryFact("acme", "mira", "passport_deadline", "2026-06-30", "2026-06-03T10:00:00Z", "e2"),
)
current = fact_at(db, "2026-06-04T00:00:00Z")
assert (current["value"], current["source_episode_id"]) == ("2026-06-30", "e2")
historical = fact_at(db, "2026-06-02T00:00:00Z")
assert (historical["value"], historical["source_episode_id"]) == ("2026-07-15", "e1")
# A delayed extraction predates e1. It ends at e1's existing boundary,
# rather than closing e2, which remains current.
replace_fact(
db,
MemoryFact("acme", "mira", "passport_deadline", "2026-08-01", "2026-05-30T08:00:00Z", "e0"),
)
delayed = fact_at(db, "2026-05-31T00:00:00Z")
assert (delayed["value"], delayed["source_episode_id"]) == ("2026-08-01", "e0")
current = fact_at(db, "2026-06-04T00:00:00Z")
assert (current["value"], current["source_episode_id"]) == ("2026-06-30", "e2")
intervals = db.execute("select valid_from, valid_to from memory_facts").fetchall()
assert all(row["valid_to"] is None or row["valid_from"] < row["valid_to"] for row in intervals)
episodes = (
"e1: Mira prefers concise answers. Her passport deadline is 2026-07-15.",
"e2: Mira corrected the deadline. It is now 2026-06-30.",
)
naive_match = next(episode for episode in episodes if "passport deadline" in episode)
assert naive_match.startswith("e1:")
replace_fact reject eerst een gelijke valid_from: voor dat conflict is application policy nodig, zoals source precedence of een user-confirmed revision, in plaats van een silent overwrite. Vervolgens zoekt het interval dat de incoming timestamp bevat. Als het er één vindt, sluit het die predecessor op de incoming boundary en geeft het de inserted row het eerdere einde van de predecessor. Als de timestamp vóór elk opgeslagen interval ligt, gebruikt het de volgende interval’s valid_from als het einde van de nieuwe row. Zo wordt een delayed fact vóór e1 [2026-05-30, 2026-06-01) en blijven e1 en de current e2 intact. De row factory maakt row["fact_id"] en named result fields geldig op de default connection die hier wordt aangemaakt. De partial unique index is de database guard voor één open row; een multi-writer deployment moet een database- en retry policy kiezen die bij de workload past. DM heeft geen equivalente update step, dus de oude tekst kan de correctie nog steeds overtreffen.
De assertions verifiëren de current e2 row, de historische e1 row, delayed insertion vóór e1, de interval invariant en de eerste matching naive text episode:
Naive text memory:
returned episode: e1 -> passport deadline is 2026-07-15
SGAM current state:
mira.passport_deadline = 2026-06-30
valid_from=2026-06-03T10:00:00Z, source=e2
SGAM point-in-time state:
on 2026-06-02, mira.passport_deadline = 2026-07-15
Combineer deze transaction in production met structured extraction op de write path. De database transaction werkt temporal validity bij. Het model extraheert een candidate fact, maar beslist niet welke opgeslagen row current blijft.
Storagekeuzes volgen uit het retrieval pattern
Projects gebruiken verschillende namen voor onderdelen van dit pattern: memory stores, context graphs, profiles, long-term stores, graph RAG en stateful agents.
| Tool of framework | Belangrijkste storage layer | Mechanisme voor temporal state | Schema-mechanisme | Praktische niche |
|---|---|---|---|---|
| Graphiti | Neo4j, FalkorDB en Amazon Neptune; Kuzu is deprecated | Fact validity intervals plus source-episode provenance | Pydantic entity- en edge-types, temporal edges, provenance | Self-hosted temporal graph memory |
| Zep | Proprietary Context Graph Engine | Managed temporal Context Graphs die changing facts behouden | Default en custom entity- en edge-types | Managed agent memory en governance |
| LangGraph / LangMem | LangGraph stores, Postgres-backed stores | Application-owned timestamps en fields in store records | JSON stores plus Pydantic profile- of collection extraction | Agent-apps die al op LangGraph zijn gebouwd |
| Mem0 | Managed stack, Valkey / Redis / vector backends in OSS-setups | Memory updates; temporal policy blijft application-owned | Memory types, custom categories, extraction prompts | User-, agent- en session memory als service |
| Letta / MemGPT | Database-backed agent state en memory blocks | Editable blocks zonder field-level validity intervals | Editable labeled memory blocks | Stateful agents met OS-style context management |
| Cognee | Graph plus vector- en relational backends | History hangt af van de ontology en de geselecteerde backend | Ontology-oriented extraction en validation | Enterprise knowledge graph memory |
| LlamaIndex property graph | Property graph stores plus vector stores | Time fields hangen af van het graph schema en de store | SchemaLLMPathExtractor met toegestane entities en relations | Graph extraction over documents en traces |
Graphiti is een concrete open-source implementation van relational, temporal memory. Het trackt facts terwijl ze veranderen, bewaart pointers naar source episodes en ondersteunt hybrid retrieval. LangGraph scheidt thread checkpoints van cross-thread stores. Mem0 verpakt memory operations als een managed service. Letta gebruikt editable context blocks in plaats van field-level SGAM, maar behandelt agent state nog steeds als persistent data.
Begin met het data model. Als exact fact lookup de belangrijkste operatie is, volstaat meestal een relational table met JSON payloads, validity columns, tenant indexes en een vector sidecar. Voeg een graph toe wanneer relationship traversal onderdeel is van het product, niet omdat de graph demo er indrukwekkend uitziet.
Bouw eerst de write path, daarna de graph
Bepaal eerst wat het product mag onthouden. De keuze tussen graph en vector komt later.
Een support agent kan account tier, open cases en durable contact preferences onthouden. Het moet niet elke gefrustreerde terzijde promoveren tot profile state. Een coding agent kan repo conventions en unresolved tasks onthouden. Het moet een private note niet voor altijd bewaren omdat die note toevallig één keer werd opgehaald.
Begin met de write path en behandel memory als een kleine state mutation:
- Geef het memory type, de subject, tenant scope en retention class een naam.
- Extraheer candidate records met structured output.
- Valideer de payload met Pydantic of de schema layer die je stack al gebruikt.
- Resolve conflicts vóór insert, inclusief de vraag of het nieuwe record een oud record supersedes.
- Bewaar een source pointer naar de raw episode, tool result, file, ticket of user confirmation die het record heeft opgeleverd.
- Schrijf de schema version met elk record weg, in plaats van die alleen in application code te laten staan.
De eerste SGAM store kan een relational table met een JSON column en enkele indexes zijn. Een graph wordt nuttig wanneer het product relationships moet traverseren, zoals customer-to-account, account-to-policy, task-to-artifact of project-to-decision.
Hot path en background writes
Immediate extraction is de moeite waard wanneer de volgende turn afhankelijk is van de nieuwe memory. Als de gebruiker zegt “onthoud dat ik korte antwoorden prefereer”, zou het systeem geen nightly job nodig moeten hebben voordat het zich anders gedraagt.
De meeste turns hebben geen immediate write nodig. Sla de raw episode op met tenant-, session- en tool-metadata en laat daarna een background worker candidates extraheren. Met recurrence-based consolidation buffert de worker weak signals en promoveert hij een fact pas nadat vergelijkbare evidence zich herhaalt of de user die bevestigt. Dit voegt freshness lag toe. Dat is acceptabel voor “de gebruiker vraagt vaak om CSV-exports” en riskant voor “de klant heeft het afleveradres gewijzigd.”
Houd de read path deterministic. Handhaaf tenant scope en validity eerst en gebruik daarna fuzzy retrieval alleen wanneer dat nuttige context kan toevoegen.
- Filter op tenant, memory type en validity window.
- Haal eerst exacte structured state op, vóór semantic neighbors.
- Gebruik vector- of graph-expansion voor supporting evidence, related entities en examples, niet als authority voor current facts.
- Stel de kleinste cited context samen die de vraag kan beantwoorden.
Behandel schema migration als een productwijziging, omdat die verandert wat de agent kan ophalen, citeren of verwijderen. Ze kan ook veranderen welke historical facts als current gelden. Plan migration scripts, backfills, dual-read windows en deletion behavior in dezelfde release.
Wanneer SGAM de complexiteit waard is
Gebruik SGAM wanneer facts door de tijd heen kunnen veranderen:
- user preferences die kunnen worden bijgewerkt of ingetrokken
- customer- of account-facts met audit requirements
- task state voor long-running assistants
- coding-agent project memory
- multi-agent shared state
- compliance notes waarbij provenance belangrijk is
- temporal questions zoals “wat geloofden we vóór de migration?”
SGAM is overkill wanneer memory short-lived, exploratory of goedkoop opnieuw te berekenen is. Als de agent slechts enkele turns aan continuity nodig heeft, zijn een checkpoint en trimmed message history voldoende. Voor static document QA heb je mogelijk alleen RAG nodig. En als het domain zo unsettled is dat het schema dagelijks verandert, zal typed memory het team vertragen.
Evaluation checklist
Evalueer de memory lifecycle én het uiteindelijke antwoord. Een systeem kan een plausibele response produceren nadat het het verkeerde fact heeft geschreven, een stale fact heeft opgehaald of een tenant boundary heeft overschreden.
Ik gebruik dezelfde stage-by-stage split als in mijn RAG evaluation article. Meet de stage waar een failure kan ontstaan, in plaats van evaluation te beperken tot de generated text. De trace discipline uit het agent evaluation article is hier ook van toepassing, omdat een memory bug vaak in de run history zichtbaar wordt voordat die het antwoord bereikt.
Ik zou SGAM met replay testen. Voer een fixed sequence van episodes in de memory writer in en inspecteer de ledger na elke betekenisvolle turn. Stel vervolgens current-state- en point-in-time-vragen aan de resulterende store.
| Layer | Failure waarnaar je zoekt | Measures |
|---|---|---|
| Write extraction | De agent miste een fact, verzon er een of produceerde een invalid shape | Schema-valid write rate, extraction precision/recall, source episode coverage |
| Conflict handling | Een stale fact bleef current of een geldig oud fact werd overschreven | Supersession correctness, duplicate rate, stale-fact invalidation correctness |
| Isolation en policy | Memory lekte tussen users of bleef bestaan na de policy window | Tenant isolation failures, deletion correctness, retention compliance |
| Read retrieval | Het juiste record bestaat, maar de reader haalde het niet op | Current-state accuracy, point-in-time accuracy, recall@k over memory records |
| Answer grounding | Het antwoord gebruikte memory zonder support of citeerde de verkeerde source | Claim support against source episodes, citation accuracy, conflict-resolution correctness |
| Operations | De memory path is te langzaam, te stale of te duur | p95 write latency, freshness lag, read latency, cost per query |
Benchmarks zoals LoCoMo, LongMemEval en ATM-Bench bieden public test cases. Ze vervangen geen domain test suite. Een coding assistant, customer support bot en compliance copilot hebben verschillende schemas, filters, retention rules en failure tests nodig.
Caveats
SGAM is mijn label voor een pattern, geen standard. Bestaande projecten verdelen het probleem anders. LangGraph memory en LangMem beschrijven short-term en long-term stores, profiles, collections, hot-path writes en background memory managers. Zep Graphiti gebruikt de term temporal Context Graph. Letta persisteert editable memory blocks, terwijl Mem0 een managed memory layer biedt. Microsoft GraphRAG, LlamaIndex property graphs en Cognee benaderen verwante onderdelen van het probleem als knowledge graphs.
Een user profile, episode log, document graph en agent-editable memory block lossen verschillende retrieval- en updateproblemen op. Ik reserveer SGAM voor durable memory die current application state representeert en daarom schema, validity, provenance, conflict handling, retention en migration nodig heeft.
Typed memory kan nog steeds verkeerd zijn. Een schema maakt bad writes eenvoudiger te inspecteren; het maakt ze niet trustworthy. Je hebt nog steeds source trust, user confirmation voor sensitive facts, conflict policy, deletion en monitoring nodig.
Schema migration is werk. Zodra memory state wordt, ben je verantwoordelijk voor versioning, backfills, old records en deletion behavior. Sla je dat werk over, dan overleven old records de semantics of retention policy waardoor ze zijn aangemaakt.
References
- According to Me: Long-Term Personalized Referential Memory QA - Paper van Mei et al. waarin ATM-Bench en Schema-Guided Memory worden geïntroduceerd.
- Towards Scalable Multi-Domain Conversational Agents: The Schema-Guided Dialogue Dataset - Paper van Rastogi et al. over de SGD-dataset.
- LongMemEval: Benchmarking Chat Assistants on Long-Term Interactive Memory - Benchmark van Wu et al. voor long-term memory abilities.
- Graphiti: Build Temporal Context Graphs for AI Agents
- Zep: A Temporal Knowledge Graph Architecture for Agent Memory
- Mem0 Platform Overview
- Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory
- LangGraph Memory Overview
- LangGraph Persistence
- LangMem documentation
- Letta: Introduction to Stateful Agents
- Microsoft GraphRAG documentation
- LlamaIndex: Using a Property Graph Index
- Cognee Documentation
- Pydantic model validation docs
- Python sqlite3 documentation