BLINKCADEAI GAME DEVELOPMENT
Sign In
Home Library Intelligence BC-010

How to Add Memory to an AI NPC

Quick answer An AI NPC should not remember everything the player has ever said. A better memory architecture separates information by purpose: recent conversation → current-session state → structured long-term facts → retrieved relevant memories → current game state Then, before the AI generates a response, the game provides only the memories relevant to the […]

AI NPCs
AI NPC memory

Quick answer

An AI NPC should not remember everything the player has ever said.

A better memory architecture separates information by purpose:

recent conversation → current-session state → structured long-term facts → retrieved relevant memories → current game state

Then, before the AI generates a response, the game provides only the memories relevant to the current situation.

A useful architecture looks like:

player interaction → identify memory candidates → score importance → store selected facts → retrieve relevant memories later → combine with current game state → generate response

This approach keeps prompts smaller, reduces inference cost, makes characters easier to debug, and prevents years of accumulated dialogue from overwhelming the model.

Real game systems are already moving toward this pattern. KRAFTON’s 2026 PUBG Ally implementation uses short-term memory for the current match and structured long-term memory across matches, storing information such as player preferences, shared personal details and prior match history.

The lesson is simple:

Good NPC memory is selective memory.


What does “memory” actually mean for an AI NPC?

Suppose the player meets our fictional merchant from the previous Blinkcade guide:

Mara Venn

During the first conversation, the player says:

“I’m Alex. I usually carry a pulse rifle.”

Ten minutes later:

“Have you found anything I’d like?”

Tomorrow, after starting the game again:

“Do you remember me?”

Those three interactions require several different kinds of memory.

The NPC needs to remember that:

the player’s name is Alex

and:

Alex prefers pulse rifles.

But it probably does not need to permanently remember:

Player said “thanks” at 8:42 PM.

That distinction is the foundation of a useful AI memory system.


The four memory layers I recommend

For most games, divide NPC memory into four layers:

1. WORKING MEMORY
Recent conversation

2. SESSION MEMORY
Important current-session events

3. LONG-TERM MEMORY
Persistent structured facts

4. WORLD STATE
Canonical facts owned by the game

They are not interchangeable.


1. Working memory: what just happened

Working memory gives the NPC enough recent context to understand the current conversation.

For example:

Player:
Who owns the refinery?

Mara:
Voss Industries.

Player:
Do you trust them?

The phrase:

“them”

only makes sense if Mara remembers the previous turn.

You might send the last:

4–12 dialogue turns

depending on your game.

Conceptually:

{
  "recentConversation": [
    {
      "speaker": "player",
      "text": "Who owns the refinery?"
    },
    {
      "speaker": "mara",
      "text": "Voss Industries."
    },
    {
      "speaker": "player",
      "text": "Do you trust them?"
    }
  ]
}

This memory should usually be temporary.

Once that conversation is no longer active, there is little reason to keep every sentence in the model context forever.

Current model APIs can support persistent conversational state if you want it. OpenAI’s Conversations API, for example, allows applications to maintain durable conversation objects across sessions, devices or jobs.

But persistent conversation storage and good game memory design are different problems.

Just because you can save every turn doesn’t mean you should feed every turn back into the NPC forever.


2. Session memory: what matters right now

Session memory stores significant things that happened during the current game session.

Example:

The player:

  • rescued Mara from raiders
  • told her they work for the resistance
  • purchased a thermal cloak
  • threatened one of her friends.

A session-memory record could be:

{
  "sessionMemories": [
    {
      "type": "event",
      "key": "rescued_mara",
      "value": true
    },
    {
      "type": "affiliation",
      "key": "player_claimed_faction",
      "value": "resistance"
    },
    {
      "type": "purchase",
      "item": "thermal_cloak"
    }
  ]
}

These facts may affect Mara’s behavior immediately.

For example:

“You already bought the cloak. Don’t tell me you lost it.”

That feels like memory.

But we’re not replaying an entire transcript.

We’re storing meaningful state.


3. Long-term memory: what survives between sessions

Long-term memory should contain information that remains useful tomorrow, next week or 30 hours later.

Examples:

{
  "playerName": "Alex",
  "preferredWeapon": "pulse_rifle",
  "relationship": 0.73,
  "helpedMara": true,
  "betrayedSmuggler": false,
  "favoriteDropLocation": "Old Harbor"
}

This closely resembles the approach NVIDIA describes for PUBG Ally: structured long-term memory stores player profile information, preferences and prior match history, while short-term memory tracks the current match.

Notice that these aren’t full transcripts.

They’re facts.

That’s usually the right design.


4. World state is not NPC memory

This distinction is critical.

Suppose:

The bridge was destroyed.

The mayor is dead.

Quest 14 is complete.

Player has 82 credits.

Those are not memories the language model should own.

They are canonical game state.

The game database should supply those facts when they’re relevant.

Why?

Because game state needs to be:

deterministic

authoritative

debuggable

consistent across systems.

If the mayor dies, the game knows the mayor is dead.

You don’t want Mara “remembering” that the mayor is alive because an old dialogue chunk was retrieved.

So the prompt may include:

{
  "currentWorldState": {
    "mayorAlive": false,
    "northBridge": "destroyed"
  }
}

The current game state always outranks an old memory.


Step 1: Extract memory candidates

Suppose the player says:

“My name’s Alex. I can’t stand plasma rifles. Give me a pulse rifle whenever you see one.”

The NPC system can extract possible memories:

[
  {
    "type": "identity",
    "key": "player_name",
    "value": "Alex"
  },
  {
    "type": "preference",
    "key": "weapon_dislike",
    "value": "plasma_rifle"
  },
  {
    "type": "preference",
    "key": "weapon_preference",
    "value": "pulse_rifle"
  }
]

Now evaluate whether they deserve storage.

Don’t blindly persist every sentence.


Step 2: Score memory importance

Give each candidate a usefulness score.

For example:

0.0 = irrelevant
1.0 = extremely important

Possible criteria:

Identity

Player name:

0.95

Preference

Favorite weapon:

0.75

Major relationship event

Player saved NPC:

0.95

Ordinary dialogue

Player said hello:

0.05

Temporary observation

Player is standing near a door:

0.01

Then:

if (memory.importance >= 0.6) {
  longTermMemory.store(memory);
}

The threshold can vary by memory type.

This gives your system a mechanism for forgetting by default.

That is desirable.


Step 3: Store structured facts when possible

Compare two approaches.

Transcript memory

"Yesterday Alex told Mara that he prefers pulse rifles because
plasma weapons remind him of an accident at Ceres Station..."

versus:

Structured memory

{
  "subject": "player",
  "type": "weapon_preference",
  "value": "pulse_rifle",
  "confidence": 0.92,
  "source": "player_statement"
}

The second representation is:

  • easier to query
  • cheaper to store in context
  • easier to update
  • easier to invalidate
  • easier to test.

You can still keep original text as provenance if useful.

But the game’s operational memory should usually be structured.


Step 4: Store episodic memories separately

Some experiences don’t fit neatly into a key/value pair.

For example:

Alex and Mara escaped the refinery together while Mara was injured.

That’s a narrative event.

You might store:

{
  "id": "memory_0182",
  "type": "episodic",
  "summary": "Alex helped Mara escape the refinery after she was wounded.",
  "participants": ["player", "mara"],
  "location": "voss_refinery",
  "emotionalWeight": 0.88,
  "timestamp": 184382,
  "importance": 0.91
}

Later Mara might say:

“After what happened at the refinery, I know I can trust you.”

That’s far more convincing than random generated nostalgia because it points to an actual game event.


Step 5: Retrieve memories instead of dumping them all into the prompt

Suppose Mara has accumulated:

1,500 memories.

The player says:

“What weapon do you think suits me?”

Don’t send all 1,500.

Retrieve memories related to:

player + weapons + preferences.

A semantic retrieval system can help here.

Semantic search uses embeddings to find information that is conceptually relevant even if it doesn’t use the same keywords.

Your game doesn’t have to use OpenAI’s retrieval implementation specifically.

The architecture is what matters:

Player message
↓
Create memory query
↓
Retrieve top relevant memories
↓
Filter by validity
↓
Add only selected memories to context

For example:

{
  "retrievedMemories": [
    {
      "type": "weapon_preference",
      "value": "pulse_rifle"
    },
    {
      "type": "episodic",
      "summary": "Alex disliked the recoil of a heavy railgun during training."
    }
  ]
}

Now Mara has just enough memory to answer.


Step 6: Filter retrieval using metadata

Semantic similarity alone isn’t enough.

Imagine the game contains memory for:

Mara
Kai
Juno
three different players
multiple campaign saves.

You need filters.

A memory record might include:

{
  "npcId": "mara",
  "playerId": "player_481",
  "campaignId": "campaign_12",
  "type": "preference",
  "createdAt": 184382
}

Then retrieve only memories where:

npc = mara
AND
player = player_481
AND
campaign = campaign_12

The principle is useful even if you use your own database.

Semantic relevance + deterministic filters is safer than semantic similarity alone.


Step 7: Handle contradictory memories

Players change.

Suppose Alex says early in the game:

“I love pulse rifles.”

Later:

“I’ve switched to shotguns. Pulse rifles feel weak now.”

Do not keep both as equally current facts.

Possible record:

{
  "type": "weapon_preference",
  "value": "shotgun",
  "supersedes": "memory_102",
  "updatedAt": 293840
}

Or maintain:

{
  "weaponPreference": {
    "value": "shotgun",
    "confidence": 0.91,
    "updatedAt": 293840
  }
}

Memories require lifecycle rules.

Otherwise your NPC becomes a database of contradictions.


Step 8: Add confidence

Not every statement is trustworthy.

Player says:

“I’m the emperor.”

Should Mara permanently believe:

{
  "player_is_emperor": true
}

Probably not.

Record source and confidence:

{
  "claim": "player_is_emperor",
  "value": true,
  "source": "player_statement",
  "confidence": 0.2
}

Compare:

{
  "claim": "player_is_resistance_member",
  "value": true,
  "source": "verified_quest_event",
  "confidence": 1.0
}

The game can distinguish:

what the player claimed

from:

what the game knows.

That’s extremely useful for roleplaying characters.

Mara might say:

“You say you’re the emperor. Sure.”

rather than treating the statement as canon.


Step 9: Give memories emotional weight

Not all experiences matter equally.

Imagine:

Event A

Player bought a health potion.

Event B

Player rescued Mara’s daughter.

Both are technically events.

They should not carry equal weight.

Store something like:

{
  "importance": 0.97,
  "emotionalValence": 0.92,
  "relationshipImpact": 0.85
}

Now retrieval can prioritize:

importance

alongside:

semantic similarity

and:

recency.

A useful conceptual score might be:

memory score =
semantic relevance
× importance
× validity
× recency modifier

You don’t need that exact formula.

But you need an explicit policy for why one memory appears and another does not.


Step 10: Forget things

Perfect memory is not necessarily believable.

Humans forget.

Characters can too.

You might define:

Permanent memories

major story events
identity
important relationships.

Slow-decay memories

preferences
ordinary interactions.

Session-only memories

temporary objectives.

Immediate-only memories

conversation wording.

For example:

player_name
→ permanent

saved_maras_daughter
→ permanent

favorite_drink
→ slow decay

player_said_good_morning
→ discard

Forgetting also saves money and reduces retrieval noise.


Step 11: Summarize old episodes

Suppose Mara and Alex have interacted 47 times.

Instead of storing:

47 verbose scenes,

you might periodically summarize:

Alex and Mara have developed a strong working relationship.
Alex has repeatedly helped Mara with smuggling problems.
Mara trusts Alex but remains uncomfortable discussing her family.

Keep the major episodic events separately.

This gives the model a high-level relationship picture without needing the entire history.


Step 12: Never let memory override authoritative game state

Suppose memory says:

Mara believes Alex owns a thermal cloak.

But the player sold it.

Current inventory says:

{
  "thermal_cloak": false
}

Current state wins.

The model prompt should separate:

CURRENT VERIFIED STATE
Player does not own Thermal Cloak.

NPC MEMORY
Mara remembers selling Alex a Thermal Cloak previously.

Now she can naturally say:

“Didn’t I sell you a cloak already?”

without incorrectly claiming:

“You’re wearing the cloak I sold you.”

Memory is perspective.

Game state is reality.

That distinction produces better characters.


Step 13: Build memory as a game mechanic

Memory shouldn’t exist merely to impress players technically.

Use it to create gameplay.

Examples:

Merchant

Remembers what you buy.

Companion

Learns preferred tactics.

Rival

Remembers defeats.

Guard

Remembers suspicious behavior.

Villager

Remembers whether you helped their family.

Quest giver

References previous solutions.

The PUBG Ally example is particularly interesting because memory affects practical cooperation: NVIDIA describes the companion remembering preferred weapons and favorite landing locations across matches and then acting on those preferences without needing to be reminded.

That’s more valuable than:

“Remember when we talked yesterday?”

The memory changes behavior.


Step 14: Keep memory explainable

When Mara says something surprising, developers need to know:

Why did she say that?

Log:

{
  "interaction": "mara_992",
  "retrievedMemoryIds": [
    "memory_103",
    "memory_188"
  ],
  "currentStateVersion": 42,
  "generatedResponse": "I saved a pulse rifle for you."
}

Then, during QA, you can inspect:

Memory 103:

Alex prefers pulse rifles.

Memory 188:

Mara promised to watch for one.

Now the behavior is explainable.

Without this, debugging AI character behavior becomes guesswork.


A practical memory schema

Here’s a reasonable starting point:

interface NPCMemory {
  id: string;

  npcId: string;
  playerId: string;
  campaignId: string;

  type:
    | "identity"
    | "preference"
    | "relationship"
    | "event"
    | "claim"
    | "promise";

  summary: string;

  structuredData?: Record<string, unknown>;

  importance: number;
  confidence: number;

  emotionalWeight?: number;
  relationshipImpact?: number;

  createdAt: number;
  updatedAt: number;

  expiresAt?: number;

  supersedes?: string;

  source:
    | "player_statement"
    | "npc_observation"
    | "verified_game_event";
}

That’s far better than a table containing:

NPC CHAT LOG

and nothing else.


The complete NPC memory request

Before model inference:

{
  "character": {
    "name": "Mara",
    "role": "merchant"
  },

  "currentState": {
    "location": "Blackwater Market",
    "playerCredits": 83
  },

  "recentConversation": [
    "..."
  ],

  "sessionMemory": [
    "Player visited the Frozen Relay."
  ],

  "retrievedLongTermMemory": [
    "Player prefers pulse rifles.",
    "Mara promised to save one for the player."
  ]
}

Then the AI has:

who it is

what is happening

what just happened

what matters from the past.

That’s enough.


Memory and cost

Memory increases context.

Context increases processing.

So the naive architecture:

send complete player history every turn

will scale poorly.

Imagine:

100 NPC conversations
×
5,000 tokens of history

versus:

100 NPC conversations
×
500 tokens of retrieved memory

The exact costs depend on your chosen provider/model.

But the direction is obvious.

Selective memory reduces:

  • latency
  • token usage
  • irrelevant context
  • contradictions.

This is one reason retrieval architectures are useful.


Memory and latency

Retrieval itself also costs time.

Your pipeline may become:

player speaks
↓
extract intent
↓
query memory database
↓
retrieve records
↓
build context
↓
model inference
↓
response

So measure each stage.

For example:

{
  "memoryRetrievalMs": 28,
  "contextBuildMs": 3,
  "modelLatencyMs": 410,
  "totalLatencyMs": 441
}

If memory retrieval takes:

800 ms

you have a problem.

Don’t optimize blindly.

Instrument the pipeline.


What real games are doing

PUBG Ally provides an unusually useful public example.

According to KRAFTON’s discussion with NVIDIA, the AI teammate uses structured memory across two timescales:

Short-term memory

recent speech and events inside the current match.

Long-term memory

player profile information and cross-match history, including:

  • player name
  • preferred weapons
  • favorite drop locations
  • personal details
  • match outcomes
  • notable shared moments.

That’s remarkably close to the architecture I’d recommend.

It also reinforces an important design lesson:

Memory becomes compelling when it changes future behavior.


What RAG is—and what it isn’t

You will often hear:

RAG

or:

retrieval-augmented generation

discussed alongside memory.

RAG means retrieving relevant information from an external knowledge source before generating an answer.

But remember:

world knowledge retrieval

and:

personal NPC memory

are related but different.

Mara retrieving:

the history of Blackwater Market

is world knowledge.

Mara retrieving:

Alex prefers pulse rifles

is personal memory.

They may use similar retrieval technology.

They should live in different logical systems.


The Blinkcade NPC memory architecture

Put everything together:

PLAYER MESSAGE
      ↓
RECENT CONVERSATION
      ↓
CURRENT GAME STATE
      ↓
MEMORY QUERY
      ↓
┌──────────────────────────┐
│ SESSION MEMORY           │
│ STRUCTURED FACTS         │
│ EPISODIC MEMORY          │
│ RELATIONSHIP STATE       │
└──────────────────────────┘
      ↓
FILTER + RANK
      ↓
SELECT TOP RELEVANT MEMORIES
      ↓
NPC AI MODEL
      ↓
DIALOGUE / INTENT
      ↓
VALIDATED GAME ACTION
      ↓
MEMORY CANDIDATE EXTRACTION
      ↓
STORE / UPDATE / DISCARD

Memory is a cycle.

Characters:

remember

and:

form new memories.


AI NPC memory QA checklist

Before shipping, test:

Identity

Does the NPC remember the player’s name?

Preference

Does a changed preference supersede the old one?

Session boundary

Does persistent memory survive restart?

Forgetting

Do trivial memories disappear?

Contradiction

Does current game state override stale memory?

Retrieval

Does the right memory appear when relevant?

Isolation

Can one player’s memory leak into another player’s account?

NPC isolation

Can Mara accidentally retrieve Kai’s memories?

Campaign isolation

Do New Game saves remain separate?

False claims

Does player dialogue become “truth” automatically?

Cost

How much additional context does memory add?

Latency

How long does retrieval take?

Explainability

Can developers see which memories influenced a response?

If you cannot answer those questions, the memory system isn’t finished.


Common AI NPC memory failures

NPC forgets everything between conversations

Cause: only recent chat context exists.

Fix: structured persistent memory.


NPC remembers too much

Cause: full chat history is continually replayed.

Fix: extraction + relevance retrieval.


NPC contradicts itself

Cause: old facts aren’t superseded.

Fix: version/update memory.


NPC believes player lies

Cause: player statements become verified facts.

Fix: source + confidence tracking.


NPC remembers something that no longer exists

Cause: memory overrides world state.

Fix: current game state remains authoritative.


NPC feels creepy

Cause: trivial personal details are stored and surfaced unnecessarily.

Fix: deliberately define what your game should remember.

More memory does not automatically equal a better character.


Blinkcade verdict

The right way to give an AI NPC memory is not:

Save every conversation forever.

It’s:

Turn important experiences into structured, retrievable game knowledge.

For Mara:

Player says something
↓
Memory system identifies useful facts
↓
Important memories are stored
↓
Old or contradictory memories are updated
↓
Later conversation triggers retrieval
↓
Only relevant memories enter the AI context
↓
Mara responds using past experience + current reality

The best NPC memory architecture has three qualities.

Selective

It remembers what matters.

Grounded

Current game state always remains authoritative.

Behavioral

Memories influence what the NPC does—not merely what it says.

That’s where AI NPC memory becomes more than a novelty.

A companion that remembers your favorite weapon and brings it to you later feels meaningfully different from a chatbot that merely says:

“I remember you.”

The first creates gameplay.

The second creates a demo.

If you’re building AI-driven characters, design memory as a game system first and an LLM context system second.

That’s the difference between a character that stores history and a character that actually seems to have lived through it.

Sources & verification

Last verified: September 3, 2026

Blinkcade original contribution: four-layer NPC memory architecture, structured memory schema, memory-candidate and importance model, fact/episode separation, confidence and supersession rules, memory-versus-world-state boundary, retrieval pipeline, memory QA checklist and Mara worked example.

CONTINUE LEARNINGBC-009

How to Build AI NPCs in Games

Quick answer The best way to build an AI NPC is not to hand complete control of the character to a language model. A reliable architecture looks more…

Read next guide →