Memory

Models do not remember between calls. Learn how apps fake memory with saved notes and summaries, and how to decide what to save, update and load.

13 minLesson 6 of 8
On this page
  1. Where memory actually lives
  2. A memory over three sessions
  3. The store in code
  4. Stale memory in action
  5. Common mistakes
  6. Try it yourself
  7. Check yourself
  8. What to practise next

You see your family doctor twice a year. They do not remember you; they see hundreds of people. But in the minute before you walk in, they read your file: allergies, current medication, what you agreed last time. A good file makes it feel like they remember. An empty file means starting over. A file that still says you smoke, ten years after you quit, is worse than either.

AI apps with "memory" work the same way. The model does not learn from your conversation as it happens. The app keeps a file and slips the right parts of it into the context before each call.

Where memory actually lives

A model's weights are fixed while you use it. Nothing you say changes them. So every kind of memory is the app storing text somewhere and sending some of it back later. There are three common layers.

  • The conversation itself. The history resent on every call, as in What Is Context. It lasts until the chat ends or the window trims it.
  • A running summary. When a chat gets long, the app replaces old turns with a short summary of what was said and decided. It keeps the gist in far fewer tokens, but details can be lost.
  • Long-term notes. Facts saved across chats: "vegetarian", "prefers short answers", "working on the billing project". A small set can be loaded every time. A large set is searched like any document collection, with the same retrieval tools.

Every memory system makes two decisions over and over:

  1. Write: what is worth saving, and does it replace something already saved?
  2. Read: which saved notes belong in the context for this call?

A memory over three sessions

Here is a small note store, keyed by topic, so a new fact on the same topic replaces the old one. Step through three separate chats.

Saving, updating and loading notesUse the arrows or ← → keys
write: notes[topic] = fact   (replaces any older fact)read:  load notes for the topics this message needscontext = notes loaded + message
  1. topic
    0diet
    fact
    0vegetarian
    session
    1

    1Session 1. The user mentions they are vegetarian. That is a lasting preference, so save it under diet.

  2. topic
    0diet
    1city
    fact
    0vegetarian
    1Leeds
    session
    1

    2They also say they live in Leeds. Save it under city. "I'm tired today" was also said, and is not saved: it will not be true tomorrow.

  3. topic
    0diet
    1city
    fact
    0vegetarian
    1Leeds
    session
    2
    loaded
    diet

    3Session 2, a fresh chat: "Any quick dinner ideas?" This needs diet but not city, so only the diet note is loaded. The suggestions are all vegetarian.

  4. topic
    0diet
    1city
    fact
    0vegetarian
    1Bristol
    session
    3

    4Session 3: "I moved to Bristol last month." Same topic, newer fact. Replace Leeds instead of adding a second city. Two cities side by side would be a contradiction waiting to happen.

  5. topic
    0diet
    1city
    fact
    0vegetarian
    1Bristol
    session
    3
    loaded
    city

    5Later in session 3: "Find me a climbing gym nearby." Load city. The model gets Bristol and searches there.

  6. topic
    0diet
    1city
    fact
    0vegetarian
    1Bristol
    notes
    2
    sessions
    3

    6Two notes, a few tokens each, carried across three chats. Each call loaded only what it needed.

1 / 6

The important step is the fourth one. If the store had only ever appended, the context in session 3 would hold both "lives in Leeds" and "moved to Bristol", and the model would have to work out which is current. Sometimes it would get it wrong.

The store in code

class Memory {
  constructor() {
    this.notes = new Map(); // topic -> { fact, saved }
  }
  remember(topic, fact, saved) {
    this.notes.set(topic, { fact, saved }); // newer replaces older
  }
  forget(topic) {
    this.notes.delete(topic);
  }
  recall(topics) {
    return topics
      .filter((t) => this.notes.has(t))
      .map((t) => `- ${t}: ${this.notes.get(t).fact} (saved ${this.notes.get(t).saved})`)
      .join("\n");
  }
}
 
const memory = new Memory();
memory.remember("diet", "vegetarian", "March");
memory.remember("city", "Leeds", "March");
memory.remember("city", "Bristol", "June");
console.log(memory.recall(["city"])); // - city: Bristol (saved June)
class Memory:
    def __init__(self):
        self.notes = {}  # topic -> (fact, saved)
 
    def remember(self, topic, fact, saved):
        self.notes[topic] = (fact, saved)  # newer replaces older
 
    def forget(self, topic):
        self.notes.pop(topic, None)
 
    def recall(self, topics):
        return "\n".join(
            f"- {t}: {self.notes[t][0]} (saved {self.notes[t][1]})"
            for t in topics if t in self.notes
        )
 
memory = Memory()
memory.remember("diet", "vegetarian", "March")
memory.remember("city", "Leeds", "March")
memory.remember("city", "Bristol", "June")
print(memory.recall(["city"]))  # - city: Bristol (saved June)

Real systems are messier in two places. Deciding what to save is usually done by a model reading the conversation and proposing notes, which means it can save the wrong thing. And choosing which notes to load is usually a similarity search rather than exact topics. The shape stays the same: write with replacement, read selectively, and keep the date.

Stale memory in action

The saved date is not decoration. Compare two versions of the same request, where the app's notes were never updated after a move.

Undated note, no ruleIllustrative example. Real replies vary.
System prompt
Notes about the user: - Lives in Leeds
You
Find me a climbing gym nearby.
Model
Here are three well-reviewed climbing gyms in Leeds: ...
Dated note, with a ruleIllustrative example. Real replies vary.
System prompt
Notes about the user (may be out of date): - Lives in Leeds (saved 14 months ago) If a note matters to the answer and is more than a year old, check it with the user before relying on it.
You
Find me a climbing gym nearby.
Model
Happy to. My notes say you live in Leeds, but that was over a year ago. Are you still there?

The second version costs one extra question and avoids a confidently wrong answer.

Common mistakes

Try it yourself

Try it: What is worth remembering

A user of a general-purpose assistant says these things over one chat. Decide for each one: save it as a long-term note, keep it only for this chat, or never store it. Give a reason.

  1. "I work night shifts as a nurse."
  2. "Ugh, I'm so tired today."
  3. "Please always keep answers short, I read them on my phone."
  4. "My sister is visiting this weekend."
  5. "Here's my online banking password so you can check my balance: …"
Show a sample answer
  1. Save. A lasting fact that changes useful answers, such as meal timing or sleep advice. Store it as a note the user can see and remove.
  2. This chat only. True today, false tomorrow. Saving moods makes future replies oddly fixated on them.
  3. Save. A clear, lasting preference about every future answer. This is exactly what long-term memory is for.
  4. This chat only, or save with an expiry date. It is useful this week and wrong next week. If saved, the date matters.
  5. Never store. Secrets do not belong in memory or, ideally, in the conversation at all. A good assistant should also tell the user not to share it.

The pattern: save what is lasting, useful and safe. When in doubt, ask the user ("Want me to remember that?") rather than guessing.

Check yourself

Quick check

An assistant with a memory feature recalls your favourite programming language in a brand-new chat. How?

A memory store holds "works at a bakery" from January and "works at a bookshop" from May. What is the best design fix?

What is the main trade-off of replacing old chat turns with a running summary?

What to practise next

Notes and documents are text you prepare in advance. Tools and MCP shows how a model can fetch fresh information itself, in the middle of answering. For what happens when a single chat runs too long, see Context Rot.