← Thamilvendhan Munirathinam

Recovering a poisoned agent memory

Most agent-memory tooling detects or prevents poisoning. Almost nothing recovers from it.

17 July 2026

An LLM agent's long-term memory can be poisoned: a malicious "fact" or a fake "successful experience" gets written once, and then quietly steers every future session. Deleting the obvious entry isn't enough — laundered copies and dormant triggers survive. So the real question is not can you stop the write (well studied) but can you clean a memory that is already poisoned, and prove it's clean?

memorywire now ships recover, and a companion benchmark, PurgeBench, that scores recovery.

Recovery purges untrusted-origin poison, quarantines a directive hidden in a trusted memory, and keeps benign facts
recover: purge untrusted-origin poison, quarantine directives hidden in trusted memories, keep the benign facts.

How recovery works

The strongest lever is provenance. Every memory carries a source (user, tool_result, web_page, …). Recovery purges memories from untrusted sources, quarantines trusted-source entries that read like an embedded directive (for a human to review, rather than deleting them), and optionally expires low-confidence rows. A --dry-run mode previews everything first; purges are restorable soft-deletes by default.

The evidence — PurgeBench

PurgeBench poisons a memory store with 30 adversarial entries across five classes (direct, laundered, entangled, dormant, procedural), applies a recovery procedure, and scores the result on Recovery-Completeness: RC = HarmonicMean(ER, UR) × RR over eradication, utility retention, and re-emergence resistance. Doing nothing and wiping the whole store both score zero by construction, so RC measures recovery quality, not cleanliness alone.

Recovery procedureRCERURRR
forget by provenance (memorywire)0.6400.800.800.80
forget flagged (naive)0.4290.900.500.67
expire low-confidence0.2090.400.750.40
OWASP Agent Memory Guard (content detectors)0.0360.230.750.10
do nothing0.0000.200.750.00
wipe everything0.0001.000.001.00

Three findings. Provenance wins — purging by untrusted source is the strongest lever. Content anomaly detection barely beats doing nothing on semantic poison (a plausible-sounding malicious fact isn't an "anomaly"). And the entangled class — a directive hidden inside a legitimate, trusted memory — defeats every automatic method, because removing it also destroys the benign fact it rides with. That is why recovery quarantines it for a human rather than deleting it, and it is the open research problem.

For semantic memory poisoning, provenance and rollback are the levers that work — not content anomaly detection.

Use it

Install from PyPI and clean a store from the command line:

pip install "memorywire[sqlite-vec]"
memorywire recover --agent my-agent --store sqlite-vec://./mem.db --dry-run

Or add it to any MCP agent (Claude Desktop, IDE assistants) — the agent then has remember / recall / forget / merge / expire / recover tools, no code:

pip install "memorywire[mcp,sqlite-vec]"
{ "mcpServers": { "memorywire": { "command": "memorywire-mcp",
    "env": { "MEMORYWIRE_STORE": "sqlite-vec://./mem.db",
             "MEMORYWIRE_AGENT": "assistant" } } } }

Links