Dollar amounts on this page are in USD unless another currency is explicitly named.
The shop that keeps selling yesterday's price
Picture a small AI system that helps run an ice cream shop's ordering. It answers questions like "what's our vanilla price today?" by pulling from a memory store built from past conversations, supplier emails and inventory snapshots. On Monday, someone updates the inventory system: vanilla goes from $4.10 a tub to $4.60. The agent's memory store, though, still holds a note from three weeks ago that says "vanilla is $4.10, confirmed with supplier." A customer-facing draft asks for the current price, the retrieval system searches the memory index, and the old note comes back as the closest semantic match. The note contains the product and price terms the query asks for, so the similarity ranking is plausible. Its freshness still needs a separate check.
The retrieval pipeline is missing a freshness rule. Similarity search alone does not promise the current price: an old note can remain a strong semantic match long after the source changes. To answer a present-tense question, the application must select an authorized, current record before the model uses it.
Facts and decisions are not the same kind of memory
Before fixing anything, it helps to split what an agent stores into two categories that get blurred together in practice. One is a record of what happened: a note that on August 3rd, someone confirmed vanilla was $4.10. Changing today's price need not erase that historical observation. Keep it separately from the current value under the store's retention policy, so a later audit can distinguish what was recorded then from what should be quoted now. Anthropic's engineering writeup on context management describes context as a finite resource that has to be actively curated across prompts, tools and runtime state (Anthropic, "Effective context engineering for AI agents," 2025-09-29). Curating a finite resource means deciding what gets pulled into an active decision, not deciding what gets destroyed from the record.
The other category is the current value an application should act on right now: the price to actually quote a customer today. That value needs to be selected, not just retrieved. Selection means applying a rule that says "give me the record for this fact that is both the newest and the one whose source revision matches the authoritative system," rather than "give me the record that sounds most like the question." LangChain's writeup on self-correcting memory frames this as knowledge going stale as underlying systems change, which is exactly the shape of the ice cream shop's problem: the code (or the inventory database) moved on, and the memory didn't (Colin Francis, LangChain, "Self-correcting memory," 2026-08-25). That piece describes a wiki whose claims are tied to versioned code evidence, not a price database; the mechanism it demonstrates — comparing a stored claim's evidence version against the current source before trusting it — is what the ice cream shop's price record needs too, even though the two systems track different kinds of facts.
A memory record needs enough structure to be checked, not trusted
The fix is not "delete old memories more often." Deleting aggressively loses the audit trail and risks throwing out something still true. The fix is giving every stored fact enough structure that a program, not a similarity score, can decide whether it is still authoritative. A workable record for this teaching example looks like this:
| Field | Purpose |
|---|---|
fact_id | The exact fact being selected, such as price.vanilla |
source_id | The authoritative system for that fact; an old email is not automatically authoritative |
source_revision | A reliable revision for this fact at the authoritative source; document its scope |
recorded_at | When the memory itself was written |
status | current, superseded, or disputed |
In this example, v17 and v18 are revisions of the vanilla price record. When that record moves from v17 to v18 and the price changes, the v17 price record's status flips to superseded. It is not deleted. A new record is written for v18 with status: current. Any retrieval that needs "the current price" filters on status == "current" and, critically, cross-checks source_revision against the authoritative system's present revision before treating the answer as safe to quote. If the two don't match, the agent has found a record that merely used to be current, and it should say so rather than guess.
This is a proposed schema for this teaching example, not a description of a shipped product feature. The related first-party lesson on memory handoffs works through a companion structure for job state and permissions rather than factual claims, and it makes a parallel point: a schema can validate that a field exists, but it cannot by itself prove the referenced fact is still true (see the course material on memory handoffs and permissions). Structure narrows the check. It does not replace the check.
Working the invalidation scope, not just the trigger
A second mistake sits right next to the first one: treating an invalidation event as a signal to wipe everything the agent knows, rather than the one fact that actually changed. Suppose the shop's price table updates vanilla from $4.10 to $4.60, but strawberry stays at $3.90. A blunt invalidation rule that says "the source changed, clear the whole price memory" forces the agent to re-fetch and re-verify facts that never moved, which wastes work and, worse, can introduce a window where the agent has no price at all for an item nobody touched.
Scoped invalidation requires a per-fact revision or a trustworthy change list identifying affected facts. If v18 is only a global inventory revision, a mismatch says that something changed, not that vanilla changed. Revalidate all dependent facts in that case, or obtain the change list before narrowing the work. Do not claim fact-level precision from a global version number.
For the next exercise, use separate revisions for price.vanilla and price.strawberry. A practical test for this, proposed here as a bounded exercise rather than a claimed production run: build two small in-memory fixtures. Fixture one changes only the vanilla record between source revision v17 and v18. Fixture two changes only the strawberry record. Run the same "give me current prices" query against both and check that fixture one's response updates vanilla while leaving strawberry's recorded_at and status untouched, and that fixture two does the mirror image. If you build and run this, it would be a bounded, in-memory check of the invalidation logic's scoping behavior inside a single test program — it would show the logic distinguishes fact-level changes correctly within that program. It would say nothing about how any production database enforces consistency, concurrent writes or durability, and it would not be evidence about behavior at an external supplier's system.
Write source_id and source_revision at the moment a fact is recorded, not as an afterthought bolted on later.
Before returning a fact to answer a live question, check whether its source_revision still matches the authoritative source's current revision.
A revision mismatch makes the cached value unsuitable for a current answer. Fetch and validate its replacement before publishing a new current record. Update the old status and current pointer atomically in the datastore. If the source is unavailable, report that the current price is unavailable; do not promote an unchecked value.
When a reliable change list or per-fact revision identifies one changed item, invalidate that item's dependent records. If only a global revision is available, revalidate the wider dependency set.
Naming who owns a fact's freshness
None of this runs on its own. Somebody or something has to notice that the inventory system moved from v17 to v18 and trigger the comparison. Leaving this to "the agent will figure it out from context" is exactly how stale prices survive: nothing scheduled the check. A workable ownership record, again as a teaching exercise, has five fields: fact_id, authoritative_source, updater_role, invalidation_trigger, and escalation_when_missing. For the vanilla price, that might read: fact_id price.vanilla, authoritative_source inventory-db, updater_role inventory-clerk-agent, invalidation_trigger on inventory revision bump, escalation_when_missing alert shift manager if a detected change has no verified replacement within 15 minutes. The 15-minute interval is an illustrative operating choice. It starts when a change is detected, so an unchanged price does not generate an alert merely because it is old. Withhold an unverified current answer immediately; the escalation timer governs who investigates the gap. A production store also needs to detect missing change events and unavailable sources.
The write sequence below shows the intended transaction after a replacement has been checked. Use it to inspect whether readers can see two current records or a partly updated pointer. A diagram specifies the operation; it does not establish that your database implements it atomically.

A high similarity score tells you the retrieved text answers the same kind of question. It tells you nothing about whether the source underneath that text has since changed. Always pair retrieval with a revision check before treating a fact as safe to act on.
Testing the agent memory invalidation rule directly
Check the decision
Where the freshness rule can fail
A reliable revision identifier is one way to check freshness. If the source lacks one, the application can re-fetch the authoritative value, compare a content hash, or apply a documented freshness interval. Each has different costs and assumptions. A locally recorded timestamp alone tells you when a copy was written; it cannot prove that no upstream change happened afterward.
Two writers can also race to publish different current values. The datastore needs a uniqueness rule for the current pointer and a conditional update against the revision each writer read. Otherwise the later commit can overwrite a newer source value with an older one. The proposed in-memory exercise does not test concurrent writers or durable commits; those require tests against the datastore you actually use.
Finally, a revision can change between reading a price and executing an order. The current-answer check establishes which value was observed at that read. If the transaction requires the same price, bind the proposal to that revision and recheck it at execution, or use an authoritative quote with an explicit validity rule. Memory freshness and purchase validity are related checks at different moments.
Where to take this next
The distinction between preserving history and selecting current truth also governs job state and permissions when one agent instance hands work to another, which the course lesson on memory handoffs works through in more depth.
If retiring stale facts made sense, the next step is learning how the same current-versus-history split governs handing off in-progress work between agent instances.

