Most NPC AI breaks the moment a player returns. It forgets the conversation, repeats itself, or states something that was never true. The usual response is to store more, and it rarely helps, because the problem is not volume. It is that memory written as a pile of text has no way to express that one thing replaced another.
A better approach is to treat NPC memory as a graph of state, where current facts, historical facts, and superseded facts all coexist, and where a fact that stops being true gets corrected rather than deleted.
Who it's for: Game developers, narrative designers, and AI engineers building NPCs that need continuity across sessions, per-player relationships, and lore-safe dialogue.
Step 1: Stop treating memory like a chat log
- A transcript is useful for reference and it is not enough to drive behaviour. It records what was said without recording what any of it meant or whether it still holds.
- Separate the raw conversation from structured memory: who the player is, what happened, what the character now believes, and how certain it is of each belief.
- That confidence field is not decoration. It is what lets a later contradiction resolve sensibly instead of the newest line always winning.
Step 2: Model memory as a graph, not a flat list
- Store each memory as a node and connect nodes with typed edges: caused by, contradicts, supersedes, supports, belongs to this relationship.
- The edges are the point. They let the character reason about how one fact changed another rather than retrieving five sentences that happen to look similar to the question.
- If you want the entity-and-edge modelling in more depth, that is the subject of persistent NPC memory for long-running worlds. This post is about what happens when one of those facts stops being true.
Step 3: Keep three versions of truth: current, historical, and superseded
- Current facts are the active beliefs, the only tier the character should speak from.
- Historical facts stay readable so you can explain how the character arrived here. "She trusted you until the ambush" is a different character from "she does not trust you," and only the history distinguishes them.
- Superseded facts preserve the correction trail. They are not active and they are not deleted, so you can always answer why the character believed something last month.
- The three tiers are cheap to add early and painful to retrofit, because once facts have been overwritten the trail is genuinely gone.
Step 4: Add per-player memory and relationship state
- Do not let every player share one character state. Track trust, affinity, hostility, promises, and unresolved events per player.
- A returning player should get a different response from a stranger in the same place at the same time. That single difference does more for the sense of a living world than most authored content.
- Per-player state also contains the blast radius of a bad memory. One corrupted record affects one relationship rather than every player's experience of that character.
Step 5: Use correction rules instead of silent overwrites
- When new information conflicts with an older fact, record a correction edge and mark the old fact superseded. Do not delete it.
- This is the step teams skip, and it is the one that costs the most later. An overwrite is a fact that changed with no record of what it was, when it changed, or what changed it, which makes "why does she think I stole the ledger" undebuggable.
- A correction trail also protects canon. When a contradiction shows up in play, you can see which fact came from where and decide which one is wrong, instead of guessing.
Step 6: Ground every response in memory, lore, or the character brief
- Before the character speaks, check whether each specific claim traces back to a valid source: stored memory, world lore, or the character brief.
- If nothing supports it, rewrite the answer, stay vague, ask a clarifying question, or decline. "I don't remember" is in character. An invented name is not.
- Grounding and correction are the same discipline applied at two moments. One stops a false fact from being spoken, the other stops a false fact from quietly becoming history.
Step 7: Let mood evolve separately from memory
- Memory says what happened. Mood says how the character feels about it right now. Keeping them in one field means every emotional swing rewrites the record.
- Use a gradual scale and move one step at a time. Calm to annoyed, loyal to suspicious. A character that flips states inside one exchange reads as unstable rather than reactive.
- Mood should follow accumulated pressure rather than the last message, so a single rude question colours a reply without redefining the relationship.
Where a cognition layer fits
Everything above is buildable, and the reason teams do not build it is that the payoff shows up months later while the cost is immediate.
MistScale covers the runtime half. Conversations are distilled into compact memory records rather than stored as transcripts, kept per player, and consolidated on their own. Relationship state (trust, patience) is separate from what the character knows. Mood is a slow baseline that shifts one step at a time with a faster per-reply emotion on top. Every specific claim is checked against memory, your uploaded lore, or the character brief before it ships, and anything unsourced is rewritten or declined.
Two honest limits, because this post is specifically about correction. MistScale does not expose a typed-edge graph you author or query, and memory records carry no supersedes or version field, so retrieval ranks on similarity rather than on authority. Precedence between an old fact and its replacement is expressed through your world knowledge documents: unpublish or re-scope the source that is no longer true, and the character stops speaking from it. That is a coarser instrument than a per-fact correction edge, and it is worth knowing before you design around it. The document-level version of this problem is covered in version-aware NPC memory.
Start with one character rather than a world. Give it a lore set, talk to it, contradict something you told it last week, and watch what it does. That answers more than an architecture diagram will.
Common mistakes
- Overwriting old facts instead of preserving the correction history, which makes it impossible to debug why the character believes what it believes.
- Merging every player into one shared relationship state, which makes the character feel generic and inconsistent.
- Treating retrieval as memory. Similarity search surfaces relevant text and cannot express contradiction, supersession, or continuity.
- Letting the model guess when it is unsure, which manufactures lore and costs you the player's trust in the character permanently.
FAQ
What is the difference between a memory graph and a normal vector database?
A vector database finds similar text. A memory graph represents structure: what happened, what caused it, what it contradicts, and what now supersedes it. For persistent characters, that structure matters more than similarity on its own.
Why not just keep everything in the prompt?
Prompts are temporary. They work for short context and they give you no durable relationship state, no contradiction history, and no reliable way to correct a past fact.
How do I keep NPCs from hallucinating lore?
Let the character speak only from approved sources: stored memory, lore documents, and the character brief. If a specific cannot be traced to one of those, rewrite it or decline it.
Do I need a full graph system for every NPC?
No. Simple characters do fine on lighter memory. The graph earns its cost when you want returning-player continuity, evolving relationships, and lore consistency across a long-running world.