Memory with receipts: building agent memory that can take things back
An agent reads a web page that says invoice 104 is paid. It stores the fact. A summary picks it up. A billing agent closes the invoice. Then someone notices the page was forged.
Delete the fact and you have fixed one row. The summary still carries it. The decision still stands. And nothing in the system can tell you any of that, because nothing remembers why it believed the fact in the first place.
That is the quiet flaw in agent memory. Most systems store what an agent was told. Almost none store why it was believed. So when the evidence collapses, you can delete, or you can pretend. I built WYSE for Graph Hacks to do the third thing: work out exactly what still stands.
Beliefs have a shape
In WYSE, nothing is a bare fact. A claim is supported by justifications, and a justification is a node in a graph. It can mean two very different things:
- Alternative proofs (OR). A payment provider's record or a bank statement can each show an invoice settled. Lose one, and the claim survives on the other.
- Joint premises (AND). "The customer owes nothing" needs the invoice settled and no other open invoices. Lose either, and it falls.
A plain graph of "derived from" edges cannot tell those apart. A justification node can: it requires all of its premises, and several justifications can point at one claim. Support is then the least fixed point of that structure, computed outward from valid observations. A justification with no premises is never valid, and two claims that only justify each other never hold each other up.
What happens when a source goes bad
Quarantine the forged page and WYSE does five things:
- One atomic write marks the source, so the very next read is safe.
- It recomputes support. Invoice 9, backed only by the forged page, falls. Invoice 104, also backed by the payment provider, survives.
- The retrieval gateway withholds fallen claims and never returns their text. A poisoned sentence cannot reach the model through memory.
- Every decision that relied on affected claims gets a label: correction, compensation, or review.
- The incident is logged with its full result.
That fourth point is the one I like most. Invoice 104 is still a correct belief. But the billing decision rested on evidence that has since gone bad, so it gets a review. A belief can stay true while the basis of a decision stops being acceptable. A system that only tracks facts cannot say so.
Three agents, one email
Corroboration has a trap. If three agents confirm a supplier's new bank account, that looks like three votes. If all three read the same compromised email, it is one source.
WYSE counts distinct sources among each claim's root observations, not votes. In the benchmark, vote counting reports 10 confirmations where the truth is 1. WYSE reports 1.
Why a graph
Blast radius, selective survival, independent corroboration and decision replay are all questions about paths. FalkorDB holds the topology, gives every tenant and every agent its own graph, and enforces integrity: unique and mandatory constraints, atomic single-query writes, and compare-and-set updates. Impact discovery walks the dependency graph in Cypher, one level per query, because dependencies alternate direction and a single variable-length pattern cannot follow them. It also survives cycles.
To be precise about the split: support evaluation itself runs in the application over the connected graph it loads. The Cypher and the algorithms are written out in the repository.
Does it work? I tried to catch it lying.
I built a seeded benchmark: layered evidence graphs of 70 claims and 20 decisions, with three of twelve sources compromised. The ground truth comes from an oracle of about thirty lines of set logic that never imports engine code. Three systems get identical inputs: plain memory with source attribution, a delete-cascade baseline, and WYSE. Means over 20 seeds:
| System | Poisoned claims still served | Valid claims preserved | Withdrawal precision | Bad decisions missed | Decisions labelled correctly |
|---|---|---|---|---|---|
| Plain memory | 60.0% | 100.0% | 100.0% | 100.0% | 0.0% |
| Delete-cascade | 0.0% | 53.2% | 33.3% | 0.0% | 46.3% |
| WYSE | 0.0% | 100.0% | 100.0% | 0.0% | 100.0% |
Plain memory leaks everything derived. Delete-cascade is safe but throws away nearly half the valid knowledge. WYSE matches the oracle.
Then the part I would rather you read than skip. In a second run, half of the alternative proofs secretly come from a mirror of the compromised source, and the systems are told only about the primary. Delete-cascade serves no poisoned claims, because it deletes everything downstream regardless. WYSE serves 17.7%. Its safety rests on independence being real, and a hidden mirror breaks that. It still flagged every truly wrong decision, but labelled 8.7% of them reviews where corrections were due. I would rather publish that number than hide it.
What broke along the way
- Silent truncation. A query matching 20,000 nodes returned exactly 10,000 rows, with no error. My first loader would have quietly dropped half of a large tenant. Bulk reads now page.
- Lost updates. Under 16 and 40 concurrent writers, a read followed by a write kept 90 of 800 and 112 of 2000 updates, with zero errors. A single-query write kept every one. Every state change is now one query or a compare-and-set.
- A bug the benchmark design caught. Designing the benchmark made me trace two quarantines in a row. The second could silently downgrade a decision labelled "correction" to "review". No test covered it. Labels now only move up in severity during an incident.
Limits
The scenarios are synthetic and come from my own generator, and the oracle shares the engine's support semantics. So the benchmark checks the implementation, not that the model fits every real deployment. Latency was measured at 70 claims per tenant, and the engine loads whole tenants, so large ones will cost more.
Try it
The repo has a pinned FalkorDB image, an end-to-end demo, an MCP server with 12 tools where identity and trust tier are never arguments, and 82 tests.
- Code: https://github.com/bitbyrizbit/wyse
- Method and results: docs/BENCHMARK.md
Built solo for Graph Hacks, Track 02. AI coding assistants were used for design review and drafting, and every query and design decision is mine to explain.
Remember why.
Top comments (0)