Local AI Agents · State, memory and retrieval · Lesson 1 of 3
Conversation state versus durable memory
A model's "memory" of a conversation is a transcript your own code resends every turn, not storage — three concrete ways that transcript disappears, and the working, episodic, semantic and procedural memory taxonomy grounded directly in this course's own tool loop.
By the end, you can
- Explain why a model's conversation state is not durable memory, and name three concrete ways that state disappears (LA-9).
- Name the four agent memory types — working, episodic, semantic and procedural — and give a concrete example of each grounded in this course's own tool loop (LA-9).
- Identify which memory type a bounded local agent already has by default, and which require something built on purpose (LA-9).
Before you start
This is Lesson 1 of 3 in State, memory and retrieval, the module that follows Tool use and the agent loop and turns the course from "the agent can act" into "the agent can remember." It assumes The model underneath module's Tokens and context windows lesson, which already established that a context window is a shared token budget, not a message-count limit, and that once that budget fills, the oldest content gets dropped or summarized by whatever is managing the conversation. It also assumes Tool use and the agent loop's lab, Lab: building a first tool loop, whose script this lesson points to directly as a concrete, already-built example. No running model or install is required for this lesson.
A model's "memory" of a conversation is a transcript you resend, not storage
It is tempting to picture a running conversation as something the model itself is quietly holding onto, turn after turn. That is not what is happening, even on a hosted API built specifically for multi-turn use. OpenAI's own documentation on conversation state says so directly: "each text generation request is independent and stateless" — and to get anything that looks like a remembered conversation, "you can still implement multi-turn conversations by providing additional messages as parameters to your text generation request." The same page is explicit about what that requires in practice: "To manually share context across generated responses, include the model's previous response output as input, and append that input to your next request." There is no server-side memory happening automatically. Your own code is resending the transcript, every time, and the model is reading it fresh each request as if for the first time.
Local AI Agents' own tool loop makes this completely literal. In Tool use and the agent loop's lab, the `messages` list inside `run_loop()` is an ordinary Python list your own script builds, appends to, and passes as the `messages` field on every single call to Ollama's chat endpoint. Nothing about that list lives inside the model, inside Ollama's server process between requests, or anywhere else — it is a variable in your script's own memory, for exactly as long as your script keeps a reference to it and no longer. This is the plain, unglamorous fact underneath the word "memory" as it is usually used about a single conversation: it is a growing transcript, resent in full, not a store.
Where it actually disappears: three concrete ways
Given that a conversation's "memory" is just a transcript your code is holding and resending, it disappears in exactly the ways an ordinary variable or file would — no more mysteriously than that, once you name the three cases plainly:
None of these three is a bug. A local agent that needs to remember something past any one of them — past the script exiting, past the context window filling, past a brand-new session starting — needs somewhere else for that information to live, and a deliberate decision about what goes there. That "somewhere else" is what the rest of this module calls durable memory, and what this lesson's taxonomy, next, gives you the vocabulary to describe precisely rather than lumping everything under one vague word.
- **The process ends.** `messages` is a Python list living in your script's own memory. The moment the script exits — normally, by a crash, or because the machine restarts — that list and everything in it is gone. Nothing about running a chat loop causes it to be written anywhere durable unless your own code does that explicitly.
- **The context window fills up.** Tokens and context windows already covered this mechanism: every system instruction, every turn and every tool result counts against one shared token budget, and once a conversation would exceed it, the oldest content is the first to go — evicted from what the model actually sees, whether or not your own `messages` list still holds a copy of it in memory.
- **A new session starts fresh.** This is worth seeing directly in code you have already read: Tool use and the agent loop's lab script calls `run_loop(prompt)` once per prompt in its example list, and `run_loop()` creates a brand-new `messages = [{"role": "user", "content": user_message}]` on every call. The lab's two example exchanges — the add-tool request and the word-count request — never shared a single token of context with each other. That was not a limitation the lesson had to work around; it is what a fresh conversation actually is, by default, unless something is built specifically to carry information across it.
The memory-type taxonomy, grounded in what you have already built
"Memory," used loosely, hides several genuinely different things an agent might need to hold onto. Cognitive Architectures for Language Agents, an academic framework widely used as the reference vocabulary for language-agent memory, names four kinds precisely — and every one of them maps onto something concrete in this course, not an abstraction:
Working memory is the only one of the four this course's tool loop already has, by construction, and only for the lifetime of one `run_loop()` call. Episodic and semantic memory need something built on purpose — a place to write a fact or a past event down and read it back later, which is exactly what this module's remaining two lessons address: how that "somewhere" is found among a growing store (Lesson 2) and kept safe, scoped and eventually deleted (Lesson 3). Explicit procedural memory, this course has also already been building all along, one module at a time, in the form of code — the registry and dispatcher are as much a piece of this agent's memory as any note it might write to a file.
- **Working memory** — the paper's own words: "Working memory maintains active and readily available information as symbolic variables for the current decision cycle." Concretely, in this course: the `messages` list inside one call to Tool use and the agent loop's `run_loop()`. It is exactly what this lesson's first section described — real, but temporary, and gone the moment that call returns or the process exits.
- **Episodic memory** — "Episodic memory stores experience from earlier decision cycles. This can consist of ... history event flows ... or other representations of the agent's experiences." Concretely: a record that a specific past run happened — "the last time this customer asked about a refund, they were told to expect it within five business days" — tied to a particular prior event, not a standing fact.
- **Semantic memory** — "Semantic memory stores an agent's knowledge about the world and itself." Concretely: a durable fact that holds regardless of which past run it came from — "this customer is on the Pro plan," "the support team's refund limit is $50 without escalation." Semantic memory does not care which conversation first established the fact; it only cares that the fact is currently true.
- **Procedural memory** — the paper distinguishes two forms: "implicit knowledge stored in the LLM weights, and explicit knowledge written in the agent's code." Concretely, in this course, the explicit half is not hypothetical: Tool use and the agent loop's `TOOL_REGISTRY`, `dispatch()` and `validate_args()` are exactly explicit procedural memory — literally, in code, how this agent does things. The implicit half is whatever the base model already knows how to do — write a polite sentence, follow an instruction — that was never written down anywhere in your own project at all.
A worked example: one support agent, four kinds of memory
A support-reply agent handles one ticket at a time, using Tool use and the agent loop's registry-and-dispatcher pattern. Laid out by type:
Nothing about the working-memory transcript for today's ticket tells the agent any of the other three on its own — that is exactly the gap Lesson 2 and Lesson 3 exist to close.
- Working: the `messages` list for the ticket currently open — the customer's latest message, the agent's own tool calls and their results, all live only for this one exchange.
- Episodic: "this same customer emailed twice last month about a shipping delay, and both times asked to be contacted by phone, not email" — a record of specific past events, useful precisely because they are specific.
- Semantic: "this customer is on the Pro plan, which includes free expedited shipping" — a durable fact, true regardless of which past ticket it was first learned from, and just as true on a ticket that mentions it for the first time.
- Procedural: the explicit half is the agent's own tool registry (a `check_order_status` tool, a `refund_customer` tool, both from earlier modules); the implicit half is whatever the underlying model already knows about writing a polite, on-topic reply, which was never written into this project's code at all.
Accessibility notes
This lesson is text-first, with no images, audio, video or downloadable artifacts. All code and prose examples appear as plain inline or block text, readable and copyable by assistive technology and keyboard-only users. The practice exercise's model answer sits behind a native disclosure control that is reachable and operable by keyboard and correctly announced by screen readers. The knowledge check uses native radio-button inputs with a visible question and options, and posts its result to a live status region so assistive technology announces the outcome without a page reload.
Practice
Sort a returns agent's memory by type
A local agent handles product-return requests. During one ticket, a customer says: 'I'm returning the blue jacket from order ORD-7734. Note that I'm allergic to synthetic packing material, in case that matters for future exchanges.' The agent looks up the order using a tool, confirms the return, and replies. Its tool registry includes check_order_status and start_return, both written by the project's own developers. The underlying model itself was never specifically trained on this company's return policy.
- Label the current exchange's request-and-tool-call transcript. Which of the four memory types is it, and how long does this lesson say it naturally lasts?
- The packing-material allergy note is worth keeping for next time this customer orders something. Which memory type should hold it, and why does that type fit better than treating it as part of this ticket's own transcript?
- Name the two forms procedural memory takes according to this lesson, and say which form the check_order_status and start_return tools belong to.
- Suppose this same agent, next week, handles a brand-new ticket from a different customer. Using this lesson's three concrete disappearance cases, explain whether today's transcript will be present in that new ticket by default, and why.
Compare with a bounded first version
The current request-and-tool-call transcript is working memory — active, readily available information for this one decision cycle — and this lesson's own account says it lasts only for the current run: it disappears once the process ends, once it is evicted by a full context window, or once a new session starts fresh, whichever comes first. The allergy note is a durable fact, true regardless of which ticket it was first mentioned in, so it belongs in semantic memory rather than staying only inside this ticket's own transcript — leaving it in working memory alone means it is gone the moment this session ends, exactly the gap this lesson's taxonomy exists to name. Procedural memory has an implicit form (knowledge inside the model's own weights) and an explicit form (knowledge written in the agent's own code); check_order_status and start_return are explicit procedural memory, matching this course's own registry-and-dispatcher pattern from Tool use and the agent loop. Next week's new-customer ticket will not have today's transcript present by default: it is exactly the 'new session starts fresh' case this lesson named directly, the same way Tool use and the agent loop's lab script reinitializes messages on every call to run_loop() — nothing about starting a new ticket automatically carries a previous one's working memory forward, unless something was deliberately written to a more durable store first.
Knowledge check
Try the idea
Low-stakes practice only. This does not score, block progress or create a learner record.Sources and limits
This lesson synthesises the sources below into a practical learning model. It is not a security standard, legal advice or a guarantee that any particular agent design is safe.
- Conversation state — OpenAI. States that each text generation request is independent and stateless, and that multi-turn conversation requires manually including the model's previous response output as input appended to the next request.
- Cognitive Architectures for Language Agents — Sumers, Yao, Narasimhan and Griffiths (arXiv). Defines a language agent's working memory, episodic memory, semantic memory and procedural memory (implicit, in model weights, and explicit, in agent code).