← Alle Playbooks
Playbook· setup

Repair memory drift, when your agent's memory starts contradicting itself

Diagnosis and repair in 90 minutes when your memory server has gone contradictory, duplicated or stale.

At some point it happens to everyone who uses memory seriously. You ask the AI something and get two answers in one session. It says in one sentence "You use Postgres" and in the next "You use Supabase". Both were true once, now it just confuses things. That is memory drift. The symptoms are subtle at first, get more aggressive over time, and at some point the memory is so cluttered with old statements that the AI hallucinates more than it helps.

This playbook is the toolkit for the day you notice your memory is broken. We go through diagnosis, cleanup and verification step by step. Unlike the memory hygiene routine (L4-09), this is not a maintenance ritual but emergency repair. One hour to 90 minutes, then the memory is back on its feet.

1. Spot the drift, three symptoms

Before you reach for tools, ask yourself whether the symptoms are really memory and not model variance. Three clear signals.

First, the AI cites facts that no longer hold. Six months ago you said "We use MySQL", then migrated to Postgres, both are in memory, and it picks at random. Second, it gives contradictory names for the same thing. "Aklow Memory" and "StudioMeyer Memory" are two separate entities in your knowledge graph even though it is the same product. Third, it makes suggestions you explicitly rejected. Lodash for example, because you said in May go vanilla, in July you forgot and briefly used lodash, and now both are stored as a "user preference".

If you see two of these three, the drift is here. Time for diagnosis.

2. Pull an inventory, quantify the damage

Before you delete anything, look at how bad it really is. nex_contradictions(action: "stats") is the entry point. That gives you the number of contradictions found, sorted by status.

Rule of thumb: under 10 open contradictions is normal wear and tear, 10 to 50 is a maintenance backlog, over 50 is acute drift. If pending or unresolved is over 50, keep going with this playbook. If under 10, you only need the routine from L4-09.

Write the number down. You will need it at the end for the before-and-after comparison.

3. List and group the contradictions

nex_contradictions(action: "pending") pulls the open list. Look at the first 20, not all of them.

What you are looking for are clusters. Same entity, multiple versions. "Database choice" will most likely show up ten times, because every migration made a new statement. When you spot a cluster, you have identified the actual problem. Taken individually the contradictions look like coincidence, in the cluster it is clear that one entity got matted up over months.

Note down the top three clusters. Those get special treatment in a moment, the rest goes into auto-resolve.

4. Identify stale observations

Contradictions are one kind of drift, old unused facts are the other. nex_consolidate(action: "cleanup_stale_obs", dryRun: true) shows you observations with confidence below 0.5 that are older than 30 days. Default filter, good for getting started.

Read the output carefully. If matched is over 50 percent of scanned, the server blocked you before the real cleanup. That is intentional, otherwise you accidentally delete half your database.

In that case check whether the filter was too broad. Maybe maxAgeDays: 30 is too young for your workflow, bump it to 60 or 90. Maybe maxConfidence: 0.5 is too loose, lower it to 0.3.

5. Read the dry run, do not skim it

The dry-run output shows you examples of the matches. Read five to ten of them manually. Ask yourself per match, is this really obsolete?

If you see matches that should not go ("from January 15, MeetMyAgent tech stack is Next.js 16"), your filter is wrong and you have to go back to step 4. If the matches look like junk ("from February 3, test entry, foo bar"), the filter is good and you go to step 6.

Never skip step 5. Cleanup without a dry-run review is like rm -rf without --preview.

6. Run the cleanup

If the dry run looked good, the same command with dryRun: false. The server invalidates the observations softly (sets valid_to), it does not delete hard. That means you can pull them back via SQL if needed.

If you saw a bulk block during the dry run (matched over 50 percent of scanned) and you are sure it is intended, add force: true. Only do that if you understand why the protection threshold triggered. Force without understanding regularly leads to memory wipes after which the AI suddenly knows nothing about you anymore.

Write down how many observations were invalidated. Second number for the before-and-after comparison.

7. Merge duplicates

Drift often produces duplicates. "StudioMeyer Memory" and "studiomeyer-memory-server" are technically two entities, in fact one. nex_deduplicate(action: "scan", autoMergeThreshold: 0.85) finds the high-confidence duplicates and merges them automatically.

The default threshold is 0.85, that only catches close matches. For a more aggressive cleanse you can drop to 0.75, then more pairs get auto-merged but the risk of false merges goes up. Personal recommendation, stay at 0.85 and merge the rest manually with nex_entity_merge.

Merge operations are reversible via nex_entity_history if you make a mistake, but only in the first seconds before caches kick in. Careful.

8. Run confidence decay

Drift also comes from old statements enjoying the same trust as fresh ones. Decay solves that. nex_decay(action: "run") reduces confidence on observations that have not been retrieved for a long time.

Good to know, decay is not destructive. It only changes the sorting. An observation with lowered confidence surfaces later in retrieval, but it is not deleted. On repeated retrieval the confidence rises again.

For acute drift run it once, then monthly. The monthly routine is L4-09.

9. Verify the always-on switch

After the cleanup you check whether the AI actually reads the new memory. Otherwise you cleaned up and nobody notices.

Open a fresh session, a tool you do not want to mention. Ask a project-specific question, with no hint that you have memory. "Which database do I use for project X?" If the answer is concrete and correct, the always-on switch is working. If the AI hedges or gives generic answers, the switch is disabled.

Repair, nex_profile(action: "save") writes a snapshot into the auto-context, which gets loaded in every new session. Then the same question in a new session, it should land now.

10. Save the pattern so it does not come back

Last step, the most important one. Write down what caused the drift. Three sentences are enough.

For example: "Drift came from a DB migration in March, old MySQL statements stayed as a truth source next to new Postgres statements. The fix was to store the migration explicitly as a decision and invalidate the old ones. Prevention, on every architecture decision mark the previous state explicitly as invalidated."

Save that as a learning with category mistake and tag memory-drift. Compound effect, in a year you have five to ten such entries and the next drift gets caught early.

Now compare the numbers from step 2 (contradictions) and step 6 (stale observations) with the current values. If contradictions are under 10 and the stale rate is under 5 percent, the memory is repaired. If not, loop back to step 3 with a finer filter setting.

What comes next

Avoiding drift again is L4-09, the maintenance-oriented memory hygiene lesson. If you want to keep memory in sync across multiple AI tools, the playbook "memory-portabel-nutzen". For the question of why memory makes sense at all and what happens without it, L4-01 "warum-memory".