Module 3: Memory: The Agent That Remembers

3. Window Buffer Memory: the context window

Description

By the end of this lesson you'll be able to predict, given a Context Window Length value and which turn a conversation is on, exactly which previous interactions reach the model on the next call — and you'll be able to decide, for a concrete use case, whether the default value (5) is enough or whether you need to raise it, with judgment and not blindly.

This matters because "memory connected" isn't a guarantee the agent remembers everything that was said. A support agent handling a long, active conversation — the same customer, the same session, with no restart in between — can still forget something the customer said just a few minutes ago, simply because that data already fell out of the buffer. If you don't know that limit exists and how it behaves, you're going to misdiagnose the symptom: you're going to check the sessionKey, you're going to confirm the memory node is connected, and you're going to find everything in order — because the problem isn't there, it's in the window's size.

Connection to the module: in lesson 2 you saw the difference between having memory connected or not. Today you assume memory is connected and correctly configured in scope — that's already resolved — and you step into Simple Memory's internal mechanism: how it decides, turn by turn, what goes in and what falls out of the history it reinjects. You won't see yet memory that survives across different sessions or external databases (that's lesson 4), or how to design multi-turn conversations (lesson 5), or what happens when a conversation is so long the model starts losing precision even though all the information is technically present — that's a different problem, lesson 6's context drift. Today the scope is narrower and more mechanical: a fixed-size buffer, within a single live session.

Window memory: a fixed-size buffer

Think of a security camera recording in a loop onto a fixed-capacity memory card. While there's free space, every new clip simply gets added. But as soon as the card fills up, every new clip that comes in erases, automatically and with no warning, the oldest clip that was there — there's no trash bin, no way to recover it afterward: it's just not on the card anymore. The camera doesn't decide what's important and what isn't; it follows a mechanical, blind rule: the newest pushes the oldest out.

Window Buffer Memory works exactly like this, swapping video clips for a conversation's interactions. In n8n, the node that implements this pattern is the same one you already used in Module 1: Simple Memory — its internal technical name, memoryBufferWindow, is literally the pattern this lesson's title describes. The parameter that defines that memory card's size is called Context Window Length: a numeric field that ships, by default, with the value 5, and its own help text in the n8n editor sums up well what it does — it defines how many previous interactions the model receives as context on every new call.

An interaction, here, is the same as a complete turn: the customer's message plus the agent's response that followed it, not each loose message. With the default value at 5, the buffer holds up to 5 complete message-response pairs; in individual messages — not counting the System Message, which doesn't live inside the buffer and gets resent separately on every call — that's up to 10 messages.

Every time the agent finishes responding, that new interaction gets added to the buffer. If the buffer already had 5 interactions saved, the oldest one leaves to make room for the new one — just like the oldest clip on the security camera. That interaction that leaves doesn't stay saved "somewhere else" inside Simple Memory: as far as what the model can see on the next call, it simply stopped existing.

Worked example

You're going to go back to the TuTienda support agent, with Simple Memory connected just as you left it in Module 1 — Session Key tied to the conversation's real chatSessionId — but this time without touching Context Window Length: you leave it at its default value, 5.

# Node: Simple Memory (connected to the AI Agent's ai_memory)
memory.sessionKey          = "{{ $json.chatSessionId }}"   # stable for this whole conversation
memory.contextWindowLength = 5                              # default value, unmodified

Marta opens the support chat and holds a seven-turn conversation, all in the same active session, with no workflow restart in between. Here's what, turn by turn, the buffer has saved right before the model processes each new message:

TurnCustomer's messageBuffer the model receives on this turn
1"Hi, I'm Marta, my order is #6023."empty — conversation's first message
2"Do you ship to Medellín?"turn 1
3"Can I pay by bank transfer?"turns 1–2
4"Do you have a physical store in Bogotá?"turns 1–3
5"How long does a size exchange take?"turns 1–4
6"And the warranty, how long does it last?"turns 1–5 (the buffer reached its maximum capacity)
7"To recap: what was the order number I gave you at the start?"turns 2–6 (turn 1 has already been evicted)

The breaking point is between turn 6 and turn 7. At turn 6, the buffer still had all 5 complete interactions, including turn 1 — if Marta had asked about her order number there, the agent would have had it available. But right after the agent answered turn 6, the buffer reached 6 saved interactions (turns 1 through 6), exceeded its capacity of 5, and evicted the oldest one: turn 1 left. When turn 7 arrives, here's the message array the AI Agent node builds to call the model:

# Message array the model receives on turn 7
# (Context Window Length = 5 — turn 1 has already left the buffer)

messages = [
  { role: "system",    content: "You are the support assistant for TuTienda. Respond
                                 in English, in a warm, direct tone." },
  { role: "user",      content: "Do you ship to Medellín?" },                 # turn 2
  { role: "assistant", content: "Yes, we cover the whole country, including
                                 Medellín." },
  { role: "user",      content: "Can I pay by bank transfer?" },              # turn 3
  { role: "assistant", content: "Yes, we accept bank transfer in addition
                                 to card." },
  { role: "user",      content: "Do you have a physical store in Bogotá?" }, # turn 4
  { role: "assistant", content: "Yes, in Zona T." },
  { role: "user",      content: "How long does a size exchange take?" },     # turn 5
  { role: "assistant", content: "Between 3 and 5 business days from when we
                                 receive the item." },
  { role: "user",      content: "And the warranty, how long does it last?" }, # turn 6
  { role: "assistant", content: "6 months for manufacturing defects." },
  { role: "user",      content: "To recap: what was the order number I gave
                                 you at the start?" }                          # turn 7, new
]

What to expect. The model receives five complete interactions and the new message — but nowhere in that array does turn 1 appear, where Marta gave her name and order number #6023. An expected response: "I don't have that on hand at this point in the chat, could you share it with me again?" Notice what didn't change: the sessionKey stays the same throughout the whole conversation, n8n's process never restarted, and if you checked the workflow's complete execution log, turn 1 is still there, recorded. The data wasn't lost from the session — it was lost from the buffer Simple Memory decides to reinject on every call, which is the only thing the model can see.

If you had left contextWindowLength at 10 — like Configuration B in Module 1 — turn 7's result would be different: with only 6 accumulated interactions up to that point, none would have been evicted yet, turn 1 would still be in the buffer, and the agent would correctly respond "#6023." The default value isn't a configuration mistake on its own — it's simply what the node ships with, and in this seven-turn conversation with an anchor piece of data at turn 1, it turned out to be insufficient.

How much is enough: choosing the window's size

There's no universally correct number — it depends on the shape your use case's typical conversation takes, particularly how far back you need to go to retrieve a piece of data mentioned earlier.

Conversation typeReasonable Context Window Length rangeWhy
Standalone questions with no follow-up (hours, policies, general prices)3–5 (the default value is usually enough)The customer rarely refers back to something said more than 2-3 turns ago
Transactional support with an anchor piece of data at the start (order number, ticket)8–12That data might be needed at any point in a multi-step conversation
Collecting several pieces of data before acting (conversational form)10–15, and even better: don't rely only on the buffer — extract and save each piece of data as soon as it's mentioned (Module 4's topic)

Raising the value isn't free. Every interaction the buffer retains gets resent in full — again — on every new call to the model, so the token cost (and the latency of every response) grows with every turn you decide to keep. And there's a second limit, independent of this one: Context Window Length has no automatic relationship to the connected model's real context window — the per-call token limit that provider sets. You can configure a buffer that retains 50 long interactions and still approach or exceed the model's real limit if those messages are lengthy. They're two different limits: one you configure yourself in Simple Memory, the other is set by the model's provider, and neither one warns you on its own when the other is close to its cap.

Common mistakes

Raising Context Window Length to a very high number thinking that makes memory persistent (conceptual). What happens: someone notices the previous example's problem — the agent "forgets" something said a few turns ago — and fixes it by raising the value to 50 or 100, assuming the agent is now "going to remember everything, always." Days later, the same customer comes back in a new session (a different tab, a different chatSessionId) and the agent has no idea about the previous conversation — the adjustment didn't help for that case. Why it happens: Context Window Length only controls how many recent interactions survive within the same active session; it doesn't change the scope (sessionKey) or the storage — where that history lives and whether it survives a restart — which are the two decisions you already saw in lesson 1 of this module. A bigger buffer still lives in n8n's process RAM, tied to the same sessionKey. How to spot it: if the symptom is the agent forgetting something between different sessions — not between turns of the same active session — raising this number changes nothing; confirm it by testing first within a single long session. How to fix it: if the use case needs to remember across different sessions of the same customer, the solution isn't a bigger buffer — it's persistent memory with a stable per-customer sessionKey, the next lesson's topic.

Confusing "5" with "5 messages" instead of "5 interactions" (conceptual). What happens: someone miscalculates how much the agent can remember because they count loose messages — "the customer wrote 5 times, it should remember everything" —, without realizing every interaction counts as a complete pair (customer's message plus agent's response). With contextWindowLength = 5, the buffer retains up to 10 individual messages, not 5 — and also the reverse: if you count standalone "customer turns" instead of complete exchanges, you can underestimate how far back memory actually reaches. Why it happens: the field is called "Context Window Length" and the visible number is "5," with the editor not clarifying the exact unit at a glance — you have to read the help text or, as you did in this lesson's example, count complete interactions step by step. How to spot it: if your calculations of "how many turns back does the agent remember" don't match the real behavior you observe when testing, check whether you're counting messages or interactions. How to fix it: always count in interactions — a customer turn plus an agent turn equals one — like this lesson's worked-example table; that way the calculation matches what Simple Memory actually does.

Configuring a high value with no measurement of the real token and latency cost (practical). What happens: out of caution, with no measurement of the real effect, someone raises Context Window Length far above what the typical conversation needs. The agent starts responding slower and the cost per conversation goes up, because every interaction the buffer retains gets resent in full on every new call to the model, regardless of whether that interaction is still relevant to the current message. Why it happens: n8n doesn't show, in the Simple Memory node's own editor, how many tokens the configured buffer represents — that cost is only noticed indirectly, in response time or in the model provider's bill. How to spot it: compare the latency and the prompt size — visible in the model sub-node's execution panel — between a short conversation and a long one with the same contextWindowLength value; if it grows noticeably, the buffer is weighing on every call. How to fix it: set the value to the actual conversation size your use case needs — the previous section's table is a starting point — not the maximum that "just in case" seems safe, and remember that value is independent of the connected model's real context limit, which you can still exceed if the retained interactions are very long, no matter how many there are.

Exercises

Exercise 1 — Calculate the buffer. An agent has Context Window Length = 3. On turn 1 of a conversation, the customer says: "We're Empanadas del Sur, my contact is Carlos Ruiz." Turns 2, 3, and 4 are unrelated standalone questions (hours, location, payment methods). On turn 5, the customer asks: "Who did you say I talked to? I mean, do you have my contact's name?" Which interactions does the buffer have when the model processes turn 5, and can the agent respond "Carlos Ruiz"?

See solution

With Context Window Length = 3, the buffer only retains the 3 most recent interactions. Reconstructing turn by turn: when processing turn 2, the buffer has [1]; when processing turn 3, [1,2]; when processing turn 4, [1,2,3] (already full); when processing turn 5, turn 4 has already been added and turn 1 has already been evicted, so the buffer is [2,3,4] — turn 1, where the customer gave their contact's name, isn't there. The agent can't respond "Carlos Ruiz" with that information in the message array; it's most likely to ask for the data again.

Why it works: the same turn-by-turn reconstruction you used in this lesson's worked example — counting complete interactions and applying the rule that the oldest leaves when a new one comes in and the buffer is already full — applies no matter what Context Window Length value you configure.

Exercise 2 — Respond to a colleague. A colleague tells you: "let's raise Context Window Length to 50 on all our agents, that way we make sure they never forget anything." What would you tell them, using what you learned in this lesson?

See solution

Two concrete objections. First, a value that high isn't free: every interaction the buffer retains gets resent in full on every new call to the model, so 50 interactions means a considerably longer — and more expensive, and slower — prompt on every turn, even in short conversations that never needed that much history. Second, "never forget anything" isn't entirely true even at 50: Context Window Length is still a fixed limit — if a conversation reaches 51 interactions, number 1 still leaves — and that value is independent of the connected model's real context limit: if the retained interactions are long, you could approach or exceed that provider limit long before reaching 50, with no warning from the field itself. The sensible move is to size the value to how many turns back that particular agent actually needs to remember, not to max it out just in case.

Why it works: the criterion isn't "more is safer" — it's measuring the use case's real conversation pattern, like this lesson's range table, and balancing that against the per-call cost, which grows with every interaction you decide to retain.

Exercise 3 — Diagnosis: is this the same as lesson 1? An agent has Simple Memory correctly connected, with a stable sessionKey that doesn't change at any point in the conversation, and n8n's process hasn't restarted even once. Even so, on turn 12 of a long, continuous conversation, the customer says "like I mentioned at the start..." and the agent responds as if it has no idea what they're talking about. Is this a scope or a storage problem, like the ones you saw in lesson 1 of the module? If not, what's the most likely cause according to this lesson?

See solution

It's neither a scope problem nor a storage problem — both are resolved in this scenario: the sessionKey is stable and didn't change, and the process never restarted, so the conversation's complete history exists and is correctly indexed under that same key throughout the whole session. The most likely cause, given what you saw in this lesson, is the buffer's size: if Context Window Length is at its default value (5) or any value below 11, by the time turn 12 arrives the buffer has already evicted the interaction from the "start" of the conversation, regardless of the session technically still being the same one.

Why it works: separating symptoms by cause — scope and storage (lesson 1) versus the buffer's size (this lesson) — keeps you from checking the wrong pieces. Here lesson 1's two pieces are fine; what's missing to check is a completely different, third dial: Context Window Length.

Summary and next step

You now know exactly how Simple Memory behaves internally: a fixed-size buffer, defined by Context Window Length (5 by default), that retains a conversation's most recent interactions and evicts the oldest one every time a new one comes in and the buffer is already full — the same mechanism as a security camera recording in a loop. You can reconstruct, turn by turn, exactly which interactions the model sees at any point in a conversation, and you can decide with judgment whether the default value is enough for your use case or whether you need to adjust it, knowing what raising it costs.

Before moving on you should be able to: given a Context Window Length value and a turn number, reconstruct which interactions the buffer contains at that point; explain the difference between "5 interactions" and "5 messages"; and, given an agent that forgets something within the same active, correctly configured session, tell apart whether the cause is the buffer's size (this lesson) or something else related to scope or storage (lesson 1).

What this buffer doesn't solve — and it's exactly where the next lesson comes in — is what happens when the conversation ends and the same customer comes back tomorrow, in a completely new session. There, a bigger buffer isn't what's needed: a stable identity per real customer and storage that survives across sessions are. That's persistent memory, and it's lesson 4's topic.

Resources