Every team that wires long-term memory into a coding agent hits the same wall about three weeks in. The agent remembers plenty. It remembers the migration you abandoned, the library you replaced, the convention one person suggested once in a thread. It recalls all of it with the same flat confidence, and now you are debugging your memory instead of your code.
The instinct at that point is to store less, or to store better. Both are the wrong axis. The problem is not how much the agent remembers. The problem is that everything it remembers has the same authority.
Short-term versus long-term is not the useful split
The common framing separates the conversation you are in now from facts you keep forever. It is a real distinction, and it will not help you, because it says nothing about what the agent should do when two remembered things disagree.
A more useful split is evidence versus policy.
Evidence is what happened. The agent tried a fix and it failed. A user rewrote a function. A test went red. Evidence is cheap to produce, it accumulates fast, and any single piece of it can be wrong or unrepresentative.
Policy is what should happen. Use pnpm. Tests mirror the src layout. Never touch the legacy billing module. Policy is expensive to produce, because a human usually decides it, and it should be hard to change by accident.
Hold those apart and a lot of confusing behaviour becomes obvious. An agent that treats one observation as policy overfits to a single incident. An agent that treats a merged architecture decision as mere evidence keeps relitigating it. Most memory systems collapse both into one undifferentiated bucket of "things we know," which is exactly why they feel unpredictable.
Three layers, ordered by how easily they should change
In practice the split works better as three layers, because evidence and policy live at different scopes.
Shared project truth. Architecture decision records, API contracts, naming conventions, the deployment runbook. This is policy: versioned, source-linked, and the same copy for every agent on the project. If your agent invents its own answer to "which database do we use," that is not a memory problem, it is a missing shared layer.
Role memory. Heuristics that belong to a job rather than to a project. What a frontend reviewer usually checks. How the QA pass is structured. Which failure modes a migration tends to hit. This is the layer most systems skip entirely, and it is why teams re-teach the same review standards to every new session.
Episodes. What happened on a task: what was attempted, what failed, what feedback followed. Evidence in its rawest form, the layer that grows fastest and rots fastest.
These are not ranked by importance. They are ranked by how easily something should change. Episodes are written constantly. Role memory shifts slowly. Shared project truth changes only when a human decides it does.
The two time axes, and the bug you get free without them
This is the part worth stealing even if you ignore everything else.
Say your codebase used Redux, and last quarter you moved to Zustand.
With one time axis, the agent learns "we use Zustand" and the older note is overwritten or decays away. Now ask why a component written in March is structured the way it is. The agent cannot tell you. The fact that explains that code has been deleted, because it is no longer current.
But "recorded at" and "was true from / until" are different questions. "Use Redux" was true from January to June and was recorded in February. It is not wrong. It is closed. An agent that keeps closed facts with their validity window can still explain old code, warn you that a pattern you are copying belongs to a superseded era, and avoid confidently rewriting history.
Replacing a fact instead of closing it is the most common destructive operation in agent memory, and it stays invisible until someone asks about the past.
None of this is new engineering, by the way. Separating when a fact was true from when the system learned it is bitemporal modelling, standardised in SQL:2011 as application-time and system-versioned period tables (ISO/IEC 9075:2011; Kulkarni and Michels, Temporal features in SQL:2011, DOI:10.1145/2380776.2380786). The database people solved this before agents existed.
Evidence should have to earn its way into policy
If evidence and policy are different things, there has to be a path between them, and it should be explicit rather than accidental.
An agent observation starts as low-authority evidence. It becomes policy through one of a few events: a human correction, which is the strongest signal there is; a merged ADR or pull request that puts the decision in the repository; or a repeated successful outcome, where the same approach has worked often enough to stop being a guess.
The important word is earns. Systems that let a single agent observation write straight into shared knowledge will drift, and the drift is hard to spot because every individual step looks reasonable.
Demotion matters too and is rarer to see implemented. If a policy keeps producing failures, something should notice. Not delete it automatically: mark it disputed and surface that to a human.
Retrieval should hand you contradictions, not resolve them quietly
This is where most implementations go wrong, and it follows from everything above.
The default behaviour of a vector store is to return the nearest matches. If two stored items contradict each other, the one that happens to sit closer in embedding space wins, silently, and the agent proceeds as though there was never a disagreement.
That is backwards. A contradiction is information. If the store holds "we use Redux, valid until June" and "we use Zustand, valid from June," the right move is not to pick one. It is to return both with their validity windows and let the reasoning step deal with it. Same for a policy that a recent episode contradicts: an agent that sees "convention says X" next to "X failed twice last week" can raise it with you. An agent that sees only the closer embedding match cannot.
Preserving contradictions costs context budget. That is the honest trade. Losing them costs correctness in a way you cannot detect from the outside.
The practical gap nobody mentions
Here is the thing that surprises teams most, and it has nothing to do with architecture.
Connecting a memory tool does not make an agent use it.
You can wire up a perfectly good backend, expose it over MCP, watch the tools register, and then watch the agent go an entire session without calling any of them. Tool availability is not tool usage. The model has no standing incentive to check memory before acting, and no habit of writing anything down afterwards.
What closes the gap is boring: a standing instruction. Something in the system prompt or the project rules that says, in effect, recall before acting on anything project-specific, and save durable decisions and corrections when they happen. In Cursor that is a rule file. In Claude Code it is the project instructions. The exact mechanism matters much less than the instruction existing at all.
If you take one thing from this piece, take that one. It is the cheapest fix on the list and the one most often missing.
Disclosure: I work on Mnemoverse, a memory engine for AI agents. This article is adapted from the original in our library, which carries the FAQ and the mechanics in more depth: Agent memory: evidence versus policy.
Top comments (4)
The evidence-vs-policy reframing is the useful cut, and I think it's more powerful than it first looks because it also tells you where each layer is allowed to be written. Episodes accrete automatically from what happened. Policy should require a deliberate promotion step — a human, or at minimum an explicit review gate — precisely because it's expensive and slow to change by design. Most systems that "feel unpredictable" are actually letting a single episode silently graduate into policy with no promotion boundary at all.
The layer I'd push on is your role memory, because it's the one that quietly drifts. Project truth is source-linked so it stays honest; episodes are timestamped so you can age them out. Role heuristics ("what a frontend reviewer usually checks") have neither anchor, so they tend to ossify into folklore that no longer matches the codebase. Do you attach any provenance or decay to that middle layer, or is it treated as durable once learned?
Genuinely one of the clearer writeups I've seen on this — the "debugging your memory instead of your code" line is exactly the three-weeks-in wall.
The promotion boundary is a sharper way to say it than anything in the article, and I am taking it. A single episode silently graduating into policy with no explicit gate describes most of the "my agent feels unpredictable" complaints I have seen, including some of ours.
On role memory, honest answer in two parts, with a correction I owe this thread after re-checking our shipping read path today. Role heuristics in our store carry timestamps and a domain like every other record, and outcomes can be reported per memory. But the recorded outcome currently gets stored and displayed without changing what recall selects; wiring it into selection is active engineering work, not a shipped behavior. And the corrective signal itself is explicit feedback, which in production almost nobody sends. So you are right twice over: without both the loop firing and the wiring finished, role heuristics ossify toward folklore exactly as you describe. We measured how rare the signal actually is, and that measurement is the subject of the next piece, this Friday.
Your framing might simply be the better design: make graduation into policy expensive, instead of hoping demotion catches up later.
The evidence versus policy split is the right pressure point. I would probably add a third field to every promoted memory item, which is who gets to revoke it. Without that, old policy tends to survive because it still sounds official, even after the repo has moved on.
The revocation field is the missing half of the promotion boundary another commenter proposed above: a gate on the way in, an owner on the way out. Without both, policy is write-only.
Here is the part I find genuinely uncomfortable, having walked into it: when policy lives in a rules file in the repo, revocation authority exists for free. It is whoever can merge. Git gives you the revoker, the history, and the "this stopped being true on this date" for nothing. The moment policy migrates into a memory store, that authority silently evaporates, and nothing in the store's schema asks for it back. So the store ends up more official-sounding than the repo and less accountable than it.
Practical shape I would try: policy items carry a revoker the way they carry an author, and policy without a named revoker expires by default instead of persisting by default. Persistence should be the thing you earn, not the thing you get for free.