You found the poisoned memory. Now remove it
TL;DR
- A fact written into agent memory rarely lives in one place. It can exist as a record, an embedding, an extracted summary, a graph edge, a cached answer, and a copy in another agent's store. A delete that reaches one of those is still called a delete.
- OWASP named memory poisoning as its own risk in December 2025, and its mitigation list asks for snapshots, rollback and quarantine. The standard treats safe removal as something a team must build, not as a property memory already has.
- Across eleven systems read at pinned commits and dated documentation, none of the reviewed source sets establishes a delete that reaches every derived artifact and records who performed it. Four establish part of it, and this piece names which part.
- The strongest failure found was not a vector database and not a backup. It was a cache: graph and vector stores verified empty, and stored answers still asserting the deleted facts.
Memory poisoning is an attack that writes malicious content into an agent's persistent memory so that it steers behaviour in later, unrelated sessions. It has a name in the standards now and a fast-moving research literature. Of the work read for this piece, most of the papers stop at the moment of discovery.
The question after discovery is not subtle. You found the poisoned entry. You know which record caused it. Now remove it.
That is where the abstraction breaks. A delete button removes a row, an edge, a document, or a file. An agent does not run on rows. It runs on what was derived from them.
The question is no longer whether a delete endpoint exists. It is what remains after that endpoint succeeds.
Here is the falsifiable version of the claim, so it can be argued with. Name one agent memory system, installable or purchasable today at a version you can pin, whose own documentation states what a delete does to every artifact derived from the deleted record, and records who performed it. Reading eleven of them, I could not find one.
This is a dated source review, not an execution benchmark. Nothing was run. Claims come from primary documentation and from source read at the commits cited, on 2026-09-12, and every negative is scoped to those sources. "Not established" means the reviewed sources do not answer the question, not that the capability cannot exist. To reproduce the review against your own vendor, take the six questions below, the read date, and the commits in the table, and ask them of the docs and code you can pin. Eleven systems appear below; Mem0 appears twice, as the open-source package and the hosted platform, which is why the table has twelve rows.
OWASP ASI06 names the problem, not the cleanup contract
OWASP's versioned document is titled "OWASP Top 10 For Agentic Applications 2026" and labelled Version 2026, December 2025, on its cover. ASI06, "Memory & Context Poisoning," runs from page 24, as numbered in the document, of the PDF, which is reachable through a download link embedded in its resource page.
Its listed examples include poisoning of retrieval stores and embeddings, contamination of shared user context, drift in long-term memory, and cross-agent propagation as an item of its own. Its prevention list asks for validation before commit, segmentation, expiry of unverified memory and, in item seven, "snapshots/rollback and version control" plus support for "rollback/quarantine for suspected poisoning."
Read that carefully. The standard treats rollback as engineering work the team owes. It does not claim persistent memory gives you safe removal.
Note also what ASI06 does not contain: a single attack-success percentage. The figures that circulate as "OWASP says" come from the primary literature, not from the standard: of the three papers below, only AgentPoison is in the ASI06 reference list, and one of the other two postdates the document. They also measure different things.
| Paper | Write or retrieval success | Behaviour or impact success |
|---|---|---|
| AgentPoison (arXiv:2407.12784, NeurIPS 2024) | 81.2 percent, retrieval metric | 59.4 and 62.6 percent |
| Memory injection via query-only interaction, MINJA (arXiv:2503.03704) | 98.2 percent write | 76.8 percent average |
| Hidden in Memory: sleeper memory poisoning (arXiv:2605.15338) | up to 99.8 percent storage | between 60 and 89 percent among successful retrievals, by the paper's own behaviour measure |
Secondary sources round MINJA's figures down to over 95 and 70 percent; the table uses the paper's own averages.
Write success is not impact success, and cleanup success is a third measurement again. These are different threat models, not interchangeable measures of harm. Every "OWASP says 99.8 percent" circulating online is a chain of retellings: the number comes from a paper, not from the standard, and it counts writes, not harm. Collapsing the three is how a deletion guarantee becomes untrue.
Where a deleted fact still lives
One fact can occupy five places at once.
- The primary record: the row, document, or memory object.
- Its embedding in a vector index.
- Anything extracted from it: a summary, an entity, a graph edge, a consolidated memory record.
- A cached answer that used it.
- A copy in another agent's store, if memory is shared. Shared access to one record is not the same thing as independent copies of it, and the table below keeps the two apart.
Think of a fact as a dependency chain rather than a row. Deleting the record deletes the record. Everything above is a separate question, and the honest starting point is that most products do not answer it in public.
The literature has started to. A 2026 survey of long-term memory security gives "forget and rollback" its own lifecycle phase, observes that deleting the visible entry can leave residues in compressed summaries, retrieval indices and propagated copies, and reports that defences in that phase remain comparatively sparse (arXiv:2604.16548). MemSecBench built a write, execute and forget protocol over 310 cases: among successfully poisoned cases, selective repair succeeds in 56.1 percent, with a 41.3 percentage-point spread between backend stacks (arXiv:2607.27080).
MEMOREPAIR shows what a principled cascade looks like, and shows its price. It reports zero invalidated-memory exposure, conditional on "complete influence provenance," and its own limitations section reports that dropping one percent of influence edges yields 17.7 percent leakage, an amplification the paper puts at about eighteen times (arXiv:2605.07242). That conditional is the whole distance between a paper result and a product guarantee.
Six deletion questions, eleven agent memory systems
For each system: does a delete exist, what does it touch, does it cascade into derived records, is it reversible, is there an audit trail naming the actor, and what happens to copies and shared scope. "Silent" means the primary documentation does not say and the answer cannot be settled from public evidence. A "no" means not documented in the source read, not impossible in the vendor's private system. Where a commit is named, that is what was read.
| System | Delete exists | Reaches derived records | Reversible | Actor recorded | Copies and scope |
|---|---|---|---|---|---|
| AWS Bedrock AgentCore Memory | DeleteEvent, DeleteMemoryRecord | No, and documented: deleting an event leaves the derived long-term record. Events expire within a configurable window up to 365 days; derived records have no documented expiry | DeleteMemoryRecord is permanent | Not stated on the memory delete pages; CloudTrail data events are off by default | Namespaces without {sessionId} share across sessions by design |
| OpenAI ChatGPT Saved Memories | In-app only | Incomplete both ways: deleting a chat leaves the memories derived from it, deleting a memory leaves its mentions in chats already generated | No restore documented | A log of a deleted memory may persist 30 days. The enterprise Compliance Platform documents removal from production indexes; the consumer flow does not | Memories live apart from chats |
| Google Vertex AI Memory Bank | memories.delete, returns a long-running operation | silent | silent | Cloud Logging is named as unsupported for this resource | silent |
Mem0, OSS (commit c7ee362) | DELETE /memories/{id}, a synchronous physical vector delete | Entity-store cleanup runs only if that store was already initialised in the process: the check reads self._entity_store is None instead of the lazy property. Graph memory was removed from the OSS SDK | No restore. An update overwrites in place; the old text survives only as a history string | Append-only SQLite history with an actor column | Separate records per user and agent |
| Mem0, Platform | DELETE /v1/memories/{id} with delete_linked | Reports a cascade_count; what "linked" means and what happens to graph nodes and edges is undocumented | No | History endpoint documented without an actor field | silent |
| Zep Cloud | REST endpoints for edges, episodes and users. Its official MCP server (tools.go) exposes thirteen tools, none of which deletes | Deleting a thread removes its episodes and cascades only to edges and nodes that no other episode contributed; the user entity node is never deleted | Edge invalidation exists and survives episode deletion; node delete is documented as permanent and cascades to the node's edges | Audit logs cover the web application only, not API or SDK calls; API logging records endpoint, key and time | One context graph per user; entities mentioned by other episodes survive |
| Graphiti (Apache-2.0) | remove_episode hard-deletes | Selective: edges created solely by the episode, and entities left with one mention. Its MCP delete_episode was a shallow node delete for a period; fixed in v0.29.2, 2026-06-08 | Temporal invalidation fields alongside Cypher DELETE; the hard path is not reversible | None built in | Shared graph; nodes mentioned by other episodes survive |
| Letta, current product (MemFS) | No documented purge | All context, memory blocks included, is tracked in git; every edit is a commit | History is navigable, and no documented mechanism rewrites it. The retired V1 server hard-deleted archival passages and cascaded shared blocks with a foreign key | Git commit history; the V1 block_history table carried an actor, passages did not | silent for MemFS |
Cognee (main c0d18c80) | Unified forget() | Dataset deletion is provenance-scoped over graph and vector stores, plus session-cache invalidation since August 2026. The per-item hard mode, in the routine the code itself calls legacy, removes entity nodes left with exactly one edge | The separate provenance ledger has a tombstone-style invalidate(); prune_system(metadata=True) erases its own audit row | A pipeline_runs row records that forget ran and by whom, not which items | Dataset provenance; shared entities survive |
| Hindsight (Vectorize) | PATCH invalidate and DELETE document, separately | Document erase removes the document, every unit extracted from it and their links; an asynchronous self-heal re-fills neighbours, v0.7.0, 2026-05-27 | Reversible curation since v0.8.2, 2026-06-12; document delete cannot be undone | A reason field on invalidation; no actor field | Banks isolated; copies and backups unpublished |
| Supermemory | DELETE, plus an isForgotten flag | The engine is not in the public repository, so what a delete physically does is unsettled | The forgotten flag is reversible curation; DELETE is documented as permanent | Not in the public source | Unsettled from primary evidence |
LangGraph store and LangMem (commit 11ee185) | delete(namespace, key) | The Postgres store's store_vectors table declares a foreign key with ON DELETE CASCADE, so the embedding goes with the record, enforced by the database | No | None in the default in-memory store | Designed to be shared across threads |
Three shapes of failure, each one dated
The cascade documented not to cascade. AWS Bedrock AgentCore's developer guide states that deleting an event does not remove the structured information derived out of it in long-term memory. Raw events carry a configurable expiry up to 365 days. The derived records carry no documented expiry at all. A derived fact can outlive its source, by design, and the design is written down.
A real cascade with a narrow rule. Cognee's per-item hard delete removes entity nodes that have exactly one remaining edge; an entity with more edges does not qualify. That is the routine the code itself calls legacy, and it should not be mistaken for the whole product: dataset deletion runs a separate, provenance-scoped path. The rule is defensible, because a shared entity should not vanish when one source goes. It is also something you only learn by reading the delete path.
The audit that skips the channel you delete through. Zep documents that its audit logs track member actions in the web application only, and that API and SDK calls are not included. An erasure request executed through the API is precisely the event that leaves no audit entry. Separate API logging records that an endpoint was hit, by which key and when, which is useful evidence and not an artifact-level deletion receipt.
The layer most often missed is the cache
The strongest evidence in this review is not a vector store and not a backup. It is Cognee issue #4030, whose title states the finding in full: a session cache makes completions assert hard-deleted data, and stale replay survives a hard delete even with an empty graph. Graph and vector stores were verified empty. Zero nodes, zero edges. The answers kept coming.
Two fixes for that mechanism merged on 21 August and 27 August 2026. The issue was still open when this was written; the merged code is what counts, and an open ticket does not negate that history.
A blog post from 6 July 2026 reported the same symptom and blamed surviving graph nodes. The bug report pinned a version, checked both stores, and named the cache. Use the bug report. The difference is not academic: harden the graph and you will have fixed the wrong layer. The engineering requirement follows directly: test the warm session, not only the empty index.
This also explains why deletion does not reduce to vector-store mechanics. Qdrant marks a point deleted with a bitmask and excludes it from results immediately, with physical removal deferred to a vacuum. Weaviate tombstones an object, hides it from future queries, and cleans the index asynchronously. pgvector rides Postgres MVCC and warns that vacuuming an HNSW index can take a while. Pinecone documents eventual consistency and gives you a sequence number to check against. A 2026 preprint claims soft-deleted embeddings remain reconstructible from HNSW stores (arXiv:2606.18497); it is unreviewed, its own comments field says it is prepared for submission, and it does not name the implementations tested. Read alongside the vendor documentation above, it speaks to what remains on disk before cleanup, not to what a query returns. Treat it as storage forensics, not as evidence that these databases return deleted vectors in normal search. The problem this article is about lives above the vector store: in derived records, summaries and caches that the application, not the database, has to clean.
Invalidation is not erasure
Two operations are on the table, and products name them inconsistently. Invalidation excludes a fact from recall, keeps it for audit, and can be reversed. Erasure destroys the fact and cannot be undone. Both are legitimate. Treating one as the other is how an answer to a data-subject request becomes false. Note what erasure does not preclude: a deletion receipt, recording that something was removed, by whom and when, can remain without retaining the erased fact. Erasure and audit are not in conflict; only the shape of the audit changes.
Graphiti carries the distinction cleanly. Contradicted facts are marked with validity fields rather than removed, and a separate path hard-deletes edges and nodes outright. Its MCP tool once bypassed the cascading delete for a shallow node delete; that was fixed and shipped in v0.29.2 on 8 June 2026. The core library's cascade was already correct, the bug lived in the wrapper, and calling it an outstanding core defect would be wrong. Fairness cuts both ways here.
Hindsight documents the split most explicitly of anything read here: a reversible curation path that prunes links and recomputes derived observations without the retired fact, and a separate document erase that removes the document, every memory unit extracted from it, and their links, with no recovery. Its changelog names erasure work directly. All of that is the vendor's own documentation, and it still records a reason but no actor on an invalidation, and publishes nothing about backups or copies in other banks.
Letta's current architecture is the trade-off at its purest. Memory, blocks included, is tracked in a git repository. The history is complete and navigable, and no documented mechanism purges it. Complete version history in one design, and no documented erasure. A version history is not the same thing as a tamper-resistant audit trail, but it answers the question of what changed and when better than most delete endpoints do.
"Just rebuild the derived state" has a measured cost
The obvious retort is that derived artifacts are cheap. Summaries and embeddings regenerate from surviving sources, so the real problem is provenance, not deletion.
The one paper that proves a lower bound on the cost disagrees about "cheap." Forgetting Without Restarting shows that exact unlearning of a fact injected at step τ of a trajectory of length T requires at least T−τ+1 recomputed transitions (arXiv:2609.04875). The earlier the fact entered, the more of the trajectory you pay for.
Among shipping products, Cognee comes closest and does it bluntly: a memory-only forget resets the dataset's pipeline status, so the next run reprocesses from scratch rather than repairing the affected subgraph. Targeted recomputation after a deletion remains a research proposal.
What GDPR Article 17 actually requires
Article 17(1) gives a right to erasure without undue delay on six grounds. Article 17(2) is the closest thing in Article 17 to a cascade duty, and it is narrower than most summaries imply: it applies where the controller has made the data public, and it requires reasonable steps to inform other controllers processing it. Article 17(3) lists five exceptions. Article 19 adds a duty to notify each recipient of the data about an erasure unless that proves impossible or disproportionate; it is a notice, not a cascade. The text is on EUR-Lex as CELEX 32016R0679, OJ L 119, 4.5.2016. That the regulation does not prescribe an unconditional technical cascade is not permission to retain what the data subject asked you to erase; it means the obligation attaches to the controller's own processing, which is where the derived records live.
Guidance reaches models, not memory stores. EDPB Opinion 28/2024, adopted 17 December 2024, holds that models trained on personal data cannot in all cases be considered anonymous, on a case-by-case test. The ICO's consultation response on engineering individual rights into generative AI says output filters may not be sufficient because they do not remove the data from the model, and that organisations must have mechanisms covering the trained model itself. CNIL's recommendations on AI system development say that, by default, exercising those rights over a model requires retraining it, provided the training data is still held.
One correction, since this piece is partly about unverified claims. The line "the ICO says embeddings remain personal data" circulates widely and does not trace to any ICO document. The word does not appear in the ICO page it is attributed to.
No regulator decision yet addresses removal from an agent's runtime memory: the embeddings, summaries, edges, caches and shared copies of a single fact. Clearview concerned biometric templates in a matching database, which is an instructive analogy and not a precedent. None of this is legal advice; it is what the texts say.
Where we stand
One honest paragraph about our own choice, since this piece argues that vendors should publish theirs. Mnemoverse withdrew deletion from the agent-facing surface: the two delete tools left the memory package in 0.9.0, and deletion is now an administrative operation only. The recommended correction is to write a new memory that supersedes the old one, which keeps the superseded revision fetchable and the chain readable. The reason is published in our own MCP server page and API reference: an earlier post-delete sweep destroyed learned cross-atom associations across a tenant, and it was removed. So is the cost. A superseded revision is still a stored row and still counts against a plan's limit, and the read-side filter that hides a replaced revision is deployed but not yet switched on. That is a position with a bill attached, and both halves belong in public.
Two actors, two rights, one door
Ask six questions before trusting a delete. What object does it remove. Does it reach the embeddings, summaries, extracted records and edges derived from that object. Does it invalidate cached answers built on it. Is it reversible, or is it final. Who is recorded as having done it, and can that record itself be removed. Where did the copies go, across sessions, agents, banks and backups. And one design question beside the six: is a hard delete among the tools the model itself can call.
None of the reviewed source sets establishes the complete contract. Four establish part. Hindsight documents the invalidate and erase split. Cognee ships provenance-scoped graph deletion and, since August, cache invalidation. LangGraph's Postgres backend gets the record-to-vector cascade right at the database layer, enforced by a foreign key rather than by application code. OpenAI documents index removal and an audit trail in its enterprise compliance surface, though not in the consumer memory flow.
The last problem is not storage. It is authority. An agent must not be able to destroy the record of what it did, because whoever controls the agent's input then controls that power too. An operator must be able to erase, because the law can require it. Those are two different actors with two different rights, and many systems put one door in front of both.
Sources
- OWASP Top 10 for Agentic Applications 2026, Version 2026 (December 2025), ASI06 Memory and Context Poisoning: resource page, PDF
- Survey on long-term memory security in LLM agents: arXiv:2604.16548
- MemSecBench: arXiv:2607.27080 · MEMOREPAIR: arXiv:2605.07242 · Forgetting Without Restarting: arXiv:2609.04875
- AgentPoison: arXiv:2407.12784 · MINJA: arXiv:2503.03704 · Hidden in Memory: arXiv:2605.15338 · Ghost Vectors: arXiv:2606.18497
- AWS Bedrock AgentCore: delete an event, DeleteMemoryRecord
- Zep: deleting data from the graph, audit logging
- Cognee issue #4030 and pull requests #4585, #4652
- Graphiti release v0.29.2
- Hindsight changelog: v0.7.0, v0.8.2
- GDPR Article 17: EUR-Lex CELEX 32016R0679
Read at, 2026-09-12: Mem0 OSS at commit c7ee362; Zep's MCP server at commit 495bf72; Cognee main at commit c0d18c80; LangGraph at commit 11ee185; Graphiti core as served on 2026-09-11; every vendor documentation page as rendered on the read date. Where a vendor page changes after that date, the claim here is about the page as it was.
Common questions
What does deleting a memory actually remove in an agent system? It depends on the system, and most documentation does not say. Where a delete endpoint exists, it removes the target it names; whether the embedding goes with it is documented by Mem0 and LangGraph and left unsaid by several others. Few systems document what happens to summaries, extracted records, graph edges, cached answers, or copies held by other agents. AWS Bedrock AgentCore states the boundary outright: deleting a raw event does not remove the structured information derived out of it in long-term memory.
Is agent memory deletion reversible? Two operations are on offer and they are often confused. An invalidation keeps the fact, excludes it from recall, and can be undone. An erasure destroys it and cannot. Graphiti and Hindsight document both paths separately. Zep, Cognee, Supermemory and Letta document some retained or reversible state; AWS, OpenAI, Mem0 and LangGraph document a hard delete only; Google's pages are silent.
Do agent memory systems clear cached answers after a deletion? Few of the reviewed systems document it, and it is the most overlooked residue. A bug filed against Cognee's own repository shows the graph and vector stores verified empty after a hard delete, zero nodes and zero edges, while a session-scoped cache kept asserting the deleted facts. Two fixes for that mechanism merged in August 2026, and the issue was still open when this was written.
Does GDPR Article 17 require deleting derived data such as embeddings? Article 17(1) gives a right to erasure on six grounds. Article 17(2) adds a duty to inform other controllers, but only where the controller made the data public, so it is narrower than many summaries suggest. In the sources reviewed, no regulator decision yet addresses an agent memory store. The ICO has said output filters may not be sufficient because they do not remove the data from the model, and CNIL has said that by default exercising those rights over a model requires retraining it.
Which agent memory system has the most complete deletion story? On these six questions, Hindsight documents the most, with a reversible curation path, a separate irreversible document erase, and a changelog that names erasure work explicitly. That is the vendor's own documentation, and it still records no actor on an invalidation and publishes nothing on backups or cross-bank copies. None of the reviewed source sets establishes the complete contract.
Related
- Agent Memory Deduplication: The Missing Error Rate
- Stale Memory Is Worse Than No Memory
- Memory Poisoning: The Patient Path to Your API Keys
- Shared Memory Poisoning: One Bad Write, Many Agents
- Provenance in Agent Memory: The Missing Who
- Bitemporal Memory for AI Agents: The Missing Axis
- Mem0 vs Zep vs Letta vs Cognee vs Supermemory, Q3 2026
- AI Agent Memory: What It Is
