Sean Egan

Writing · 2026-09-27

A grounding doctrine for an agent's memory

How Bob's memory keeps a question from being recalled as an answer. Three rules enforced in code, and a test with no model judging the results.

Bob is a personal agent with a memory. Four of us talk to him every day, from wherever we are, and he's supposed to remember how each of us is doing and pass word between us. That makes his memory a safety problem in the plain sense: if he remembers wrong, he'll tell my husband something I didn't say.

For a while he did. The failures had a shape. Someone would say they'd started something and a week later Bob believed they'd finished it. Someone would ask a question and Bob would recall it as an answer. A guess became a fact. A hypothetical became a plan. None of these were hallucinations in the usual sense; every one was derived from something real. The problem was that the derivation lost the qualifier and kept the claim.

I called this derivation without provenance, and wrote three rules.

The invariants

Provenance or it isn't evidence. A memory that can't point at the turn it came from doesn't get used. Every fact carries its source, its author, and its time, and a nightly job rebuilds each person's "now" block (where they are, their health, what they're carrying, what's ahead) from the raw record with zero model calls, stamping each line with where it came from. An empty slot is shown as a dated gap. Silence in an always-present block must never look like calm.

Re-ground before you act. Retrieval is cheap and memory is stale. Before Bob does anything that matters on a remembered fact, he checks it against the record again.

Modality survives every hop. "Asked" is not "answered." "Suspected" is not "confirmed." "Reported by Derek" is not "true." "Wants to" is not "did." Each time a claim moves, from turn to fact to summary to reply, the qualifier moves with it, and a claim that arrives without one is treated as unknown, not as true.

These are enforced at the seams in code, not by asking the model to be careful.

The evaluation

The obvious way to test this is to have a model read the memories and judge whether they're faithful. The obvious way is wrong, because the thing you're testing is whether model-derived text preserved a distinction, and a model judge can lose the same distinction while judging. So the rule for the evaluation was: no model reachable from the verdict path.

The class evaluation authored 32 sealed scenarios, each pinned by hash. Twelve ways a qualifier can flip, two scenarios each: staged to done, asked to answered, suspected to confirmed, denied to asserted, wants-to to did, hypothetical to actual, reported to endorsed, someone's read of a thing to a fact about the thing, direction, partial to complete, past to present, and a negation that falls past a rendering cap. Plus eight inverse controls, where the change is real and the system must accept it.

The scenarios ran through the real nightly jobs. Verdicts came from a deterministic lexicon and the record, never from a model. Results: 0 leaks over 352 verdicts, 88 controls clean, delta 0 on re-run.

The completion gate, the one that's supposed to catch "started" becoming "done," is marked partially working in the record, and it's what I'm working on now. The tracker lists it as an open class with the vectors that could make it worse.

Why a personal agent needs this more than a coding agent

A coding agent's mistakes are caught by a compiler and a test suite. A personal agent's mistakes are caught by the person it's talking to, after the damage. The bar is higher and the tools are worse. The doctrine is what I had instead of a compiler.

What I'd take to a bigger system

Store the qualifier with the claim; make losing it a type error. Regenerate summaries from the record; never append to them. Show gaps as gaps. Test faithfulness with a judge that can't be fooled the same way as the thing being judged. And publish the gates that don't hold yet.

More writing