Six months into a deployment, a customer success agent greeted a returning customer by asking how the new job at Northwind was going. The customer had left Northwind in March. They'd mentioned it on the call in March, actually, but the agent's memory still held the older fact, still ranked it near the top of retrieval because it had come up often, and cheerfully surfaced it as a friendly opener. The customer's reply was one word: "Ouch."
That's the failure mode nobody plans for when they add memory to an agent. You spend the first month making sure the agent remembers things. You don't spend any time deciding what it should forget, so it forgets nothing, and a store that forgets nothing eventually hands you the wrong fact at the worst moment. Memory that only grows doesn't get smarter. It gets more confidently wrong.
The fix isn't a bigger vector store or a better embedding model. It's a forgetting policy: an explicit set of rules for what fades, what gets deleted, and what's protected. The AI memory research through 2026 has converged on this. Memory in production is a lifecycle problem, and forgetting is half the lifecycle.
Why an Agent That Never Forgets Is a Liability
An agent that never forgets is a liability because retrieval doesn't know the difference between old and current. Every memory you keep is a memory that can match a query and get injected into context. Keep the resolved complaint from February, the address the customer moved out of, the preference they changed their mind about, and all three stay eligible to resurface. The store grows, retrieval quality drops, and the agent starts speaking from facts that used to be true.
There are three distinct costs, and they compound.
The first is wrong-fact recall, the Northwind problem. A stale memory outranks the current one and the agent acts on it. This is the one customers actually feel.
The second is context dilution. If you retrieve the top eight memories to inject into context and three of them are outdated, you've spent three slots of a limited working window on noise. Context is RAM, not storage, a point worth internalizing from context is RAM, not storage. Every stale memory you inject is a relevant one you didn't have room for.
The third is cost and latency. A larger store is slower to search and more expensive to maintain, and the marginal memory you're paying to keep is often one you'd be better off without. Unbounded growth is a bill that arrives quietly.
None of these get better on their own. They get worse at exactly the rate your memory store grows, which is to say, continuously.
The Four Levers of a Forgetting Policy
A forgetting policy has four levers: importance, merge, decay, and eviction. Importance decides what's worth keeping. Merge combines related memories into one. Decay lowers how easily unused memories are recalled without deleting them. Eviction actually removes facts. The 2026 memory systems that work in production, across Mem0, Zep, Letta, and others, treat these as a policy layer sitting on top of storage, not as features of the store itself.
Here's how the four relate:
| Lever | What it does | Deletes data? | Primary job |
|---|---|---|---|
| Importance | Scores each memory's durable value | No | Decide what's worth keeping at write time |
| Merge | Combines related or duplicate memories | Yes, the originals | Reduce redundancy, consolidate |
| Decay | Lowers retrieval score of unused memories | No | Quietly sink stale facts below the cutoff |
| Eviction | Removes facts outright | Yes | Reclaim space, guarantee a fact is gone |
The two most misunderstood are decay and eviction, because they sound like the same thing and do opposite things to your data. Getting the distinction right is most of the battle.
Decay: Making Stale Facts Hard to Recall Without Deleting Them
Decay is a search-time re-ranking layer, not a deletion mechanism. Nothing leaves the store. A recently reinforced memory gets a score boost, up to 1.5x in Mem0's decay layer, and an unused one gets dampened toward a floor of 0.3x, a 5x spread between fresh and stale. The stored fact never changes. Its accessibility falls when nothing reinforces it, so unused memories sink below your retrieval cutoff over time and stop showing up, without ever being deleted.
The mental model comes from human memory. A fact you haven't used in months isn't erased from your brain, it's just harder to reach. Reinforce it by using it again and it comes back to the top. Decay engines apply the same curve, and some are explicitly modeled on the Ebbinghaus forgetting curve from psychology. The mechanism is a multiplier on the retrieval score based on recency and access frequency.
// Decay adjusts retrieval score by recency and use. It never edits the fact.
interface Memory {
id: string;
text: string;
baseScore: number; // semantic similarity to the query
lastAccessedAt: number; // epoch ms
accessCount: number;
}
const BOOST_MAX = 1.5;
const DAMPEN_FLOOR = 0.3;
const HALF_LIFE_DAYS = 30;
export function decayedScore(m: Memory, now: number): number {
const ageDays = (now - m.lastAccessedAt) / (1000 * 60 * 60 * 24);
// Exponential decay toward the floor as a memory goes unused
const recency = Math.pow(0.5, ageDays / HALF_LIFE_DAYS); // 1 -> 0 over time
const multiplier = DAMPEN_FLOOR + (BOOST_MAX - DAMPEN_FLOOR) * recency;
return m.baseScore * multiplier;
}Decay is the right default for low-relevance memories. The transient detail from one call, the passing mention that never came up again, the inferred preference the customer never confirmed. Leave those in the store, let them dampen, and they quietly stop mattering. You don't have to decide to delete them, and if they turn out to matter again, a single reinforcing access brings them back.
But decay has a blind spot, and it's a serious one. It only dampens memories that go unused. A memory that gets retrieved constantly never decays, because every retrieval reinforces it. The Northwind fact came up on every call, so it stayed boosted the whole time it was busy being wrong. Decay handles low-relevance staleness beautifully and high-relevance staleness not at all.
Eviction and Supersession: Actually Removing What's Wrong
Eviction removes facts from the store outright, and the most important trigger for it is supersession: deleting a memory when a newer fact contradicts it. When a customer gives a new address, the old one should be superseded, not filed next to the new one. This is the lever that fixes the staleness decay can't, because it acts on the contradiction rather than on disuse.
Supersession is the single highest-value piece of a forgetting policy for customer experience, because the facts that hurt most when stale are exactly the high-relevance ones decay leaves alone. Address, employer, current plan, primary contact method, the name of the product they use. These get retrieved often, so decay never touches them, and they're precisely the facts that go wrong when a customer's life changes.
The mechanism is contradiction detection at write time, and it's the part of a memory layer that earns its keep. When a new memory comes in, check whether it contradicts an existing one about the same entity and attribute. If it does, supersede.
import { Chanl } from '@chanl/sdk';
const chanl = new Chanl({ apiKey: process.env.CHANL_API_KEY });
// On writing a new fact, find and remove the facts it contradicts.
export async function writeWithSupersession(
customerId: string,
key: string, // e.g. 'address', 'employer', 'plan'
value: string,
) {
const { data } = await chanl.memory.search({
entityType: 'customer',
entityId: customerId,
query: key,
limit: 5,
});
// Same customer, same key, different value => supersede the old fact
const stale = data.memories.filter((m) => m.key === key && m.value !== value);
for (const old of stale) {
await chanl.memory.delete(old.id);
}
return chanl.memory.create({
entityType: 'customer',
entityId: customerId,
content: `${key}: ${value}`,
key,
value,
});
}Keyed facts get a shortcut: writes to the same entity and key deduplicate into an update rather than piling up as duplicates, so the explicit search-and-delete pass is for contradictions that arrive under different keys or as free text.
Beyond supersession, eviction runs on two other triggers. Tier-based lifetimes expire memories on a schedule tied to their type: a transient conversation detail lives for a session, an inferred preference for weeks, a stated preference until superseded. Capacity eviction kicks in when a store or a per-customer memory block hits its limit, at which point a least-recently-used policy drops the coldest memories first, the same K-LRU idea that operating systems use to swap pages between RAM and disk.

Customer Memory
4 memories recalled
“Discussed upgrading to Business plan. Budget approved at $50k. Follow up next Tuesday.”
The Line You Never Cross: Protected Memories
Some memories must never decay and never be evicted, and drawing that line is the first job of a forgetting policy. Verified identity, accessibility needs, communication consent, and compliance flags go in a protected tier that no automatic process touches. Forgetting a customer's stated accessibility need because it hadn't come up in a while isn't a bug in the abstract, it's a harm to a real person.
Keep the protected set small and explicit. If everything is protected, nothing is, and you're back to a store that never forgets. The discipline is deciding, up front, the short list of facts whose staleness risk is lower than their forgetting risk.
- Identity and verification. Who the customer is, confirmed. You don't want to re-verify every session, and you never want to lose it.
- Accessibility and accommodation. Stated needs that affect how you serve someone. These are consent-adjacent and forgetting them is a real failure.
- Communication consent. What channels the customer opted into or out of. Legally and ethically load-bearing.
- Compliance flags. Do-not-contact, dispute markers, regulatory holds.
Everything outside this set is a candidate for forgetting. That's the point. The protected tier is what lets you be aggressive about decay and eviction everywhere else, because the facts where a mistake is unacceptable are walled off from the machinery that might drop them. The privacy dimension of this, deciding what should never have been stored in the first place, is its own discipline covered in privacy-first agent memory design.
How the Levers Fit Together
The four levers run at different points in the memory lifecycle, and seeing where each fires makes the policy concrete rather than abstract. Importance scores at write time. Supersession fires at write time too, when a new fact arrives. Decay runs at read time, re-ranking retrieval. Capacity eviction runs on a schedule or a threshold. The protected tier sits across all of them as a veto.
Read that top to bottom and it's a policy, not a pile of features. A fact comes in, gets checked against the protected set, gets checked for contradiction, gets scored and stored with a lifetime. At read time, decay shapes what surfaces. On a schedule, eviction reclaims space. The pieces I've walked through, decay, supersession, tier lifetimes, capacity eviction, and the protected tier, are the whole system. If you're building memory from scratch, build your own AI agent memory system covers the storage and retrieval foundation this policy sits on top of, and async memory consolidation covers the merge lever in depth.
Testing That Your Agent Forgets Correctly
Forgetting is a behavior you verify, not a setting you trust. The only way to know your policy works is to run scenarios that plant a fact, change it, and confirm the agent recalls the new value and never the old one. A forgetting policy that's never tested is a forgetting policy you're finding out about in production, one "Ouch" at a time.
The scenarios that matter map directly to the levers:
- Supersession. Give the agent a new address mid-conversation, then in a later session ask something that should surface the address. Assert it returns the new one and that the old one never appears in retrieved context.
- Decay. Plant a low-relevance fact, run several sessions that never touch it, then confirm it has dropped below the retrieval cutoff and doesn't get injected.
- Protected tier. Set an accessibility need, then run enough unrelated sessions that decay and eviction would normally have acted, and confirm the need is still recalled intact.
- Staleness under load. Plant a high-relevance fact, contradict it, and confirm supersession fired rather than leaving both versions to fight in retrieval.
Define each of those as a scenario, with the plant-then-contradict script in the scenario itself and a scorecard that fails the run if the stale value surfaces. Then executing the suite is a loop:
import { Chanl } from '@chanl/sdk';
const chanl = new Chanl({ apiKey: process.env.CHANL_API_KEY });
// Each scenario plants a fact, contradicts it, then asks a question
// that should surface only the current value.
export async function runForgettingSuite(scenarioIds: string[], agentId: string) {
for (const scenarioId of scenarioIds) {
const { data: started } = await chanl.scenarios.run(scenarioId, { agentId });
// Executions run async; poll this in real CI until status is terminal
const { data: execution } = await chanl.scenarios.getExecution(
started.executionId ?? started.execution.id,
);
console.log(scenarioId, execution.status, execution.overallScore);
}
}Run these in CI when you change your memory configuration, and run a sampled version continuously against production so a drift in retrieval quality shows up on an analytics dashboard instead of in a support ticket. Memory quality is something you monitor, not something you set once. This closes the loop from the build side, where you define what the agent stores and forgets, to the monitor side, where you confirm it's still forgetting correctly under real traffic.
The Northwind mistake wasn't a memory failure in the way you'd first assume. The agent remembered perfectly. That was the problem. It remembered a fact that had expired and had no policy for letting it go, so it did exactly what an unbounded memory always eventually does: it recalled the wrong thing with total confidence at the worst possible moment. Forgetting isn't the opposite of a good memory. It's what makes one.
Verify your agent forgets the right things
Chanl scenarios let you plant a fact, change it, and assert the agent recalls the current value and not the stale one. Test supersession, decay, and your protected tier before a customer finds the gap.
Explore scenariosCo-founder
Building the platform for AI agents at Chanl — tools, testing, and observability for customer experience.
El briefing de Signal
Un email por semana. Cómo los equipos líderes de CS, ingresos e IA están convirtiendo conversaciones en decisiones. Benchmarks, playbooks y lo que funciona en producción.



