Módulo 3: Memoria: el agente que recuerda

1. Introducción: el agente que recuerda

Descripción

Al terminar esta lección vas a poder explicar por qué "conectar memoria" no es un interruptor único, sino dos decisiones independientes —qué identidad usas para agrupar el historial, y dónde guardas ese historial—, y vas a poder ubicar, dado un síntoma de un agente que "no recuerda", cuál de esas dos decisiones falló. También vas a tener el mapa completo de las siete lecciones que vienen en este módulo.

Esto importa porque el síntoma "el agente no recuerda" no tiene una sola causa. Un cliente que escribe hoy y mañana esperando que el agente siga el hilo de su caso —un reclamo, una consulta de RR. HH., una negociación de precio— no está pidiendo un capricho: está asumiendo lo mismo que asumiría de una persona real. Cuando el agente falla ahí, casi siempre no es porque "la memoria esté rota" en abstracto, sino porque una de dos piezas concretas está mal configurada, y sin saber distinguirlas terminas tocando la que no era.

Conexión con el módulo: en la lección 5 del Módulo 1 ya conectaste una pieza de memoria (Simple Memory) a tu primer agente, con un sessionKey y un contextWindowLength, y viste que resolvía la continuidad entre el turno 1 y el turno 2 de una misma conversación. Esta lección retoma esa pieza para mostrar algo que esa primera vez no era el punto: esa continuidad de turno-a-turno es solo una de las cosas que "memoria" puede resolver, y hay al menos otras dos que este módulo cubre a fondo — persistir entre sesiones distintas del mismo cliente, y no degradarse cuando la conversación se alarga. Esta lección no repite el ejemplo del pedido #4521 turno a turno tal como lo viste ahí; lo extiende. Tampoco vas a ver todavía la comparación práctica, en vivo, entre un agente que olvida y uno que no —eso es exactamente el trabajo de la lección 2, justo después de esta.

Un agente sin memoria es un chatbot de un mensaje

Imagina un mostrador de atención al cliente. Detrás está la misma persona todo el día, pero con una particularidad: cada vez que alguien le habla —incluso si es la tercera frase de la misma conversación, dicha diez segundos después de la anterior— actúa como si lo viera por primera vez. Le pide de nuevo su nombre, su número de cuenta, el motivo de la visita. Y si ese mismo cliente vuelve mañana a preguntar "oye, ¿qué pasó con lo de ayer?", la respuesta honesta es "no sé de qué me hablas" —no por grosería, sino porque no queda ningún rastro de la conversación anterior en su cabeza.

Así se comporta, por defecto, un modelo de lenguaje. Cada llamada al modelo es una invocación aislada: no hay ningún hilo invisible que conecte una llamada con la siguiente, salvo lo que tú mismo le reenvíes dentro del prompt. Cuando en la lección 5 del Módulo 1 viste que el nodo AI Agent expone una conexión opcional ai_memory, esa pieza es exactamente el mecanismo que captura lo que ya se dijo y lo vuelve a inyectar en el contexto antes de que el modelo razone el mensaje nuevo. Sin ella, no es que el agente "tenga mala memoria" — es que no hay memoria que gestionar en absoluto, y cada mensaje se procesa como si fuera el único que ese agente ha visto jamás.

Pero "conectar memoria" tampoco es una sola pregunta con una sola respuesta. Son dos decisiones distintas, y puedes acertar en una y fallar en la otra:

  • Alcance: ¿bajo qué identidad agrupas el historial? Puede ser el id de una ventana de chat que dura mientras esa pestaña siga abierta, o puede ser algo estable del cliente real —su teléfono, su id de cuenta— que es el mismo hoy y mañana.
  • Almacenamiento: ¿dónde vive ese historial una vez agrupado? Puede vivir en la memoria RAM del propio proceso de n8n, que desaparece si el proceso se reinicia o si cambia el worker que atiende la petición, o puede vivir en una base de datos real que sobrevive a ambas cosas.

Ejemplo trabajado: el mismo pedido, tres configuraciones de memoria

Vuelve al agente de soporte de TuTienda de la lección 5 del Módulo 1, con su tool get_order_status. Vamos a correr la misma pregunta contra tres configuraciones de memoria, para ver dónde falla cada una por separado.

# CONFIGURACIÓN A — sin memoria conectada
memory                = ninguna     # ai_memory sin conexión
prompt.systemMessage  = "Eres el asistente de soporte de TuTienda..."
tool.name             = "get_order_status"

Turno 1 (10:03 a. m., mismo chat): "¿Dónde está mi pedido #4521?" El agente llama a get_order_status, obtiene "en tránsito, entrega estimada 24 de julio" y responde correctamente.

Turno 2 (10:03:15 a. m., quince segundos después, mismo chat): "¿Y cuándo llega?"

Qué esperar — Configuración A. Sin memoria, cada invocación del nodo AI Agent solo ve el mensaje que acaba de llegar — nada de lo dicho quince segundos antes. El modelo no tiene forma de saber que "llega" se refiere al pedido 4521; responde algo como "¿me puedes dar el número de pedido?", aunque el cliente ya lo dio en la misma conversación.

# CONFIGURACIÓN B — Simple Memory, alcance por sesión de chat
memory.node                = "Simple Memory"
memory.sessionKey          = "{{ $json.chatSessionId }}"   # lo genera el widget al abrir el chat
memory.contextWindowLength = 10

Turnos 1 y 2, mismo día, misma pestaña de chat: funcionan como ya viste en el Módulo 1 — el agente resuelve que "llega" se refiere al pedido 4521 y responde con la fecha correcta.

Turno 3 — al día siguiente, el cliente abre una conversación nueva (nueva pestaña, el widget genera un chatSessionId distinto al de ayer) y escribe: "Hola, ¿ya llegó mi pedido?"

Qué esperar — Configuración B. Aquí fallan dos cosas a la vez, aunque solo una es evidente. La evidente: el widget generó un chatSessionId nuevo para esta conversación, y Simple Memory indexa el historial por esa clave — bajo la clave de hoy no hay nada guardado, así que es un problema de alcance: el cliente es la misma persona, pero para la memoria es una sesión distinta. La menos evidente: incluso si hubieras reusado el mismo chatSessionId de ayer a propósito, Simple Memory guarda todo en la memoria RAM del proceso de n8n — la documentación de n8n advierte explícitamente que no conviene usar este nodo en modo queue porque no hay garantía de que dos llamadas lleguen al mismo worker. Un reinicio del contenedor, o un cambio de worker, y ese historial simplemente no está ahí. Eso es un problema de almacenamiento. El agente le pide de nuevo el número de pedido — el mismo síntoma que en la Configuración A, aunque esta vez sí había una pieza de memoria conectada.

# CONFIGURACIÓN C — Postgres Chat Memory, alcance por cliente real
memory.node                = "Postgres Chat Memory"
memory.sessionKey          = "{{ $json.customerPhone }}"   # estable: es el mismo hoy y mañana
memory.tableName           = "n8n_chat_histories"
memory.contextWindowLength = 10

Turno 3, mismo escenario que en B — día siguiente, chat nuevo, mismo cliente.

Qué esperar — Configuración C. Esta vez las dos decisiones están resueltas. El sessionKey ya no es el id efímero que genera el widget en cada visita, sino el teléfono del cliente — un valor que no cambia entre ayer y hoy, sin importar cuántas pestañas nuevas abra. Y el historial ya no vive en la RAM del proceso de n8n, sino en una tabla real de Postgres que sigue ahí después de un reinicio o de un cambio de worker. Cuando llega el mensaje de hoy con ese mismo sessionKey, n8n carga el historial de ayer desde la base de datos, y el agente responde: "Sí, tu pedido #4521 llegó el 24 de julio, según lo que hablamos ayer."

Interpretación: las tres configuraciones muestran que "memoria" no es un solo dial. La Configuración A no tenía memoria en absoluto. La Configuración B tenía memoria, pero mal en las dos decisiones a la vez para este caso de uso —alcance efímero y almacenamiento no persistente—, así que el síntoma se ve idéntico al de A aunque la causa sea distinta. La Configuración C funciona porque resuelve alcance (identidad estable del cliente) y almacenamiento (base de datos real) al mismo tiempo. Ese es, en una escena, el mapa de las lecciones 3 y 4 de este módulo.

Las siete decisiones de este módulo

El resto de este módulo son siete piezas concretas sobre esas dos decisiones —alcance y almacenamiento— más un tercer problema que solo aparece cuando la conversación se alarga:

LecciónQué resuelve
2La diferencia práctica, en vivo, entre un agente que olvida cada mensaje y uno que sostiene el hilo de una conversación
3Cómo funciona la ventana de turnos recientes dentro de una misma conversación — el eje de alcance por sesión que viste en la Configuración B
4Cómo dar a un agente un sessionKey estable por cliente real y guardar el historial en una base de datos que sobrevive entre sesiones — el eje de alcance por usuario y de almacenamiento persistente que viste en la Configuración C
5Cómo diseñar conversaciones de varios turnos que mantienen el hilo sin que el agente se pierda
6Qué es el context drift: por qué un agente puede degradarse en una conversación muy larga aunque su memoria funcione perfectamente
7Cuándo conviene resumir el historial en vez de seguir acumulándolo, y cómo reiniciar el contexto sin perder lo importante
8Mini-proyecto: ensamblar un agente con memoria persistente por usuario que sobrevive entre sesiones, uniendo alcance, almacenamiento y manejo de conversaciones largas

Nota el orden: primero ves la diferencia que hace tener memoria o no (lección 2), después las dos formas concretas de tenerla —por sesión (lección 3) y persistente por usuario (lección 4)—, luego cómo se comporta eso en una conversación real de varios turnos (lección 5), y al final el problema que ninguna de las piezas anteriores resuelve por sí sola: qué pasa cuando hay demasiado historial (lecciones 6 y 7), antes de ensamblarlo todo en el mini-proyecto (lección 8).

Errores comunes

Tratar "memoria" como un interruptor único, sí o no (conceptual). Qué pasa: conectas cualquier nodo de memoria, das por resuelto "el agente ya recuerda al cliente", y te sorprende que al día siguiente —o en otro dispositivo— el agente no tenga ni idea de la conversación de ayer. Por qué pasa: el nodo AI Agent solo pide una conexión en ai_memory, y esa simplicidad visual sugiere que es una sola pieza con un solo comportamiento. Pero como viste en el ejemplo trabajado, hay dos decisiones independientes detrás —alcance y almacenamiento— y puedes acertar en una y fallar en la otra. Cómo detectarlo: si el agente recuerda dentro de la misma pestaña pero no entre sesiones distintas del mismo cliente, no preguntes "¿está rota la memoria?" —pregunta "¿qué identidad estoy usando como sessionKey, y dónde vive ese historial?". Cómo corregirlo: nombra las dos decisiones por separado antes de tocar nada — eso es exactamente lo que separan las lecciones 3 y 4.

Confundir memoria de sesión con memoria persistente (conceptual). Qué pasa: usas Simple Memory —memoria de sesión, en RAM— para un caso de uso donde el cliente necesita que el agente lo recuerde días después, y el proyecto falla en producción justo cuando el reinicio o el redeploy borra todo el historial acumulado. Por qué pasa: Simple Memory es, con razón, la opción más simple para empezar —así la usaste en el Módulo 1—, y es fácil no notar que "simple" también significa "vive solo mientras el proceso siga corriendo". Cómo detectarlo: pregúntate, antes de elegir el nodo de memoria, si tu caso de uso necesita que el agente recuerde algo que pasó en una sesión distinta, no solo en turnos distintos de la misma sesión. Si la respuesta es sí, Simple Memory no alcanza, sin importar qué tan bien configures el contextWindowLength. Cómo corregirlo: para persistencia real entre sesiones, necesitas una memoria respaldada por una base de datos (Postgres Chat Memory, Redis Chat Memory) y un sessionKey estable del cliente, no del chat — el tema completo de la lección 4.

Creer que la memoria guarda el estado real del sistema, no solo lo que se dijo (conceptual, y se vuelve práctico en el Módulo 4). Qué pasa: el agente responde con un dato que fue correcto hace tres turnos —"tu pedido está en tránsito"— pero ya cambió en el sistema real —el pedido ya se entregó— y el agente no se da cuenta porque confía en lo que la memoria guardó en vez de volver a llamar a la tool. Por qué pasa: la memoria guarda literalmente el texto de la conversación —lo que el agente dijo, no lo que es cierto en este momento en tu base de datos o tu API. No es una caché de tu sistema; es una bitácora de lo hablado. Cómo detectarlo: revisa si el agente vuelve a llamar get_order_status cuando pasó suficiente tiempo como para que el estado real haya cambiado, o si simplemente repite lo que ya dijo antes. Cómo corregirlo: la memoria resuelve continuidad conversacional —de qué se habló—; no reemplaza volver a consultar una tool cuando el dato puede haber cambiado. Esa frontera entre "lo que se recuerda" y "lo que se verifica" es la que vas a afinar cuando conectes memoria y tools juntas en el Módulo 4.

Ejercicios

Ejercicio 1 — Diagnóstico de las tres configuraciones. Sin volver a leer el ejemplo trabajado, escribe en una frase por qué falló la Configuración A y en otra frase por qué falló la Configuración B, usando las palabras "alcance" y "almacenamiento" donde corresponda.

Ver solución

Configuración A: no falló ni el alcance ni el almacenamiento — no había ninguna pieza de memoria conectada, así que no existía ningún historial que agrupar ni que guardar. Configuración B: falló en alcance, porque el sessionKey era el id efímero de la ventana de chat (distinto cada día), y además falló en almacenamiento, porque Simple Memory guarda el historial en la RAM del proceso de n8n, que no sobrevive un reinicio ni garantiza el mismo worker en modo queue.

Por qué funciona: separar el síntoma ("no recuerda") en sus dos causas posibles —qué identidad usas y dónde vive el dato— es el diagnóstico que vas a repetir cada vez que un agente en producción "pierda memoria" entre una sesión y otra.

Ejercicio 2 — Aplica el criterio a un caso propio. Piensa en un agente que te gustaría construir (o uno que ya usas como cliente). ¿Necesita memoria que sobreviva solo dentro de una conversación, o memoria que reconozca al mismo usuario días después? Justifica con el criterio de esta lección, no con "porque sería mejor".

Ver solución

No hay una respuesta única — depende del caso. El criterio correcto es: ¿existe un mismo cliente real, identificable de forma estable (teléfono, email, id de cuenta), que vuelve a interactuar con el agente en un momento distinto y espera que el agente conecte ambas interacciones? Si la respuesta es sí, necesitas memoria persistente con sessionKey estable por cliente (Configuración C). Si el agente solo necesita sostener el hilo dentro de una única conversación continua —y nunca vuelve a hablar con ese mismo usuario en otra sesión que importe recordar—, memoria de sesión (Configuración B) alcanza y es más simple de mantener.

Por qué funciona: el criterio no es "cuánta memoria parece impresionante", sino si existe una identidad estable del mundo real que el agente necesita reconocer entre sesiones distintas.

Ejercicio 3 — El mapa sin mirarlo. Sin ver de nuevo la tabla de la sección anterior, escribe de memoria qué problema resuelve cada una de las siete lecciones que faltan en este módulo (2 a 8), en una frase cada una.

Ver solución

(2) La diferencia práctica, en vivo, entre un agente que olvida y uno que sostiene el hilo. (3) Cómo funciona la ventana de turnos recientes dentro de una misma sesión. (4) Cómo dar un sessionKey estable por cliente y guardar el historial en una base de datos persistente. (5) Cómo diseñar conversaciones de varios turnos sin que el agente se pierda. (6) Qué es el context drift y por qué un agente se degrada en conversaciones muy largas. (7) Cuándo resumir el historial y reiniciar el contexto. (8) El mini-proyecto que ensambla memoria persistente por usuario.

Por qué funciona: si pudiste reconstruir el orden sin mirar, ya tienes internalizada la progresión de este módulo — de "¿hay memoria o no?" a "¿de quién es esa memoria y dónde vive?" a "¿qué hago cuando hay demasiada?".

Resumen y siguiente paso

En esta lección viste que un agente sin memoria conectada procesa cada mensaje como si fuera el único que ha recibido jamás, y que "conectar memoria" no resuelve el problema de un solo golpe: son dos decisiones independientes —qué identidad usas como alcance del historial, y dónde guardas ese historial una vez agrupado— tal como mostraron las tres configuraciones del pedido #4521. También viste el mapa de las siete piezas que te esperan en este módulo, incluyendo un tercer problema —la degradación en conversaciones largas— que ninguna de las dos decisiones anteriores resuelve por sí sola.

Antes de avanzar a la lección 2 deberías poder: explicar en una frase la diferencia entre alcance y almacenamiento de memoria, citando el ejemplo del pedido #4521; nombrar, sin ver la tabla, al menos cuatro de las siete lecciones que siguen y qué problema resuelve cada una; y, dado un agente que "no recuerda" entre dos sesiones, decir cuál de las dos decisiones sospechas primero.

Esa distinción —memoria de sesión frente a memoria de ningún tipo— es justo lo que la próxima lección convierte en una comparación en vivo: vas a ver, lado a lado, el mismo agente con y sin memoria conectada, y por qué esa diferencia es la que separa a un chatbot de un asistente real.

Recursos

  • How memory works — n8n Docs — el catálogo completo de nodos de memoria en n8n: Simple Memory frente a las opciones persistentes (Postgres Chat Memory, Redis Chat Memory, Motorhead, Xata, Zep) que vas a usar en las lecciones 3 y 4.
  • Simple Memory node — n8n Docs — referencia del nodo que ya usaste en el Módulo 1: los parámetros Session Key y Context Window Length, y la advertencia oficial de no usarlo en modo queue porque no garantiza el mismo worker entre llamadas — la razón técnica detrás de la falla de almacenamiento en la Configuración B.
  • Postgres Chat Memory node — n8n Docs — referencia del nodo detrás de la Configuración C: cómo guarda el historial en una tabla real de Postgres, indexada por Session Key.
  • Effective context engineering for AI agents — Anthropic — el artículo donde Anthropic describe el "context rot": a más tokens de historial acumulado, más se degrada la capacidad del modelo de recordarlo con precisión — la investigación detrás de lo que la lección 6 de este módulo llama context drift.
  • AI Agent node — n8n Docs — la misma referencia del nodo que ya usaste en los Módulos 1 y 2; confirma que ai_memory es la única de las tres conexiones especiales que es opcional.