AI agents

Memory Expiry and Decay: Scheduling What an Agent Forgets

Antonio Evans10 min read

A clean side view of a memory shelf where each labeled box carries a small clock and a colored tag.
Key points

Key points

  1. 1Set a time-to-live (TTL) per memory type, because a user preference and a tool output have different useful lifetimes.
  2. 2Trigger eviction on more than the clock: contradictions, low retrieval hit rate, source revocation and session boundaries each justify an early delete.
  3. 3Log every write and every delete with a reason code, so a forgotten entry can be reconstructed and reviewed.
  4. 4Default to forgetting: promote only memories that prove useful through repeated retrieval, and expire the rest.

Why forgetting is a recall-quality control, not housekeeping

Most teams treat deletion as an infrastructure chore. Disk fills, the vector index slows, latency creeps, and someone schedules a cleanup job. That framing gets the problem backwards. A memory store gets worse at recall as it grows, even when storage is free and retrieval is fast, because every extra fact becomes another candidate to surface in the top-k search, and most of those candidates are noise for the current turn. Recall quality is bounded less by storage capacity than by how well the system suppresses irrelevant entries, as Mem0's guide to eviction and forgetting puts it.

There is a second cost that shows up long before storage bites: tokens. Stuffing full history into every prompt scales linearly with conversation length and forces the model to re-read irrelevant material, and long contexts also degrade reasoning because models handle information buried in the middle of a prompt poorly, a pattern documented in Mem0's long-term memory overview and analyzed in the systems study of agent memory workloads. Forgetting is therefore a lever on answer quality, latency and spend at once.

The practical stance that follows: treat every memory as a loan, not a purchase. It must justify its renewal.

A TTL policy per memory type

A single global TTL is the most common design mistake. Facts, preferences, task state and tool outputs have different decay profiles and different failure modes when they go stale. The memory design guide by Hidekazu Konishi argues for building forgetting into the design from the start, with freshness metadata per memory type rather than one expiry rule.

Here is a starting table you can copy into a design doc and adjust with your own numbers. The durations are illustrative defaults, not measured optima; the important column is the failure mode, which tells you what to test.

Memory typeExample contentDefault TTLRenewal ruleFailure if too longFailure if too short
Semantic fact (personal)"Account tier is enterprise", "prefers direct flights"180 daysRenew on each confirming retrievalAnswers built on an outdated account stateAgent re-asks known questions
Semantic fact (sensitive)Dietary restriction, allergy, accessibility needNo expiry by defaultNever age out; evict only on contradictionLow riskSafety-relevant answer becomes wrong
Episodic record"On this day the user asked for X and we decided Y"90 daysRenew if cited in later sessionsRetrieval noise, privacy exposureLoses decision history
Task stateOpen ticket, draft plan, intermediate result7 days after last activityRenew on each tool call in the taskAgent resumes a dead taskAgent loses an in-flight task
Tool outputHTTP response body, search result, file listing1 to 24 hoursRenew on re-fetchAgent cites stale prices or stock levelsExtra tool calls, higher latency
Procedural note"This API needs a pagination cursor"365 daysRenew on successful useKeeps bad procedure aliveRelearns the same lesson

Three rules make the table operational. First, attach the TTL to the record at write time, not to a global config, so a single entry can be granted a shorter life without a schema change. Second, separate "hard TTL" (a privacy or retention obligation that must be enforced) from "soft TTL" (a recall-quality default that can be extended on evidence). Mem0's eviction overview makes exactly this split: age-based TTL is the right tool for legally constrained data, while relevance decay handles recall quality.

Third, never let a pure TTL delete a small set of "never age out" facts. The classic failure is a user's allergy that has not been mentioned in six months. An age or recency policy quietly prunes it, and the next relevant question gets a dangerous answer. That same analysis flags this as the central weakness of LRU-style eviction: it treats access frequency as a proxy for importance, and rare-but-critical facts have low access frequency by definition.

A worked example of the budget effect: suppose an agent holds 40,000 memory entries averaging 60 tokens each. Relaxed TTLs let 5,000 of them exceed 180 days, and a naive retrieval layer puts 20 of those into every prompt at 60 tokens, which is 1,200 tokens of memory context per call. If a third of those are stale tool outputs that now expire in a day, and you also cut the retrieval fan-out from 20 to 12 candidates, the per-call memory payload drops to roughly 480 tokens. At 200,000 calls a month that is on the order of 144 million tokens saved, before any quality gain. Run the arithmetic with your own traffic to decide whether the engineering time pays for itself.

Eviction triggers beyond the clock

Time is a weak signal. An entry written yesterday can be wrong today, and an entry written a year ago can still be exactly right. Production systems need event-driven eviction alongside TTL. The AgentCore deep dive from AWS describes the core problem well: a memory system has to detect that two statements refer to the same thing and merge them without creating duplicates or contradictions, which is the same mechanism that lets you detect a contradiction and retire the older side.

Five triggers cover most cases:

  1. Contradiction. A new write conflicts with an existing entry. Do not keep both and hope ranking sorts it out. Mark the older entry superseded, keep it in the audit log, and remove it from the retrieval index. The AgentCore write-up gives the canonical example: a user says they are allergic to shellfish in January and "can't eat shrimp" in March, and those must consolidate rather than coexist.
  2. Low retrieval hit rate. If an entry has been a retrieval candidate many times and has never been cited in a final answer, it is crowding the candidate pool. Score each memory with an access counter and a citation counter, and evict entries that fall below a ratio you choose (for example, fewer than one citation per 50 retrievals after 30 days).
  3. Source revocation. When the document, ticket, CRM record or permission that produced a memory is deleted or its access policy changes, the derived memory must go too. Keep a source identifier on every write so revocation is a query, not an archaeology project. The Atlan taxonomy of agent memory types is useful here because it separates governed organizational context (definitions, lineage, access policy) from free-form episodic traces, which makes the revocation boundary explicit.
  4. Session boundary. Working memory should not survive the session by default. Anything worth keeping must be promoted explicitly to long-term storage. The Redis guide to agent memory describes the short-term layer as the equivalent of RAM: fast, limited and volatile, cleared when the thread ends. The KodeKloud explainer on agent memory makes the same point, that memory is a loop of writing, retrieving and forgetting rather than a one-time save.
  5. Memory pressure. The OS-inspired approach in MemGPT uses warning and flush thresholds on the prompt buffer: at a warning level the agent is prompted to save what matters, and at the flush level older items are evicted and summarized into external storage. You can apply the same thresholds per user or per tenant, not just per prompt. The alphaXiv summary of MemGPT describes the queue manager and recursive summarization concretely, and notes that this paging does not enlarge the model's real context window.

A decision rule to keep teams consistent: evict on any hard trigger (contradiction, revocation, hard TTL) immediately and without review; evict on soft triggers (hit rate, soft TTL, pressure) only through a scheduled job that writes an audit record. The first category is correctness and compliance. The second is tuning, and tuning should be reversible.

Writing the policy in code

Implement the policy as data, not as scattered if statements. A single policy record per memory type plus a pure function makes the behavior testable.

from dataclasses import dataclass
from datetime import datetime, timedelta

@dataclass(frozen=True)
class Policy:
    memory_type: str
    soft_ttl: timedelta
    hard_ttl: timedelta | None   # compliance bound, None means no hard limit
    max_retrievals_without_citation: int
    promote_after_citations: int  # citations needed to extend soft_ttl

def decide(entry, policy, now):
    """Return (action, reason) where action is keep, extend, expire or review."""
    if policy.hard_ttl and now - entry.created_at > policy.hard_ttl:
        return "expire", "hard_ttl"
    if entry.citations >= policy.promote_after_citations:
        return "extend", "proven_useful"
    if entry.retrievals >= policy.max_retrievals_without_citation and entry.citations == 0:
        return "review", "low_hit_rate"
    if now - entry.last_confirmed_at > policy.soft_ttl:
        return "expire", "soft_ttl"
    return "keep", "within_ttl"

Two implementation details matter more than they look. Store created_at, last_confirmed_at, last_retrieved_at, citations, retrievals, source_id and policy_name on every record; the machine learning mastery guide to agent memory design shows a comparable MemoryEntry shape with importance, confidence, source and timestamps, and gates persistence on thresholds rather than writing everything. And use a soft delete: set status = 'expired' and remove the entry from the retrieval index, but keep the row. Hard deletion belongs to the compliance path only, covered by hard_ttl.

Notice that last_retrieved_at is not the same as last_confirmed_at. A retrieval proves the entry was a candidate, not that it was right. Renewing on retrieval alone is how stale facts survive forever. Renew on citation in a delivered answer, or on an explicit user confirmation.

The audit trail: what to log, and why every delete needs a reason

An eviction you cannot explain is an incident waiting to happen. The first time a customer says "your assistant used to know my account manager's name," you need to answer three questions in minutes: was the memory ever written, when was it removed, and by which rule. Without an audit trail the answer is a log grep through application code.

Log every mutation as an append-only event with these fields:

FieldExamplePurpose
event_idevt_01H...Stable reference for support tickets
memory_idmem_8842Links events into a lifecycle
operationwrite, update, expire, purge, restoreWhat happened
reason_codesoft_ttl, contradiction, source_revoked, low_hit_rate, user_requestWhy
actoragent id, scheduled job name, user idWho or what did it
policy_namepreference_v3Which rule applied
occurred_atISO 8601 with timezoneWhen
snapshotlast 500 characters of contentReview without resurrecting the entry

Three practices make the trail useful rather than merely present. First, capture a snapshot on delete, so a reviewer can see what was forgotten without restoring it. Second, make the reason codes a closed list, so dashboards can group expiries by cause and reveal, for example, that 60 percent of deletions come from one over-eager TTL. Third, retain the audit log longer than the memories themselves, and record the retention period in your privacy notice; the Forgetful but Faithful paper frames this as forgetting-by-design, where retention decisions are explicable and aligned with privacy norms, and evaluates six forgetting policies including FIFO, LRU, priority decay and a hybrid that scored best across its simulations.

For regulated data, the audit log is also the evidence file. A retention policy that promises an eighteen-month window is only credible if you can show, per record, when it was deleted and under which rule.

Reviewing what was forgotten

The review step is where most designs stop short. A forgotten entry is a hypothesis: we believed this would not be needed. Once a week, test the hypothesis on a sample.

Sample the expiries. Pull a random sample of 100 expired memories per policy and ask two raters, one of them the product owner for the agent, whether each removal was correct, neutral, or a mistake. Track the mistake rate. A rate that climbs means the TTL is too aggressive for that memory type.

Watch for re-ask signals. If users repeat information after the agent forgot it, that is direct evidence of a bad eviction. Instrument the conversation for repeated entity values and attribute them to the expired memory that used to hold them.

Run resurrection drills. Take ten expired entries, restore them in a staging index, and replay the queries that once used them. If answers improve, the policy is wrong. If they do not, the deletion was free.

Review the low-hit-rate queue, not just the deletions. The review action in the policy code above produces a queue of entries that retrieved often and never helped. That queue is where over-writing happens; it usually shows the agent recording too much small talk and too few confirmed facts.

Close the loop on contradictions. Every superseded fact should have a cause. If contradictions cluster around one source, such as a CRM sync that writes every field nightly, fix the source rather than the eviction job.

One decision rule ties the review together: promote on evidence, expire on default. An entry earns a longer life only when it is cited in a delivered answer, confirmed by the user, or explicitly marked as durable by policy. Everything else shrinks toward the TTL. This inverts the common instinct to keep everything and prune later, and it is far easier to defend when someone asks why the agent forgot.

Where this fits in a running system

The eviction policy has to live somewhere that sees every write and every retrieval. If you are running several models in one agent (a small model for extraction, a larger one for reasoning, an embedding model for the index), keep the memory layer independent of the model choice so a swap does not reset your counters and TTLs. Quanta Inference (https://quantaintelligence.ai/inference) exposes text, image, video, audio and embedding models through a single OpenAI-compatible API key, which keeps the memory service free to call whichever model the policy needs.

For teams that would rather not build the whole loop from scratch, a specialist can take the design and ship it with you; that is what the Quanta build service is for. Either way, the three controls are the same: a TTL per memory type, triggers that go beyond the clock, and an audit trail that makes every removal explainable.

FAQ

FAQ

How long should an agent remember a user preference?

There is no universal number. Set a soft TTL per memory type (180 days is a reasonable starting point), let confirmed citations extend it, and never let a preference age out on a timer alone if it is safety-relevant. The renewal rule matters more than the initial duration, because the rule is what separates a fact that is still true from one that merely survived.

Is a bigger context window a substitute for a TTL policy?

No. Larger windows delay the problem and raise cost and latency, and models use long contexts unevenly: facts buried in the middle are recalled less reliably, a result discussed in Mem0's overview and in the agent memory systems study. Context is what the model sees in one call; memory is what you store outside it and choose to load. Each needs its own policy.

What is the difference between soft and hard TTL?

A soft TTL is a recall-quality default that can be extended when an entry proves useful. A hard TTL is an obligation, usually from a retention commitment or regulation, and it fires regardless of usefulness. Keep them as separate fields so an eviction job can be tuned without weakening a compliance control, a distinction that Mem0's eviction guide makes when it recommends TTL for legally constrained data.

How do I stop a stale fact from leaking into an answer?

Detection first: on every write, search for an existing entry on the same subject and mark the older one superseded. Second, keep expiry metadata on the record and filter expired entries out of the retrieval index rather than relying on ranking. Third, attach the source identifier so revocation of the underlying document removes the derived memory. The consolidation problem is described concretely in AWS's AgentCore memory deep dive.

Do I need to keep deleted memories?

Keep the audit event, not the full memory, unless a law or contract requires otherwise. Store the reason code, actor, timestamp and a short snapshot, and set a retention period for the log itself. This gives you reviewability and an evidence trail for support questions while honoring the principle that the default is to forget, which the design guide on forgetting and staleness treats as a first-class design concern.

Sources

Sources

  1. Memory eviction and forgetting in AI agents
  2. Long-Term Memory for AI Agents: The What, Why and How - Mem0
  3. Agent Memory: Characterization and System Implications ...
  4. AI Agent Memory Design Guide - Working, Long-Term, and ...
  5. Building smarter AI agents: AgentCore long-term memory deep dive - AWS
  6. Types of AI Agent Memory: Episodic, Semantic, Procedural and More
  7. Build AI agents with short-term & long-term memory in Redis
  8. Agent Memory Explained in 5 Minutes - YouTube
  9. 2310.08560 MemGPT: Towards LLMs as Operating Systems - arXiv
  10. MemGPT: Towards LLMs as Operating Systems - alphaXiv
  11. AI Agent Memory Design: What Works and What Doesn't
  12. Forgetful but Faithful: A Cognitive Memory Architecture and ...
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles