Módulo 3: Memoria: el agente que recuerda

3. Window Buffer Memory: la ventana de contexto

Descripción

Al terminar esta lección vas a poder predecir, dado un valor de Context Window Length y el turno en que va una conversación, exactamente qué interacciones anteriores le llegan al modelo en la próxima llamada — y vas a poder decidir, para un caso de uso concreto, si el valor por defecto (5) alcanza o si necesitas subirlo, con criterio y no a ciegas.

Esto importa porque "memoria conectada" no es garantía de que el agente recuerde todo lo que se dijo. Un agente de soporte que atiende una conversación larga y activa —el mismo cliente, la misma sesión, sin ningún reinicio de por medio— puede seguir olvidando algo que el cliente dijo hace pocos minutos, simplemente porque ese dato ya salió del buffer. Si no sabes que ese límite existe y cómo se comporta, vas a diagnosticar mal el síntoma: vas a revisar el sessionKey, vas a confirmar que el nodo de memoria está conectado, y vas a encontrar todo en orden — porque el problema no está ahí, está en el tamaño de la ventana.

Conexión con el módulo: en la lección 2 viste la diferencia entre tener memoria conectada o no. Hoy asumes que la memoria sí está conectada y bien configurada en alcance —eso quedó resuelto— y entras al mecanismo interno de Simple Memory: cómo decide, turno a turno, qué entra y qué sale del historial que reinyecta. Todavía no vas a ver memoria que sobrevive entre sesiones distintas ni bases de datos externas (eso es la lección 4), ni cómo diseñar conversaciones de varios turnos (lección 5), ni qué pasa cuando una conversación es tan larga que el modelo empieza a perder precisión aunque toda la información esté técnicamente presente —eso es un problema distinto, el context drift de la lección 6—. Hoy el alcance es más angosto y más mecánico: un buffer de tamaño fijo, dentro de una sola sesión viva.

La memoria de ventana: un buffer de tamaño fijo

Piensa en una cámara de seguridad que graba en bucle sobre una tarjeta de memoria de capacidad fija. Mientras hay espacio libre, cada clip nuevo simplemente se agrega. Pero en cuanto la tarjeta se llena, cada clip nuevo que entra borra, de forma automática y sin aviso, el clip más viejo que había — no hay papelera, no hay forma de recuperarlo después: ya no está en la tarjeta. La cámara no decide qué es importante y qué no; sigue una regla mecánica y ciega: lo más nuevo empuja a lo más viejo hacia afuera.

Window Buffer Memory funciona exactamente así, cambiando clips de video por interacciones de una conversación. En n8n, el nodo que implementa este patrón es el mismo que ya usaste en el Módulo 1: Simple Memory — su nombre técnico interno, memoryBufferWindow, es literalmente el patrón que describe el título de esta lección. El parámetro que define el tamaño de esa tarjeta de memoria se llama Context Window Length: un campo numérico que trae, de fábrica, el valor 5, y su propio texto de ayuda en el editor de n8n resume bien qué hace — define cuántas interacciones anteriores recibe el modelo como contexto en cada llamada nueva.

Una interacción, acá, es lo mismo que un turno completo: el mensaje del cliente más la respuesta del agente que le siguió, no cada mensaje suelto. Con el valor por defecto en 5, el buffer guarda hasta 5 pares completos de mensaje-respuesta; en mensajes individuales —sin contar el System Message, que no vive dentro del buffer y se reenvía aparte en cada llamada— eso son hasta 10 mensajes.

Cada vez que el agente termina de responder, esa interacción nueva se agrega al buffer. Si el buffer ya tenía 5 interacciones guardadas, la más antigua sale para hacerle espacio a la nueva — igual que el clip más viejo en la cámara de seguridad. Esa interacción que sale no queda guardada "en otro lado" dentro de Simple Memory: para efectos de lo que el modelo puede ver en la próxima llamada, simplemente dejó de existir.

Ejemplo trabajado

Vas a retomar el agente de soporte de TuTienda, con Simple Memory conectada tal como la dejaste en el Módulo 1 —Session Key atado al chatSessionId real de la conversación— pero esta vez sin tocar Context Window Length: la dejas en su valor por defecto, 5.

# Nodo: Simple Memory (conectado a ai_memory del AI Agent)
memory.sessionKey          = "{{ $json.chatSessionId }}"   # estable durante toda esta conversación
memory.contextWindowLength = 5                              # valor por defecto, sin modificar

Marta abre el chat de soporte y sostiene una conversación de siete turnos, todos en la misma sesión activa, sin ningún reinicio del workflow de por medio. Así se ve, turno a turno, qué interacciones tiene guardadas el buffer justo antes de que el modelo procese cada mensaje nuevo:

TurnoMensaje del clienteBuffer que recibe el modelo en este turno
1"Hola, soy Marta, mi pedido es el #6023."vacío — primer mensaje de la conversación
2"¿Hacen envíos a Medellín?"turno 1
3"¿Puedo pagar con transferencia?"turnos 1–2
4"¿Tienen tienda física en Bogotá?"turnos 1–3
5"¿Cuánto tarda un cambio de talla?"turnos 1–4
6"¿Y la garantía, cuánto dura?"turnos 1–5 (el buffer llegó a su capacidad máxima)
7"Recapitulando: ¿cuál era el número de pedido que te di al principio?"turnos 2–6 (el turno 1 ya fue expulsado)

El punto de quiebre está entre el turno 6 y el turno 7. En el turno 6, el buffer todavía tenía las 5 interacciones completas, incluyendo el turno 1 — si Marta hubiera preguntado ahí por su número de pedido, el agente lo habría tenido disponible. Pero justo después de que el agente respondió el turno 6, el buffer llegó a 6 interacciones guardadas (turnos 1 al 6), superó su capacidad de 5, y expulsó a la más antigua: el turno 1 salió. Cuando llega el turno 7, este es el arreglo de mensajes que arma el nodo AI Agent para llamar al modelo:

# Arreglo de mensajes que recibe el modelo en el turno 7
# (Context Window Length = 5 — el turno 1 ya salió del buffer)

messages = [
  { role: "system",    content: "Eres el asistente de soporte de TuTienda. Responde
                                 en español, en tono cercano y directo." },
  { role: "user",      content: "¿Hacen envíos a Medellín?" },                 # turno 2
  { role: "assistant", content: "Sí, cubrimos todo el país, incluida Medellín." },
  { role: "user",      content: "¿Puedo pagar con transferencia?" },           # turno 3
  { role: "assistant", content: "Sí, aceptamos transferencia bancaria además
                                 de tarjeta." },
  { role: "user",      content: "¿Tienen tienda física en Bogotá?" },          # turno 4
  { role: "assistant", content: "Sí, en la Zona T." },
  { role: "user",      content: "¿Cuánto tarda un cambio de talla?" },         # turno 5
  { role: "assistant", content: "Entre 3 y 5 días hábiles desde que recibimos
                                 la prenda." },
  { role: "user",      content: "¿Y la garantía, cuánto dura?" },              # turno 6
  { role: "assistant", content: "6 meses por defectos de fábrica." },
  { role: "user",      content: "Recapitulando: ¿cuál era el número de pedido
                                 que te di al principio?" }                     # turno 7, nuevo
]

Qué esperar. El modelo recibe cinco interacciones completas y el mensaje nuevo — pero en ninguna parte de ese arreglo aparece el turno 1, donde Marta dio su nombre y el número de pedido #6023. Una respuesta esperable: "No tengo ese dato a la mano en este momento del chat, ¿me lo puedes compartir de nuevo?" Nota lo que no cambió: el sessionKey sigue siendo el mismo durante toda la conversación, el proceso de n8n no se reinició, y si revisaras el log completo de ejecución del workflow, el turno 1 sigue estando ahí, registrado. El dato no se perdió de la sesión — se perdió del buffer que Simple Memory decide reinyectar en cada llamada, que es lo único que el modelo puede ver.

Si hubieras dejado contextWindowLength en 10 —como en la Configuración B del Módulo 1— el resultado del turno 7 sería distinto: con solo 6 interacciones acumuladas hasta ese punto, ninguna se habría expulsado todavía, el turno 1 seguiría en el buffer, y el agente respondería correctamente "#6023". El valor por defecto no es un error de configuración en sí mismo — es simplemente el que trae el nodo de fábrica, y en esta conversación de siete turnos con un dato ancla en el turno 1, resultó insuficiente.

Cuánto es suficiente: eligiendo el tamaño de la ventana

No hay un número universal correcto — depende de la forma que tiene la conversación típica de tu caso de uso, en particular de qué tan atrás necesitas volver a buscar un dato mencionado antes.

Tipo de conversaciónRango razonable de Context Window LengthPor qué
Preguntas sueltas sin seguimiento (horarios, políticas, precios generales)3–5 (el valor por defecto suele alcanzar)Rara vez el cliente vuelve a referirse a algo dicho hace más de 2-3 turnos
Soporte transaccional con un dato ancla al inicio (número de pedido, ticket)8–12Ese dato puede necesitarse en cualquier punto de una conversación de varios pasos
Recolección de varios datos antes de actuar (formulario conversacional)10–15, y mejor aún: no depender solo del buffer — extraer y guardar cada dato apenas se menciona (tema del Módulo 4)

Subir el valor no es gratis. Cada interacción que el buffer retiene se reenvía completa —de nuevo— en cada llamada nueva al modelo, así que el costo en tokens (y la latencia de cada respuesta) crece con cada turno que decides conservar. Y hay un segundo límite, independiente de este: Context Window Length no tiene ninguna relación automática con la ventana de contexto real del modelo conectado —el límite de tokens por llamada que ese proveedor fija—. Puedes configurar un buffer que retenga 50 interacciones largas y aun así acercarte o exceder el límite real del modelo si esos mensajes son extensos. Son dos límites distintos: uno lo configuras tú en Simple Memory, el otro lo fija el proveedor del modelo, y ninguno de los dos avisa por sí solo cuándo el otro está cerca de su tope.

Errores comunes

Subir Context Window Length a un número muy alto pensando que eso vuelve la memoria persistente (conceptual). Qué pasa: alguien nota el problema del ejemplo anterior —el agente "olvida" algo dicho hace pocos turnos— y lo resuelve subiendo el valor a 50 o 100, dando por hecho que ahora el agente "va a recordar todo, siempre". Días después, el mismo cliente vuelve en una sesión nueva (otra pestaña, otro chatSessionId) y el agente no tiene ni idea de la conversación anterior — el ajuste no sirvió para ese caso. Por qué pasa: Context Window Length solo controla cuántas interacciones recientes sobreviven dentro de la misma sesión activa; no cambia el alcance (sessionKey) ni el almacenamiento —dónde vive ese historial y si sobrevive un reinicio—, que son las dos decisiones que ya viste en la lección 1 de este módulo. Un buffer más grande sigue viviendo en la memoria RAM del proceso de n8n, atado al mismo sessionKey. Cómo detectarlo: si el síntoma es que el agente olvida algo entre sesiones distintas —no entre turnos de la misma sesión activa—, subir este número no cambia nada; confírmalo probando primero dentro de una sola sesión larga. Cómo corregirlo: si el caso de uso necesita recordar entre sesiones distintas del mismo cliente, la solución no es un buffer más grande — es memoria persistente con un sessionKey estable por cliente, tema de la próxima lección.

Confundir "5" con "5 mensajes" en vez de "5 interacciones" (conceptual). Qué pasa: alguien calcula mal cuánto puede recordar el agente porque cuenta mensajes sueltos —"el cliente escribió 5 veces, debería recordar todo"—, sin darse cuenta de que cada interacción cuenta como un par completo (mensaje del cliente más respuesta del agente). Con contextWindowLength = 5, el buffer retiene hasta 10 mensajes individuales, no 5 — y también al revés: si cuentas "turnos de cliente" sueltos en vez de intercambios completos, puedes subestimar cuánto atrás llega realmente la memoria. Por qué pasa: el campo se llama "Context Window Length" y el número visible es "5", sin que el editor aclare a simple vista la unidad exacta — hay que leer el texto de ayuda o, como hiciste en el ejemplo de esta lección, contar interacciones completas paso a paso. Cómo detectarlo: si tus cálculos de "cuántos turnos atrás recuerda el agente" no coinciden con el comportamiento real que observas al probar, revisa si estás contando mensajes o interacciones. Cómo corregirlo: cuenta siempre en interacciones —turno de cliente más turno de agente, igual a uno—, como en la tabla del ejemplo trabajado; así el cálculo coincide con lo que Simple Memory realmente hace.

Configurar un valor alto sin medir el costo real en tokens y latencia (práctico). Qué pasa: por precaución, sin medir el efecto real, alguien sube Context Window Length muy por encima de lo que la conversación típica necesita. El agente empieza a responder más lento y el costo por conversación sube, porque cada interacción que el buffer retiene se reenvía completa en cada llamada nueva al modelo, sin importar si esa interacción sigue siendo relevante para el mensaje actual. Por qué pasa: n8n no muestra, en el propio editor del nodo Simple Memory, cuántos tokens representa el buffer configurado — ese costo solo se nota indirectamente, en el tiempo de respuesta o en la factura del proveedor del modelo. Cómo detectarlo: compara la latencia y el tamaño del prompt —visible en el panel de ejecución del sub-nodo del modelo— entre una conversación corta y una larga con el mismo valor de contextWindowLength; si crece de forma notoria, el buffer está pesando en cada llamada. Cómo corregirlo: ajusta el valor al tamaño real de conversación que tu caso de uso necesita —la tabla de la sección anterior es un punto de partida—, no al máximo que "por si acaso" te parezca seguro, y recuerda que ese valor es independiente del límite de contexto real del modelo conectado, que puedes exceder igual si las interacciones retenidas son muy largas, sin importar cuántas sean.

Ejercicios

Ejercicio 1 — Calcula el buffer. Un agente tiene Context Window Length = 3. En el turno 1 de una conversación, el cliente dice: "Somos Empanadas del Sur, mi contacto es Carlos Ruiz." Los turnos 2, 3 y 4 son preguntas sueltas sin relación (horario, ubicación, formas de pago). En el turno 5, el cliente pregunta: "¿Con quién dijiste que hablé? O sea, ¿tienes el nombre de mi contacto?" ¿Qué interacciones tiene el buffer cuando el modelo procesa el turno 5, y puede el agente responder "Carlos Ruiz"?

Ver solución

Con Context Window Length = 3, el buffer solo retiene las 3 interacciones más recientes. Reconstruyendo turno a turno: al procesar el turno 2, el buffer tiene [1]; al procesar el turno 3, [1,2]; al procesar el turno 4, [1,2,3] (ya lleno); al procesar el turno 5, el turno 4 ya se agregó y el turno 1 ya fue expulsado, así que el buffer es [2,3,4] — el turno 1, donde el cliente dio el nombre de su contacto, no está ahí. El agente no puede responder "Carlos Ruiz" con esa información en el arreglo de mensajes; lo más probable es que pida el dato de nuevo.

Por qué funciona: la misma reconstrucción turno a turno que usaste en el ejemplo trabajado de esta lección —contar interacciones completas y aplicar la regla de que la más antigua sale cuando entra una nueva y el buffer ya está lleno— aplica sin importar el valor de Context Window Length que configures.

Ejercicio 2 — Responde a un colega. Un colega te dice: "vamos a subir Context Window Length a 50 en todos nuestros agentes, así nos aseguramos de que nunca olviden nada." ¿Qué le responderías, usando lo que aprendiste en esta lección?

Ver solución

Dos objeciones concretas. Primero, un valor tan alto no es gratis: cada interacción que el buffer retiene se reenvía completa en cada llamada nueva al modelo, así que 50 interacciones significa un prompt bastante más largo —y más caro, y más lento— en cada turno, incluso en conversaciones cortas donde nunca se necesitó tanto historial. Segundo, "nunca olvide nada" no es del todo cierto ni con 50: Context Window Length sigue siendo un límite fijo —si una conversación llega a 51 interacciones, la número 1 igual sale—, y ese valor es independiente del límite de contexto real del modelo conectado: si las interacciones retenidas son largas, podrías acercarte o exceder ese límite del proveedor mucho antes de llegar a 50, sin ninguna advertencia del propio campo. Lo razonable es dimensionar el valor según cuántos turnos atrás realmente necesita recordar ese agente en particular, no subirlo al máximo por si acaso.

Por qué funciona: el criterio no es "más es más seguro" — es medir el patrón real de conversación del caso de uso, como la tabla de rangos de esta lección, y balancear eso contra el costo por llamada, que crece con cada interacción que decides retener.

Ejercicio 3 — Diagnóstico: ¿es esto lo mismo que la lección 1? Un agente tiene Simple Memory correctamente conectada, con un sessionKey estable que no cambia en ningún momento de la conversación, y el proceso de n8n no se ha reiniciado ni una vez. Aun así, en el turno 12 de una conversación larga y continua, el cliente dice "como te comenté al principio..." y el agente responde como si no supiera de qué le está hablando. ¿Es esto un problema de alcance o de almacenamiento, como los que viste en la lección 1 del módulo? Si no, ¿cuál es la causa más probable según esta lección?

Ver solución

No es un problema de alcance ni de almacenamiento — ambos están resueltos en este escenario: el sessionKey es estable y no cambió, y el proceso nunca se reinició, así que el historial completo de la conversación existe y está correctamente indexado bajo esa misma clave durante toda la sesión. La causa más probable, dado lo que viste en esta lección, es el tamaño del buffer: si Context Window Length está en su valor por defecto (5) o en cualquier valor menor a 11, para cuando llega el turno 12 el buffer ya expulsó la interacción del "principio" de la conversación, sin importar que la sesión siga siendo, técnicamente, la misma.

Por qué funciona: separar los síntomas por causa —alcance y almacenamiento (lección 1) frente al tamaño del buffer (esta lección)— evita que revises las piezas equivocadas. Aquí las dos piezas de la lección 1 están bien; lo que falta revisar es un tercer dial completamente distinto: Context Window Length.

Resumen y siguiente paso

Ya sabes exactamente cómo se comporta Simple Memory por dentro: un buffer de tamaño fijo, definido por Context Window Length (5 de fábrica), que retiene las interacciones más recientes de una conversación y expulsa la más antigua cada vez que entra una nueva y el buffer ya está lleno — el mismo mecanismo de una cámara de seguridad grabando en bucle. Puedes reconstruir, turno a turno, exactamente qué interacciones ve el modelo en cualquier punto de una conversación, y puedes decidir con criterio si el valor por defecto alcanza para tu caso de uso o si necesitas ajustarlo, sabiendo qué cuesta subirlo.

Antes de avanzar deberías poder: dado un valor de Context Window Length y un número de turno, reconstruir qué interacciones contiene el buffer en ese punto; explicar la diferencia entre "5 interacciones" y "5 mensajes"; y, dado un agente que olvida algo dentro de una misma sesión activa y bien configurada, distinguir si la causa es el tamaño del buffer (esta lección) o algo distinto de alcance o almacenamiento (lección 1).

Lo que este buffer no resuelve —y es exactamente donde entra la siguiente lección— es qué pasa cuando la conversación termina y el mismo cliente vuelve mañana, en una sesión completamente nueva. Ahí no hace falta un buffer más grande: hace falta una identidad estable por cliente real y un almacenamiento que sobreviva entre sesiones. Eso es memoria persistente, y es el tema de la lección 4.

Recursos