Module 3: Memory: The Agent That Remembers

5. Multi-turn conversations: holding the thread

Description

By the end of this lesson you'll be able to take the message array the memory node reconstructs and explain, turn by turn, which entity every reference a user writes within an ongoing conversation points to — a pronoun like "that one," a description like "the previous order," or no word at all naming the entity. And you'll be able to tell apart the case where that resolution is automatic and reliable from the case where it's genuinely ambiguous, and write the instruction line that makes the agent ask instead of guess.

This matters as soon as an agent moves from a one-message demo to a real conversation. A support customer with two open orders in the same chat writes, with no further context, "cancel my order" — and if the agent guesses which of the two, half the time it cancels the wrong one. Nobody notices this in a demo, because demos are almost always a single message. In production, at real volume, it's one of the costliest failures an agent can have: not because it fails loudly, but because it answers with complete confidence about the wrong entity.

Connection to the module: in the previous lesson you resolved where the history lives across sessions — a session ID that identifies the user and a store (Postgres or Redis) that survives a workflow restart. This lesson takes a step sideways: assuming that history is already complete and available, what does the agent do with it inside an ongoing conversation? That's today's job — how the model looks back several turns to resolve what a reference points to, and what happens when there's more than one possible candidate. You still won't see what happens when that same conversation gets so long the model starts losing precision over huge histories — that's context drift, and it's exactly lesson 6's topic. Here the conversations are short and manageable; the problem isn't size, it's which entity every word points to.

Reading backward: how the model finds the antecedent

Think of a long WhatsApp thread with a supplier, one of those that stretches all week with photos, prices, and changed minds. At some point the supplier writes: "Confirmed, we're going with the first option, I'll ship it Friday." If someone forwards you just that screenshot, with nothing else, "the first option" tells you absolutely nothing. But if you have the whole thread and scroll up a few messages, you find the exact point where two options were discussed — and one of them, a few messages earlier, was marked as "the first." You didn't guess: you read backward until you found the message that makes sense of the one now.

That, at its core, is what a language model does when it resolves a reference within a conversation. In computational linguistics the phenomenon has a name: when two expressions in a text point to the same entity it's called coreference, and the specific case where an expression (a pronoun, for example) appears after the thing it refers to is called anaphora (see Resources). "That order," "the previous one," "the same thing" are anaphors: they point back to something already said, instead of naming it again.

You already know, from lesson 2, that the AI Agent node builds a message array before every call, and that array — turns marked user and assistant — is the only thing the model receives; there's no open session on the model provider's side waiting for you, no "memory" saved separately. Resolving references isn't an extra step someone programs separately in n8n: it's the same model, in the same call where it generates the response, reading backward within that array to find which entity makes the current sentence make sense. There's no "reference resolution" module anywhere in the AI Agent node — there's a complete text array, and a model trained to read whole conversations, not standalone messages.

Worked example

You're going to build a support agent for Andes Market, an online store. The System Message carries, hardcoded, the data for two existing orders — this way you can follow the example without yet depending on a tool that queries a live database (that's Module 4's territory; here the focus is only memory).

# Agent's System Message
"You are the support assistant for Andes Market. You help customers
with questions about their orders. Order data in the system:
- Order #7734: status 'in transit', total $134, estimated delivery
  Thursday.
- Order #7601: status 'in preparation', total $76, not shipped yet."

Turn 1. The customer writes: "How's my order #7734 doing?" The agent responds: "Your order #7734 is in transit, estimated delivery is Thursday."

Turn 2. The customer writes: "And how much did I pay for that order?" Here's what the message array reaching the model looks like on this turn:

messages = [
  { role: "system",    content: "You are the support assistant for Andes
                                 Market... [order data]" },
  { role: "user",      content: "How's my order #7734 doing?" },
  { role: "assistant", content: "Your order #7734 is in transit, estimated
                                 delivery is Thursday." },
  { role: "user",      content: "And how much did I pay for that order?" }
]

What to expect. "That order" is an anaphor: it points backward. The model walks through the array and finds a single possible candidate — #7734, mentioned in turn 1 and again in its own response. There's no ambiguity because there's no other order in play yet. Expected response: "You paid $134 for order #7734."

Turn 3. The customer writes: "OK. Change the delivery address to Avenida Providencia 1234." Notice something different from the previous turns: this sentence has no pronoun or description pointing to an order — no "that one," no "the previous one," nothing. And yet, the expected response is: "Done, I updated the delivery address for order #7734 to Avenida Providencia 1234."

Interpretation: this isn't resolving a pronoun — it's topic continuity. The model reads the whole array and finds there's only one active order in the entire conversation, and that "changing the delivery address" is an action coherent with that order (which is also still in transit, not delivered). When there's a single candidate and the topic fits, the model resolves the reference even if the customer didn't even name it explicitly. This is the easy part: a single active entity, zero real ambiguity. The hard part starts once a second entity enters the picture.

When the reference is ambiguous: two candidates in play

Let's continue the same conversation with two more turns.

Turn 4. The customer writes: "And I also want to ask about my order #7601, how's that going?" The agent responds: "Order #7601 is in preparation, not shipped yet."

At this point, the message array has two orders mentioned: #7734 (turns 1-3) and #7601 (turn 4). Both are still cancellable — neither has been delivered yet.

Turn 5. The customer writes: "Cancel my order, please."

No word in that sentence distinguishes between the two orders. There's no "that one," no ordinal, no feature pointing to one more than the other. This is no longer an anaphor easily resolved by topic continuity — it's a genuinely ambiguous reference, with two equally valid antecedents.

What the agent responds depends on how the System Message is written:

# CONFIGURATION A — System Message with no instruction about ambiguity

What to expect — Configuration A. The model has to pick something, and some models pick without flagging that they hesitated — for example, the one mentioned most recently (#7601). The response can sound just as confident as any other: "Done, I cancelled order #7601." The problem is the customer might have meant #7734. There's no way to know from the outside, because the agent never asked — and the customer, if they don't check the exact number in the response, might not even notice the wrong order got cancelled.

# CONFIGURATION B — an explicit line is added to the System Message
"...If the customer asks for an action on 'their order' without
specifying the number, and more than one order has been mentioned in
this conversation, ask first which one they mean. Don't assume based
on the order in which they were mentioned."

What to expect — Configuration B. With that line, the expected response changes from the ground up: "You have two active orders in this conversation: #7734 (in transit) and #7601 (in preparation). Which one would you like to cancel?" The model is reading exactly the same message array as in Configuration A — the only thing that changed is that the System Message now explicitly tells it what to do when it detects more than one candidate: don't resolve silently, resolve by asking.

One tool that can help you reinforce this in delicate cases is n8n's Chat Memory Manager node: it lets you insert an additional message into the history — for example, a system-type one that says something like "Confirmed active entity: order #7734" — right after the customer confirms which order they mean, so it stays as a clear anchor if another ambiguous reference shows up later in the same conversation. It's a targeted tool for anchoring an entity, not for summarizing or trimming history — you'll see that in lesson 7.

Common mistakes

Assuming "memory is connected" equals "zero ambiguity," no matter how many entities come into play (conceptual). What happens: since the message array carries the complete history, it's assumed any reference resolves itself, with nobody checking what happens when a second entity of the same type shows up in the conversation. The agent works perfectly in testing (where it's almost always tested with a single order, a single ticket, a single customer mentioned) and fails in production, where real customers mix several topics into the same chat. Why it happens: complete memory solves where the information is, not which of two pieces of information applies when both are valid candidates — they're two different problems, and the first doesn't guarantee the second. How to spot it: if the agent was never tested with two entities of the same type mentioned in the same conversation (two orders, two tickets, two addresses), you don't know whether it resolves ambiguity well — you only know it handles the easy single-entity case well. How to fix it: add at least one test case with two active entities and a deliberately ambiguous reference ("cancel my order," no number), and check whether the agent asks or guesses.

Confusing conversational order with real chronological order when using words like "the previous one" (conceptual). What happens: a customer writes "and about the previous order, what was the address?" expecting "previous" to mean "the one I placed earlier in time" (by real purchase date), but the model can resolve it as "the one we mentioned a moment ago in the chat" — which isn't necessarily the same order if the conversation didn't follow the purchases' chronological order. Why it happens: "previous" is ambiguous between two different axes — discourse order (the last thing said) and calendar order (what happened first) — and the model has no way to know which one the customer meant if the System Message doesn't clarify it. How to spot it: if in your tests you mention orders in an order different from when they were purchased (for example, the most recent one first and then the oldest one) and then use "the previous one," check which of the two the model chose — it might surprise you. How to fix it: when the real chronological order matters for the business (billing, warranties, deadlines), ask the customer for the exact number instead of relying on "previous," or instruct the agent to explicitly ask which axis of "previous" applies.

Not verbalizing the entity's identifier in the agent's own responses (practical). What happens: the System Message is written so the agent responds with generic phrases like "your order is on its way" instead of "your order #7734 is on its way." It works fine while there's only one entity in play, but as soon as a second one enters, the history no longer has any turn where the number is written explicitly — neither in what the customer said (who also doesn't always repeat it) nor in what the agent responded. Why it happens: repeating the number in every response feels redundant to whoever writes the prompt, because within that specific response it's obvious which order is meant — but that obviousness doesn't travel: the model, in a later turn, only has the reinjected text, and if the text never said the number, it's not there to be found. How to spot it: check a conversation's history with more than one entity and look for whether the identifier appears explicitly in at least one turn near each mention — if it only appears implicitly ("your order"), the chain of references is more fragile than it looks. How to fix it: instruct the agent to include the exact identifier (order number, ticket number, whatever it is) every time it mentions it, even if it "sounds redundant" to a human reading a single turn — that redundancy is exactly what keeps the reference resolvable later on.

Exercises

Exercise 1 — A reference with no named entity. Go back to the Andes Market conversation up through turn 1 only (the customer asked about order #7734 and the agent responded that it's in transit). The customer writes on turn 2: "About what time does it arrive, roughly?" — mentioning no order. What does that reference resolve to, and why isn't it ambiguous despite not naming anything explicitly?

See solution

It resolves to order #7734, the only one mentioned up to that point in the message array. It isn't ambiguous because there's no other candidate competing: the model reads the complete history (system + turn 1 + turn 2), finds a single "order"-type entity active, and the question about "what time does it arrive" is topically coherent with that entity (which is also "in transit," with an estimated Thursday delivery). This is topic continuity, not resolving a pronoun — the same mechanism as turn 3 in the worked example.

Why it works: when there's a single active entity, the model doesn't need any explicit linguistic clue to know what's being discussed — the candidate's uniqueness does the work. Ambiguity only shows up when there are two or more valid candidates at the same time, as in Configuration A/B of the lesson.

Exercise 2 — Write the instruction that avoids guessing. A colleague shows you the System Message for an airline's support agent that handles flight changes. The agent can have, within the same conversation, more than one booking mentioned (the customer travels often and asks about several flights). The current System Message says nothing about what to do if the customer asks to "change my flight" without specifying which one. Write the line you'd add to the System Message to keep the agent from guessing.

See solution

Something along the lines of: "If the customer asks for an action on 'their flight' or 'their booking' without giving the booking number or the date, and more than one booking has been mentioned in this conversation, ask first which one they mean before making any change. Don't assume it's the one mentioned last."

Why it works: the instruction does two things at once — it detects the risk condition (more than one candidate entity) and gives the correct action for that condition (ask, don't guess). Without that line, the model can silently default to the most recently mentioned booking, which is a reasonable bias but not a guaranteed one, and at an airline a wrong flight change is an expensive mistake to fix.

Exercise 3 — Diagnosis with the complete history in view. An Andes Market support agent, on turn 6 of a conversation, applies a 10% discount to order #7601 when the customer had clearly asked, on turn 5, to apply it "to the order I mentioned first" — which was #7734, mentioned in turn 1, three turns before #7601. The message array that reached the model had all six turns, complete and in order, with nothing missing. Is this a memory problem? Is it the same kind of error you saw in this lesson?

See solution

It's not a memory problem — the history was complete, both orders and the order in which they were mentioned are there. The failure is one of reference resolution, but of a specific kind: "the one I mentioned first" is an ordinal reference over conversational order, not ambiguous in the sense of "two equally valid candidates" (here the customer did specify a clear criterion), but a case where the model reasoned incorrectly about which of the two met that criterion — it applied the discount to the one mentioned last instead of the first, inverting the order.

Why it works: telling apart types of failure within "reference resolution" — genuine ambiguity (two candidates with no criterion distinguishing them, as in Configuration A of this lesson) versus a reasoning error over a criterion that was clear (this exercise) — tells you whether the fix is "add an instruction to ask for clarification" or "check why the model got it wrong with an instruction that already had all the information to follow correctly." They're different problems with equally complete arrays.

Summary and next step

You've now seen that resolving a reference within a conversation isn't a separate step n8n runs on its own: it's the same model, reading backward through the message array memory reconstructed, finding which entity makes sense of "that one," "the previous one," or a sentence that doesn't even name the entity. As long as there's only one active candidate, that reading is reliable almost every time. As soon as a second candidate of the same type enters, the reference can become genuinely ambiguous — and there, the difference between an agent that silently guesses and one that asks first lies in an explicit line in the System Message, not in how big or "smart" the connected model is.

Before moving on you should be able to: read a message array with several entities mentioned and predict what a given reference resolves to, tell apart a case of ambiguous reference (two candidates with no criterion telling them apart) from a case of reasoning error over a criterion that was clear, and write the instruction line that makes an agent ask for clarification instead of assuming.

All of this assumed short conversations, five or six turns, where the whole array fits without a problem in any context window. The next lesson breaks that assumption: what happens to an agent when the conversation doesn't last six turns but sixty, and the history starts getting so long the model loses precision over parts of it — the phenomenon known as context drift.

Resources

  • How memory works — n8n Docs — confirms what each memory node stores: the turn history reinjected on every call, the foundation all of this lesson's reference resolution runs on.
  • Chat Memory Manager — n8n Docs — the node that lets you insert, review, or delete history messages directly; useful for anchoring an active entity when ambiguity is a real risk.
  • AI Agent node — n8n Docs — reference for the node and the ai_memory connection, already cited in Module 1 and in lesson 2 of this module.
  • Prompting best practices — Claude Docs — techniques for explicit, unambiguous instructions, the basis for the System Message line that asks the agent to ask before guessing.
  • Coreference — Wikipedia — the formal definition of the linguistic phenomenon behind "that order" and "the previous one": when two expressions refer to the same entity.