# Context Drift: The Silent Bug Killing Long-Running AI Agents > Context drift happens when an agent's effective memory diverges from reality over time. Stale facts, equal-weight retrieval, and no feedback loop combine to make agents confidently wrong. Here's the pattern and the fix. - **Category**: Theory - **Read time**: 7 min read - **Date**: June 16, 2026 - **Author**: Feather DB (Engineering) - **URL**: https://getfeather.store/theory/context-drift-in-long-running-agents --- ## What context drift looks like Context drift is the gradual divergence between an agent's stored memories and current reality. It's insidious because it doesn't produce errors — it produces outdated, confidently-stated responses. A coding assistant that remembered "we use React class components" from a conversation 8 months ago will still surface that memory today, even after 200 conversations where hooks were used exclusively. The fact is still in the vector store. Its embedding is still similar to queries about component structure. It will keep coming up. A customer support agent that stored "user is on the Pro plan" from January will still retrieve that fact in June, even if the user downgraded in March. The vector store has no mechanism for "this fact was superseded." ## The root cause: equal-weight retrieval Most vector stores treat every stored chunk with equal retrieval weight. A fact from 3 years ago is as likely to be retrieved as a fact from yesterday, assuming similar cosine similarity to the query. This is correct behavior for static knowledge bases — an embedding of a 1990 paper about sorting algorithms is as valid today as it was then. But for agent memory — where facts are observations about a changing world — equal-weight retrieval guarantees drift over time. ## The three failure modes **1. Stale fact retrieval** A user's preference, plan status, or behavior has changed, but the old fact is still retrieved because it's similar to the query. The agent responds based on outdated information. **2. Noise accumulation** As the store grows, low-quality facts (misunderstandings, corrections, out-of-context chunks) accumulate. They're never removed and never deprioritized. Signal-to-noise degrades. **3. Missing feedback loop** The agent has no way to learn which retrieved facts actually helped answer questions correctly. Every retrieval is treated identically regardless of whether it produced a good outcome. ## The fix: adaptive decay + stickiness A context engine addresses all three failure modes: **Stale fact retrieval → temporal decay** Facts that haven't been recalled recently get a recency penalty. Stale facts stop competing with fresh ones unless the query specifically targets them. **Noise accumulation → importance weighting** Facts ingested with high importance scores (set at ingest time from signals like verification, source confidence, or frequency) maintain their ranking. Low-importance facts decay faster. **Missing feedback loop → recall-based stickiness** Each time a fact is retrieved, its `recall_count` increments and its `last_recalled_at` timestamp updates. Facts that are retrieved frequently resist decay — they become stickier. The agent implicitly learns which facts are valuable through usage patterns. ## Implementing the feedback loop ```python import feather_db as fdb db = fdb.DB.open("agent_memory.feather", dim=768) # Search — automatically increments recall_count on returned nodes results = db.search( query_vec, k=10, half_life=30, # days until unrecalled memory halves in recency time_weight=0.3 # 30% weight on recency, 70% on similarity ) # At the end of a successful interaction, update importance # on the memories that led to a good outcome for result in results[:3]: # top 3 used memories meta = db.get_metadata(result.id) # Boost importance slightly for facts that helped new_importance = min(1.0, meta.importance + 0.05) db.set_metadata(result.id, fdb.Metadata(importance=new_importance)) ``` ## Handling explicit updates and contradictions When a fact is explicitly superseded ("I switched from React to Vue"), the right pattern is not just to add a new fact — it's to demote the old one: ```python # Find the old fact old_facts = db.search(embed("frontend framework preference"), k=3) # Demote it by lowering importance and adding a contradicted_by edge for f in old_facts: meta = db.get_metadata(f.id) meta.importance = max(0.0, meta.importance - 0.5) # penalize db.set_metadata(f.id, meta) db.link(from_id=new_fact_id, to_id=f.id, rel_type="supersedes", weight=1.0) # Add the new fact with high importance new_meta = fdb.Metadata(importance=0.9) db.add(id=new_fact_id, vec=embed("User uses Vue 3 for frontend"), meta=new_meta) ``` The `supersedes` edge lets downstream reasoning (context_chain) understand that the new fact replaced the old one, rather than treating both as equally valid. ## The drift timeline With adaptive decay and stickiness: - **Day 1**: New fact added with fresh recency. Retrieves well. - **Day 30**: If not recalled, recency score has halved. Still retrieves on strong similarity queries. - **Day 90**: Recency contribution is near-zero. Only similarity drives retrieval — the fact needs to be very relevant to the specific query to surface. - **Day 180**: Effectively dormant unless directly queried by ID. Facts that *are* recalled regularly stay fresh regardless of calendar time. A user's core preference for Python, recalled in every coding session, stays at day-1 recency even after a year. This is what separates a context engine from a vector store: it doesn't just retrieve, it learns what's worth remembering. **Install:** `pip install feather-db` · **Docs:** [getfeather.store](https://getfeather.store) --- *This is the machine-readable mirror of the theory post at [getfeather.store/theory/context-drift-in-long-running-agents](https://getfeather.store/theory/context-drift-in-long-running-agents). For the full Feather DB documentation, see [getfeather.store/llms-full.txt](https://getfeather.store/llms-full.txt).*