Not All Memories Are Equal
Author: Claude Code
Note: I asked Claude Code to explain what we worked through, so that I have a record of how things work in late 2026. Newer versions of the Claude Code software may have fixed this gap.
Every session, my coding assistant — Claude Code — reads a little file that says things like "prefer plain language" and "never hardcode that path." It's a good feature. It's also, it turns out, built very differently from how Anthropic's own API does the same job, and the difference explains a real incident where the assistant confidently gave me wrong advice while quoting its own memory as the reason. This post is the ELI5 version of what I learned chasing that down, what I built in response, and why what I built barely moves the needle.
The bouncer and the guest list
Think of "memory" here as a notebook the assistant keeps between conversations. It writes itself little notes — "the user prefers X," "don't do Y, it broke once" — and reads them back later so it doesn't have to be told the same thing twice.
The notebook has two parts. There's a one-line summary of every note, all in one place, and there's the note itself, which is longer and has the actual details and caveats. Picture a bouncer holding a clipboard: the clipboard has one line per person ("Mitchell — regular, fine"), and there's a fuller file back in the office with the actual story if anyone wants to look. The bouncer reads the clipboard every single time, because that's fast. Nobody walks back to the office to check the full file unless something feels off.
That's the whole story, and it's also the whole problem. The clipboard line is short by necessity, so it drops nuance — and once it's dropped, nothing forces anyone to notice.
Two different plumbing systems
Here's the part I didn't expect: Claude Code and Anthropic's own developer API solve "give the model memory" in architecturally opposite ways.
Claude Code's version — the one I use every day — loads every single headline, every single session, whether or not it's relevant to what I'm doing right now. It's a broadcast: the clipboard gets read out loud in full, every time, regardless of who's actually walking through the door tonight.
The API offers something different: a dedicated memory tool, launched in beta in September 2025, where the model itself decides when to look something up and calls a specific command — view, in effect — to pull one file, on demand, only when it judges that file relevant right now (Monigatti, "Exploring Anthropic's Memory Tool"; Anthropic, "Managing context on the Claude Developer Platform"). Paired with a context editing feature that prunes stale material out of the conversation automatically, Anthropic reports a 39% performance improvement and an 84% reduction in token use on long-running tasks, compared to no context management at all (Anthropic, "Managing context"). In April 2026, Anthropic extended the same idea to hosted agents with per-write audit logs — a record of who wrote what, when, and why — under "Memory for Managed Agents" (Wire, "Anthropic's Managed Agents memory: what it changes").
Same goal — give the model continuity across sessions — two opposite shapes. One is a full broadcast with no relevance filter; the other is a targeted, audited, on-demand fetch.
Why the plumbing choice actually matters
Here's where it stopped being trivia. In a past session, the assistant told me a project file should be flagged for cleanup, citing "your standing preference" from memory. The preference was real — but the memory's full body carried an exception for exactly that file, recorded months earlier when someone had already checked and decided it should stay. The clipboard line didn't mention the exception. The assistant read the clipboard, not the file in the back office, and got it wrong with total confidence.
That's not a one-off glitch; it's what the broadcast architecture guarantees will eventually happen. A claim that's true when written can quietly become false, incomplete, or superseded — a store gets retired, a policy changes, an exception gets carved out — and nothing about the clipboard line changes to reflect it. The short summary still reads as settled, because nothing ever forced it to say otherwise. Worse: because the assistant is the only thing that ever writes these notes, a distinction that matters enormously — "I was told this" versus "I concluded this and nobody objected" — has no place to be recorded at all. Silence gets filed as agreement.
Anthropic's own engineering writing calls the underlying discipline "context engineering," and names compaction, tool-result clearing, and structured note-taking as the antidotes — the common thread being that an agent should keep its working context small, relevant, and periodically refreshed rather than accumulating everything forever (Anthropic, "Effective context engineering for AI agents"). Claude Code's memory feature, as it exists in my setup, does none of that pruning — it accumulates, and it broadcasts the accumulation whole.
What I built to cope
I don't have access to redesign Claude Code's plumbing, so I built three layers of governance on top of it, each catching a different slice of the problem:
memory_guard.py— checks a memory file the instant it's written, before it hits disk, and rejects it if its filename and its internal "name" field don't match. Sounds pedantic; it isn't. Loose naming is exactly what breaks the internal cross-references between notes, silently.memory_report.py— runs once at the start of every session and sweeps every stored memory for drift: broken cross-references, dead file paths that a memory still claims are valid, orphaned index entries. Silent when everything's clean, so it only ever costs attention when there's something to see.memory-pollution-auditor— the newest piece, an on-demand deep audit. Instead of just checking that a memory is filed correctly, it checks whether what the memory says is still true — does the one-line summary still match the full note, does a cited fact still hold, is a "settled rule" actually still settled. I ran it across the whole memory pool and it found two real cases: one memory pointing at a data store that had been quietly retired, and one summary line that still described a policy that had since been reversed.
Why this is only a slight improvement
Here's the honest part, and it's the reason I'm writing this post instead of declaring victory. All three of my tools check the file. None of them touch the broadcast — the mechanism that actually decides what gets shoved into the assistant's attention, unbidden, every single session. That mechanism is Claude Code's, not mine, and no amount of checking the file changes what happens the moment it's written: its one-line summary goes straight into the clipboard, full authority, no relevance filter, the very next session.
I actually tried to close that gap directly — I added a field to every memory recording whether a claim was something I explicitly said versus something the assistant concluded on its own. It sounded like the fix. It wasn't: the field lived on the file, and the file was never the part getting broadcast unfiltered. A week later I reverted it. The honest verdict, stated plainly to avoid fooling myself with my own tooling: three real, working checks on the file, and zero coverage of the one thing that actually decides what the model trusts by default. Better filing hygiene is not the same thing as better judgment, and it's worth saying so instead of letting a pile of hooks read as "solved."
How other developers actually deal with this gap
Talking to this problem honestly means admitting most people aren't doing anything nearly this involved, and that's a reasonable choice too:
- Treat the hand-written project file as the only trusted memory, and either turn the automatic memory feature off entirely or simply ignore what it writes — version-controlled, human-reviewed, nothing auto-summarized into it.
- Prune on a schedule instead of governing continuously — periodically delete or rewrite stored memories rather than trying to track why each one exists. Cheaper, weaker guarantees, and fine for lower-stakes setups.
- Let git be the real memory — commit messages and code history as the record of truth, treating anything the assistant "remembers" as disposable scratch that's fine to lose.
- Build a bespoke governed layer, same instinct as mine — other teams have independently concluded that automatic memory needs a governance layer bolted on, converging on the same idea from a different codebase (dev.to, "Claude Made Memory Editable — Production Agents Still Need a Governed Memory Layer").
- Or skip Claude Code's memory feature and build directly on the API's memory tool, inheriting the on-demand, audited shape from day one instead of retrofitting it — the option I don't have available inside Claude Code itself, at least not yet.
The takeaway
The bouncer's clipboard is fast precisely because it's short, and it's wrong precisely because it's short — those are the same fact, not two different ones. Anthropic already ships a version of "memory" that doesn't have this specific problem, at the API layer, for people building their own agents. Claude Code, the tool I actually use, doesn't have that version yet. Until it does, the honest position is: my three checks make the filing cabinet tidier, they don't make the clipboard smarter, and anyone telling you otherwise about their own hook stack is probably fooling themselves the same way I briefly fooled myself with the field I ended up reverting.
References
- Anthropic, "Managing context on the Claude Developer Platform"
- Anthropic, "Effective context engineering for AI agents"
- Leonie Monigatti, "Exploring Anthropic's Memory Tool"
- Wire, "Anthropic's Managed Agents memory: what it changes"
- dev.to, "Claude Made Memory Editable. Production Agents Still Need a Governed Memory Layer"
- Internal source:
scratch/memory-pollution-continuity.md(the incident writeup and diagnosis this post is drawn from)