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.
On this page
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:
- Write: what is worth saving, and does it replace something already saved?
- 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.
write: notes[topic] = fact (replaces any older fact)read: load notes for the topics this message needscontext = notes loaded + message- topic0dietfact0vegetarian
- session
- 1
1Session 1. The user mentions they are vegetarian. That is a lasting preference, so save it under
diet. - topic0diet1cityfact0vegetarian1Leeds
- 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. - topic0diet1cityfact0vegetarian1Leeds
- session
- 2
- loaded
- diet
3Session 2, a fresh chat: "Any quick dinner ideas?" This needs
dietbut notcity, so only the diet note is loaded. The suggestions are all vegetarian. - topic0diet1cityfact0vegetarian1Bristol
- 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.
- topic0diet1cityfact0vegetarian1Bristol
- session
- 3
- loaded
- city
5Later in session 3: "Find me a climbing gym nearby." Load
city. The model gets Bristol and searches there. - topic0diet1cityfact0vegetarian1Bristol
- notes
- 2
- sessions
- 3
6Two notes, a few tokens each, carried across three chats. Each call loaded only what it needed.
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.
The second version costs one extra question and avoids a confidently wrong answer.
Common mistakes
Try it yourself
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.
- "I work night shifts as a nurse."
- "Ugh, I'm so tired today."
- "Please always keep answers short, I read them on my phone."
- "My sister is visiting this weekend."
- "Here's my online banking password so you can check my balance: …"
Show a sample answer
- 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.
- This chat only. True today, false tomorrow. Saving moods makes future replies oddly fixated on them.
- Save. A clear, lasting preference about every future answer. This is exactly what long-term memory is for.
- This chat only, or save with an expiry date. It is useful this week and wrong next week. If saved, the date matters.
- 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
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.