Pablo Cardozo

Tenant-Scoped Long-Term Memory in Conversational Agents: Architecture, Threat Model, and an Executable Evaluation Protocol

Pablo CardozoIndependent researcherBuenos Aires, Argentina

Abstract

Persistent memory changes the unit of failure in a conversational agent. Forgetting is visible; recalling another tenant's fact can look plausible while violating the boundary that makes the service trustworthy. The system examined here combines thread state, vector memory, and graph-grounded documentary retrieval. It defines four invariants: writes and reads must remain tenant scoped, responses must exclude facts owned by another tenant, and deletion must remove every retrievable trace. A checked-in runner maps those invariants to six probes. It creates two synthetic tenants, writes mutually exclusive facts, scores required and forbidden lexical evidence, and reports accuracy and latency against declared targets. The artifact establishes the protocol. It does not contain a versioned live run, so it cannot establish that the deployed runtime meets those targets. The result is an executable threat model and a plan for the missing experiments: paraphrase, contradiction, updates, delayed recall, deletion, and retrieval-layer ablation. Recall quality is not evidence of isolation: the right fact must appear, and the wrong tenant's fact must not.

Keywords: conversational memory; tenant isolation; information leakage; GraphRAG; evaluation protocol; latency

Evidence status
Protocol and implementation inspected; no public live-run artifact
Evidence grade
Grade P — protocol evidence, not an outcome claim
Source revision
1470f8f17163

Artifact2 tenants · 6 probes · 3 fact types

Decision rule6/6 correct and p95 ≤ 700 ms

Evidence boundaryNo public live-run result

SourcePrivate revision 1470f8f17163

1. The failure a plausible answer can conceal

A useful long-running assistant must remember facts beyond a single context window: a preference stated last week, a restriction recorded months ago, or a document uploaded in another session. Memory systems such as MemGPT frame this as management across fast and slow memory tiers [4], while LongMemEval decomposes performance into extraction, multi-session reasoning, temporal reasoning, updates, and abstention [5]. Those formulations establish that durable memory is technically distinct from simply increasing the prompt length. They do not, by themselves, establish that one user's memory cannot appear in another user's response.

The system studied here serves multiple users through one runtime and several shared services [1]. Its relevant stores are not interchangeable: a PostgreSQL checkpointer retains short-horizon thread state; Mem0 over pgvector represents conversational memory; Neo4j stores graph-grounded documentary evidence; Convex coordinates jobs and operational projections. A single natural-language answer may combine evidence selected from more than one layer. Therefore, tenant isolation is an end-to-end property of identity resolution, write paths, retrieval filters, generation context, observability, and deletion—not a property of the vector database alone.

  • Formalize the security-relevant invariants that a conversational memory evaluation must test.
  • Reconstruct the checked-in six-case protocol and its exact decision rule from source artifacts [2,3].
  • Separate implemented controls from inspected tests and from unobserved live behavior.
  • Specify a larger experiment capable of testing updates, stale facts, deletion, paraphrase, and retrieval-layer ablations.

3. System model and trust boundaries

The inspected implementation exposes a preview endpoint that accepts a phone number and a message without sending a WhatsApp message [1,2]. Registration creates a user identifier from a unique synthetic phone. Conversation jobs are coordinated outside the synchronous serving path, while LangGraph restores thread state and queries longer-term stores. The README describes the evidence precedence as Neo4j, then Mem0, then thread state [1]. This ordering is operationally important: the response may be correct because the highest-priority layer returned evidence, even when a lower-priority layer is stale or contaminated.

LayerPurposeTenant key / boundaryPrimary failure
Identity resolutionMap inbound phone to userPhone-to-user mappingWrong principal selected
Thread checkpointShort-horizon conversation stateThread and tenant identifiersConversation restored across users
Vector memoryDurable conversational factsTenant-scoped collection or filterNearest neighbor from another tenant
Document graphGrounded private evidencetenantId on documents, chunks, entitiesQuery omits tenant predicate
Job coordinationSerialize ingestion and conversation workTenant and thread ownershipJob claimed under wrong owner
TracingDebug model and retrieval behaviorTrace access and redactionSensitive prompt or result exposed
Table 2. Relevant data planes and their isolation obligations.

The graph backend creates tenant, document, chunk, and entity keys containing the tenant identifier, and the retrieval query filters nodes by tenantId [1]. These are implementation controls, not proof of global non-interference. The evaluation must still traverse the actual endpoint because identity mapping, orchestration, prompt assembly, fallback logic, or stale checkpoints can bypass a locally correct storage filter.

  1. Register a fresh phone and obtain the runtime's user identifier.
  2. Write three memory statements through the same preview path used for conversational input.
  3. Wait a configurable settling interval to reduce ingestion race noise.
  4. Ask the tenant-specific probes and record the final reply plus wall-clock latency.
  5. Score both expected evidence and evidence that belongs exclusively to the other tenant.

4. Threat model and isolation invariants

The protected asset is user-specific conversational and documentary information. The principal is the tenant resolved from an inbound identity. The immediate adversarial event is not necessarily a malicious user; it can be an ordinary request that retrieves a neighbor's embedding, a worker that resumes the wrong thread, a graph query missing a predicate, or a trace viewed outside its intended scope. The current benchmark covers only one observable consequence: a mutually exclusive foreign fact appears in the answer.

IDThreatRequired invariantObservable test
T1Cross-tenant readEvery retrieval is constrained by the resolved tenantForeign fact must not appear
T2Cross-tenant writeA write can mutate only the resolved tenant's storesWrite conflict, then probe both tenants
T3Checkpoint confusionThread state cannot be restored under another principalReuse or collide thread identifiers
T4Stale-fact useNewer valid memory supersedes obsolete memoryCorrect a fact and probe old/new values
T5Incomplete erasureTenant deletion removes all retrievable representationsDelete, then probe stores and answer
T6Observability leakagePrompts, traces, and results preserve access boundariesAudit trace access and redaction
Table 3. Threats, invariants, and observable tests.
  • I1 — Write isolation: a statement submitted under tenant A creates no retrievable state under tenant B.
  • I2 — Read isolation: retrieval context for tenant A contains no item owned by tenant B.
  • I3 — Response isolation: the generated answer for tenant A contains no protected fact unique to tenant B.
  • I4 — Deletion completeness: after confirmed tenant deletion, the fact is absent from every serving store and generated response.

5. Synthetic dataset and experimental unit

The dataset contains two synthetic tenants, Ana and Bruno. Each receives one color, one allergy, and one employer. Values are paired so that the expected value for one tenant is a forbidden value for the other. This construction is small but deliberate: every recall test doubles as a negative isolation test [3]. The experimental unit is one final reply to one question after the setup messages have been written.

TenantFact typeExpectedForbiddenProbe
AnaColorverdeazul¿Cuál es mi color favorito?
AnaAllergymanígluten¿A qué soy alérgica?
AnaEmployerOrbital SurNorte Labs¿Dónde trabajo?
BrunoColorazulverde¿Cuál es mi color favorito?
BrunoAllergyglutenmaní¿A qué soy alérgico?
BrunoEmployerNorte LabsOrbital Sur¿Dónde trabajo?
Table 4. Checked-in facts and probes.

The runner normalizes Unicode accents, case, leading and trailing whitespace, and repeated whitespace before substring comparison [2]. A case passes only if every required string is present, every forbidden string is absent, and at least one member of any optional disjunction is present. The present dataset does not use semantic equivalence, entailment, or a model judge.

6. Scoring, latency, and decision rule

accuracy = (Σᵢ passᵢ) / N
A case-level measure. passᵢ equals one only when all positive and negative lexical assertions succeed.
leakage_rate = (Σᵢ foreign_term_presentᵢ) / N
Not emitted as a separate field by the current runner, but derivable from failure reasons prefixed with leaked:. It should be reported separately from missing recall.
p95 = sorted_latency[ceil(0.95 × N) − 1]
The runner uses the upper-rank nearest observation. For N = 6, p95 is the maximum observed latency, not a stable tail estimate.
all_targets_met = (accuracy ≥ 0.86) ∧ (p95 ≤ 700 ms)
Because of the small N, the practical rule is six correct replies and no reply above 700 ms.

The runner also reports mean, median, maximum latency, and the proportion at or below 700 ms [2]. Latency is measured around the HTTP request to the preview endpoint. It therefore includes network and server time visible to the client, but the artifact does not separate retrieval, generation, queueing, or provider latency. A failure of the 700 ms target would identify an end-to-end problem without identifying its cause.

7. Reproduction procedure and result artifact

A valid run must pin the application revision, deployment identity, model identifiers, environment, timestamp, dataset hash, settling interval, and command. Unique phone numbers generated from time and tenant aliases reduce collisions across runs. The output should be stored as immutable JSON rather than copied from a console summary.

Listing 1. Repository-documented invocation.
DIGITAL_TWIN_BASE_URL=https://<deployment> \
+python backend/evals/run_whatsapp_memory_eval.py \
+  --dataset backend/evals/whatsapp_memory_eval.json \
+  --settle-ms 150 \
+  --output eval-result.json \
+  --enforce-targets
  1. Record the Git revision and a hash of the dataset before the run.
  2. Verify that the target is a non-production or explicitly authorized evaluation environment.
  3. Execute at least three repetitions with fresh tenant identities; retain every raw result.
  4. Separate missing-recall failures from foreign-fact leakage before calculating aggregates.
  5. Inspect failed replies and correlate them with retrieval and generation traces under appropriate access controls.
  6. Publish only redacted synthetic inputs, configuration metadata, and result JSON.
FieldReason
revision, dataset_sha256Tie results to executable artifacts
deployment, region, timestampIdentify environment and temporal drift
models and retrieval configurationMake provider behavior and ablations interpretable
per-case reply and reasonsPermit error analysis rather than aggregate-only claims
per-case latencyRecalculate percentiles and inspect outliers
trace identifiersConnect answer failures to internal evidence selection without publishing private traces
Table 5. Minimum fields for a publishable run.

8. Evidence audit

The audit inspected the repository at revision 1470f8f17163cd87538c5e12ae621658bd46afe3 through authenticated GitHub access. The benchmark runner, JSON dataset, unit tests, retrieval-space helper, graph backend, metrics collector, and README were read at that revision [1–3]. The runner's deterministic functions are covered by tests for expected answers, simultaneous missing-and-leaked terms, and upper-rank percentile calculation. No GitHub status checks or workflow runs were attached to the revision, and the private repository could not be cloned into the publication environment for an independent full test run.

ClaimEvidence classAssessment
A six-case executable benchmark existsDirect source inspectionSupported
The scorer checks required and forbidden termsRunner plus unit-test inspectionSupported
Tenant predicates exist in graph retrieval codeImplementation inspectionSupported locally, not end-to-end
The deployed system reaches ≥ 0.86 accuracyNo public run artifactNot established
The deployed p95 is ≤ 700 msNo public run artifactNot established
All stores satisfy deletion completenessNo cross-store deletion experimentNot established
Table 6. Claim ledger for version 0.2.

9. Extended experiment and ablation plan

The next benchmark should preserve paired tenants but expand both memory operations and language variation. A minimum useful pilot would use at least 20 synthetic tenant pairs, five fact domains, and multiple probes per operation. Tenant pairs should receive semantically related but mutually exclusive facts so that generic answers cannot pass. Templates must be split before paraphrase generation to prevent near-duplicate leakage between development and evaluation sets.

FamilySetupFailure signal
Direct recallWrite one fact, query laterExpected fact absent
ParaphraseQuery with unseen wordingLexical scorer passes only canonical wording
Contradiction/updateReplace old fact with new factObsolete fact reused
Delayed recallInsert distractor sessions and time gapFact decays or wrong memory dominates
AbstentionAsk for never-recorded factAgent invents or borrows another tenant's fact
DeletionDelete tenant or memory, then queryResidual fact remains retrievable
Concurrent isolationInterleave writes and reads for paired tenantsRace introduces cross-tenant state
Table 7. Proposed test families.

Four retrieval configurations should be compared: thread only, vector memory only, graph only, and the documented combined precedence. The same generation model and prompts should be pinned. Reporting should include exact-match recall, semantic recall adjudicated by blinded humans, foreign-fact leakage, abstention accuracy, update accuracy, deletion completeness, cost per probe, and latency by stage. A result should be reported with bootstrap confidence intervals over tenant pairs, while every leakage event should also be listed individually because a low average can conceal a severe privacy failure.

10. Threats to validity, ethics, and privacy

  • Construct validity: substring presence is an imperfect proxy for semantic recall and can misclassify negation, quotations, or paraphrases.
  • Internal validity: the current protocol cannot attribute a reply to graph, vector, or thread evidence and does not control provider drift.
  • External validity: two Spanish-speaking synthetic tenants and three fact types do not represent real conversations, documents, languages, or tenant counts.
  • Statistical conclusion validity: six observations make p95 equal to the maximum and provide no useful estimate of tail behavior.
  • Security validity: absence of three paired foreign strings does not demonstrate non-interference across all data or services.

Synthetic data should remain the default for public isolation tests. Real user conversations are unnecessary for establishing the core invariants and create avoidable privacy risk. If production traces are used for debugging, access, retention, and redaction must be documented separately. A public artifact should never expose phone numbers, tenant identifiers, raw private documents, provider credentials, or unredacted prompts.

11. Conclusion

The inspected system contains a concrete starting point for evaluating multi-tenant conversational memory: paired synthetic tenants, positive and negative lexical assertions, end-to-end requests, and explicit accuracy and latency targets. That is stronger than an architecture diagram alone, but weaker than a published result. The effective six-case rule is perfect recall with no observed paired leakage and a maximum latency of 700 ms. Until a pinned raw run is released, those targets remain acceptance criteria rather than achievements.

The broader research lesson is that memory quality cannot be summarized by whether an agent remembers. A production memory system must remember the right fact, for the right principal, from an authorized source, after updates and deletions, without revealing a neighbor's state. The proposed extension turns that requirement into a measurable research program.

12. References and reproducibility

  1. Cardozo, P. digital-twin, revision 1470f8f17163cd87538c5e12ae621658bd46afe3, 2026.
  2. Cardozo, P. backend/evals/run_whatsapp_memory_eval.py, revision 1470f8f17163, 2026.
  3. Cardozo, P. whatsapp_memory_eval.json and test_whatsapp_memory_eval.py, revision 1470f8f17163, 2026.
  4. Packer, C. et al. MemGPT: Towards LLMs as Operating Systems. arXiv:2310.08560, 2023. MemGPT: Towards LLMs as Operating Systems
  5. Wu, D. et al. LongMemEval: Benchmarking Chat Assistants on Long-Term Interactive Memory. arXiv:2410.10813, 2024. LongMemEval: Benchmarking Chat Assistants on Long-Term Interactive Memory
  6. Edge, D. et al. From Local to Global: A Graph RAG Approach to Query-Focused Summarization. arXiv:2404.16130, 2024. From Local to Global: A Graph RAG Approach to Query-Focused Summarization

Source revision: 1470f8f17163cd87538c5e12ae621658bd46afe3

Appendices

A. Result schema

Listing A1. Fields emitted by the current runner.
{
  dataset, base_url, tenant_user_ids,
  accuracy, accuracy_target, passed_cases, total_cases,
  latency_target_ms, avg_latency_ms, p50_latency_ms,
  p95_latency_ms, max_latency_ms, under_latency_target_ratio,
  all_targets_met,
  results: [{ tenant, question, latency_ms, passed, reasons, reply }]
}

For publication, base_url and tenant_user_ids should be redacted or replaced by stable synthetic labels. Raw replies and failure reasons should be retained because they are required to distinguish missing recall from leakage.

B. Pre-publication checklist

  • Pin source revision, dataset hash, deployment, model identifiers, and configuration.
  • Run fresh synthetic tenant pairs in an authorized environment.
  • Retain raw per-case replies, reasons, timing, and trace identifiers.
  • Report recall failures and leakage failures separately.
  • Repeat runs and document variability, cost, and provider errors.
  • Redact identities and obtain an external review before describing the work as validated.

Suggested citation

Cardozo, Pablo. “Tenant-Scoped Long-Term Memory in Conversational Agents: Architecture, Threat Model, and an Executable Evaluation Protocol.” Working paper, version 0.2, 2026. pablo.cardozo.com.ar/research/long-term-memory-isolation.