Sessions, Memory & Skills
Los LLMs son stateless: cada llamada de API nace sin recordar nada. Para que un agente recuerde, aprenda y personalice, alguien debe armar — turno a turno — la información correcta dentro de la context window. Ese oficio es la Context Engineering. Esta guía resume el paper "Context Engineering: Sessions, Memory" (Kimberly Milam & Antonio Gulli, Google) en formato interactivo: diagramas clicables, simuladores, quiz y cheatsheets.
Presupone familiaridad con LLMs y desarrollo de software. No presupone conocimiento previo de frameworks de agentes — ADK y LangGraph se presentan como ejemplos, no como prerrequisito.
Qué es la Context Engineering
El oficio de armar, en cada turno, la información correcta dentro de la context window — ni más, ni menos.
Los LLMs son inherentemente stateless: todo su razonamiento ocurre dentro de la context window de una única llamada de API. Nada de lo anterior existe para el modelo — a menos que alguien lo coloque ahí. La Context Engineering es el proceso de armar y gestionar dinámicamente la información dentro de la context window para habilitar agentes stateful e inteligentes.
Es la evolución natural del Prompt Engineering: en lugar de pulir una instrucción estática, el ingeniero de contexto orquesta el payload completo — seleccionando, resumiendo e inyectando estratégicamente distintos tipos de información en cada turno, con máxima relevancia y mínimo ruido. Sistemas externos (RAG, session stores, memory managers) gestionan el contexto; el framework lo orquesta todo.
El chef no cocina con la receta en la mano — cocina con la bancada lista
Un chef que solo tiene la receta usa ingredientes aleatorios que encuentra a su paso. El plato sale… aceptable. Es el prompt estático: una buena instrucción, sin contexto preparado.
El chef reúne y prepara todos los ingredientes, organiza las herramientas y define el estilo de presentación antes de cocinar. Es el contexto completo: histórico, memorias, hechos, herramientas — todo en su lugar, en el momento justo.
Prompt = la receta
- dice qué hacer
- no sabe qué hay en la nevera
- resultado impredecible
Contexto = ingredientes preparados
- receta + ingredientes correctos + herramientas + presentación
- armado por plato (por turno)
- ni más, ni menos de lo necesario
El objetivo no es llenar la context window — es entregar la información más relevante para este turno. Ni más, ni menos.
El payload del contexto
Tres capas de componentes — haz clic en cada una para ver qué contiene.
Todo lo que el modelo "ve" en un turno cabe en tres categorías. El armado es dinámico: las memorias no son estáticas, los few-shot examples deben ser relevantes para la tarea (no hardcoded) y el RAG responde a la query inmediata.
Contexto que guía el razonamiento
comportamientoHechos y evidencias
sobre qué razonarConversación inmediata
la tarea actual🧭 Guia o raciocínio
…
Context rot y el ciclo continuo
Por qué el histórico debe mutarse en cada turno — y las cuatro etapas que lo hacen posible.
El histórico de conversación crece sin parar. Ventanas más grandes soportan transcripciones largas, pero: el costo y la latencia suben con cada token y aparece el context rot — la atención del modelo a la información crítica disminuye a medida que el contexto crece. La solución es mutar el histórico dinámicamente: sumarización, poda selectiva, compactación.
1 · Fetch Context
…
La Session es la bancada de trabajo; Memory es el archivo organizado
Herramientas, notas y borradores esparcidos: todo accesible, pero temporal. Al final del día la bancada se vacía — y la próxima conversación empieza limpia.
Revisas los materiales de la bancada, descartas los borradores y archivas solo lo esencial. Nadie mete la bancada desordenada entera en el archivo — por eso el upload es consolidación, no copia.
Sessions: fundamentos
El contenedor cronológico de UNA conversación — events + state, ligado a un único usuario.
Una session encapsula el histórico de diálogo y la working memory de una conversación continua: un registro autocontenido ligado a un usuario específico. Un usuario puede tener múltiples sessions — logs distintos y desconectados entre sí.
El agente anexa events y muta el state según la lógica del negocio. La estructura refleja la lista de objetos Content de la Gemini API — cada Content tiene role (user/model) y parts (texto, imágenes, tool calls): un turno = un Event.
# o histórico é uma lista de Content: role + partsresponse = client.models.generate_content( model="gemini-2.5-flash", contents=[{"role": "user", "parts": [{"text": "Quero ir a Paris em novembro"}]},{"role": "model", "parts": [{"text": "Direto ou com escala?"}]},{"role": "user", "parts": [{"text": "Direto, por favor"}]}, ], )
Los runtimes de producción son stateless — el histórico debe persistirse. El storage in-memory sirve para desarrollo; producción exige bases de datos robustas (ej. Agent Engine Sessions).
Frameworks: el traductor universal
ADK y LangGraph implementan sessions de formas distintas — pero las ideas centrales son las mismas.
El framework es un traductor universal entre tu código y el LLM: mantiene el histórico y el state, construye las requests, parsea y almacena las respuestas. Para Gemini, la request es List[Content] — cada Content con role y parts. El framework mapea tu objeto interno (ej. un Event de ADK) a role/parts antes de la llamada. Esta abstracción desacopla la lógica del agente del LLM específico — y previene el vendor lock-in.
Tu lógica
Eventos y state internos del agente
Framework
arma la request · parsea la respuesta
Gemini API
List[Content] · role + parts
Session store
histórico + state persistidos
ADK — objeto Session explícito
Una Session con una lista de Events + un objeto state separado. Piensa en un archivo con una carpeta para el histórico y otra para la working memory — cada cosa en su lugar, claramente delimitada.
session = Session( id="s_771", events=[event_1, event_2, event_3], # histórico cronológicostate={"cart_items": [...]}, # working memory separada)
LangGraph — el state ES la session
No existe un objeto "session" formal: el estado abarcador y mutable (histórico como lista de Messages + datos de trabajo) es la session. Y puede ser transformado — por ejemplo con history compaction — lo que es valioso para conversaciones largas y límites de tokens.
class AgentState(TypedDict): messages: Annotated[list, add_messages] # históricocart: dict # dados de trabalho# o grafo pode reescrever o state a cada passo (ex.: compactar)
Sessions multi-agente
Cuando varios agentes colaboran, la arquitectura define quién ve el histórico de quién.
Session history es la transcripción permanente e integral. Contexto es el payload cuidadosamente construido para UN turno — puede ser un extracto relevante con formato especial. Esta sección trata de lo que pasa entre agentes, no necesariamente de lo que va al LLM.
Histórico compartido
- todos los agentes leen y escriben en el mismo log cronológico
- ideal para tareas acopladas: el output de uno es el input del siguiente
- aun así, cada agente puede filtrar/etiquetar events antes de pasarlos al LLM
- ej. delegación LLM-driven en ADK — los events del sub-agente caen en la session del root agent (con
output_key)
Históricos separados
- cada agente mantiene un histórico privado: razonamiento, tool use y pasos intermedios quedan ocultos
- la comunicación ocurre solo por mensajes explícitos — el output final, no el proceso
- vía Agent-as-a-Tool (invoca a otro agente como herramienta y recibe un output autocontenido)
- o vía el Protocolo A2A (mensajes directos y estructurados)
Interoperabilidad y el protocolo A2A
La abstracción que libera al agente del LLM también lo aísla de otros frameworks — la memory layer es el puente.
Hay un trade-off crítico: la misma abstracción que desacopla al agente del LLM lo aísla de agentes de otros frameworks. El aislamiento se solidifica en la capa de persistencia — el schema de la base queda acoplado a los objetos internos del framework y el registro se vuelve no portable. Un agente LangGraph no puede interpretar nativamente los objetos Session/Event de un agente ADK: handoff seamless, imposible.
Session stores aislados
- A2A intercambia mensajes, pero no comparte estado contextual rico
- el histórico vive en el schema interno de cada framework
- enviar events de session vía A2A exige una capa de traducción customizada
Memory layer compartida
- conocimiento abstraído en una capa de datos framework-agnostic
- guarda información procesada y canónica: resúmenes, entidades, hechos como strings/dicts
- agentes heterogéneos logran inteligencia colaborativa compartiendo un recurso cognitivo común — sin traductores
Los session stores guardan objetos raw y framework-specific; la memory layer guarda información procesada y canónica. Ella es la capa de datos universal.
Sessions en producción
Tres áreas críticas que un session store gestionado (ej. Agent Engine Sessions) resuelve.
🔐 Seguridad y privacidad
- Strict isolation es el principio más crítico: una session pertenece a un usuario — nadie más puede accederla (ACLs; cada request autenticada contra el owner)
- PII: redactar antes de escribir en storage — reduce el "blast radius" de una brecha (herramientas como Model Armor)
- simplifica el cumplimiento GDPR/CCPA y construye confianza
🗂️ Integridad y ciclo de vida
- las sessions no deben vivir para siempre: políticas de TTL eliminan sessions inactivas (costo de storage + overhead)
- política de retención clara: cuánto tiempo antes de archivar o eliminar
- events anexados en orden determinístico — secuencia cronológica correcta = integridad del log
⚡ Rendimiento y escala
- los datos de session están en el hot path de cada interacción — lectura/escritura debe ser muy rápida
- runtimes stateless buscan el histórico completo de la base central en cada turno (latencia de red)
- mitigación: reducir lo transferido — filtrar/compactar el histórico antes de enviar (ej. eliminar function call outputs antiguos e irrelevantes)
Compactación de conversaciones largas
Cuatro presiones, una maleta y tres estrategias — juega con el simulador.
En una arquitectura simple, la session es un log inmutable. A medida que escala, el uso de tokens explota — y cuatro limitaciones golpean a las aplicaciones sensibles a la latencia:
📏 Ventana
exceder el máximo de texto procesable = la llamada de API falla
💸 Costo
se cobra por token enviado/recibido — histórico menor, cuenta menor
🐢 Latencia
más texto = más tiempo de procesamiento = respuesta más lenta
📉 Calidad
más tokens = peor rendimiento: ruido + errores autorregresivos
La context window es una maleta con espacio limitado
Una maleta pesada y desorganizada: pagas exceso de equipaje (costo) y no encuentras nada (lentitud). Es el histórico sin compactar.
Olvidas el pasaporte y el abrigo — pierdes contexto crítico y respondes mal. Compactar bien es llevar solo lo necesario.
Las tres estrategias de compactación
🪟 Keep last N turnos
la más simple: una ventana deslizante sobre los N turnos más recientes — todo lo anterior se descarta
✂️ Truncado por tokens
cuenta tokens desde el más reciente hacia atrás e incluye tantos mensajes como sea posible sin exceder un límite predefinido (ej.: 4.000 tokens) — el resto se corta
📜 Sumarización recursiva
los mensajes antiguos se vuelven un resumen prefijado a los recientes — mejor balance fidelidad/costo (operación LLM cara → corre en background)
# limita o contexto enviado ao LLM, sem modificar o log persistidoplugin = ContextFilterPlugin(num_invocations_to_keep=10)# ou: compactação agendada de eventosconfig = EventsCompactionConfig(compaction_interval=5, overlap_size=1)
Mecanismos de trigger
🔢 Count-based
umbral de tokens o de turnos — simple y "suficiente"
⏰ Time-based
falta de actividad (ej. 15–30 min sin interacción) → compactación en background
🎯 Event-based
detecta una tarea, sub-objetivo o tema completado — trigger semántico
La sumarización recursiva debe correr asíncronamente en background y persistir sus resultados (el cliente no espera; la computación no se repite). El agente registra qué events ya están en el resumen compactado — para no reenviar los originales verbosos. La generación de memoria es la capacidad amplia detrás de esto: extraer conocimiento persistente de fuentes ruidosas, descartando el relleno.
Memory 101
La relación simbiótica entre sessions y memory — y las cinco capas que colaboran en cada turno.
Sessions y memory viven en simbiosis: las sessions son la fuente primaria para generar memorias, y las memorias son la estrategia clave para gestionar el tamaño de las sessions. Una alimenta a la otra, en un ciclo continuo.
Una memoria es un snapshot de información extraída y significativa de una conversación o fuente: una representación condensada que preserva el contexto importante, persistida entre sesiones para una experiencia continua y personalizada.
Algunos frameworks llaman a la conversación textual "short-term memory". En este paper, las memorias son información extraída — no el diálogo raw.
Cuatro capacidades que un sistema de memoria habilita
🎯 Personalización
recordar preferencias, hechos e interacciones pasadas — el equipo favorito, el asiento preferido en el avión
📦 Gestión de la context window
compactar históricos largos en resúmenes y hechos clave, preservando contexto sin enviar miles de tokens por turno — menos costo, menos latencia
📊 Data mining e insights
analizar memorias de muchos usuarios de forma agregada y privacy-preserving — ej. un chatbot de retail descubre que muchos preguntan por la política de devolución de un producto
🔁 Auto-mejora del agente
memorias procedimentales sobre su propio rendimiento — qué estrategias, tools y caminos llevaron al éxito — se vuelven un playbook que el agente reutiliza y adapta
Las cinco capas colaborando en cada turno
1 · User
provee los datos raw — a veces directamente, vía formulario
2 · Agent (lógica del desarrollador)
decide qué y cuándo recordar, y orquesta el memory manager — desde "siempre buscar/generar" hasta memory-as-a-tool, donde el LLM decide
3 · Agent framework (ADK, LangGraph)
la plomería: estructuras y herramientas para interactuar con la memoria, acceder al histórico, inyectar en la context window — no gestiona el storage de largo plazo
4 · Session storage (Agent Engine Sessions, Spanner, Redis)
almacena la conversación turno a turno; el diálogo raw es la materia prima ingerida por el memory manager
5 · Memory manager (Agent Engine Memory Bank, Mem0, Zep)
storage, retrieval y compactación — el ciclo de vida completo: Extraction → Consolidation → Storage → Retrieval
Un memory manager no es un vector database pasivo. Su valor central es extraer, consolidar y curar memorias inteligentemente a lo largo del tiempo — no solo hacer similarity search.
RAG × Memory
Roles distintos y complementarios: RAG hace al agente experto en hechos; Memory, experto en el usuario.
El retrieval de memoria se compara frecuentemente con RAG, pero los principios arquitectónicos son diferentes: RAG lidia con datos externos estáticos; Memory, con contexto dinámico y específico del usuario. Son complementarios — y un agente verdaderamente inteligente necesita ambos.
RAG · el bibliotecario de investigación
- trabaja en una biblioteca pública vasta: enciclopedias, docs oficiales, base estática y compartida
- recupera hechos establecidos y autoritativos
- read-only, global — igual para todos los usuarios
- no sabe nada personal sobre ti
Memory · el asistente personal
- anda con un cuaderno privado, registrando detalles de cada interacción
- dinámico y altamente aislado: preferencias, conversaciones pasadas, metas
- escribe en cada turno o al fin de la sesión — event-based
- se adapta a medida que la relación evoluciona
| Dimensión | RAG Engines | Memory Managers |
|---|---|---|
| Objetivo | inyectar conocimiento factual externo | experiencia personalizada y stateful: recuerda hechos, se adapta al usuario, mantiene contexto largo |
| Fuente de datos | base de conocimiento externa pre-indexada (PDFs, wikis, docs, APIs) | el diálogo usuario-agente |
| Aislamiento | generalmente compartido (global, read-only) | altamente aislado (por usuario, previene fugas) |
| Tipo de información | estática, factual, autoritativa | dinámica, específica del usuario, con incertidumbre inherente |
| Patrón de escritura | procesamiento por lotes (acción administrativa offline) | event-based (cada turno / fin de sesión) o memory-as-a-tool |
| Patrón de lectura | casi siempre as-a-tool (el agente decide cuándo lo necesita) | memory-as-a-tool O retrieval estático al inicio del turno |
| Formato | chunks en lenguaje natural | snippets en lenguaje natural O perfil estructurado |
| Preparación de datos | chunking + indexing (embeddings para búsqueda rápida) | extraction + consolidation (sin duplicación ni contradicción) |
Tipos de memoria
Anatomía, taxonomía cognitiva, organización, storage, creación, alcance y multimodalidad.
Las memorias se clasifican por cómo se almacenan y capturan — y trabajan juntas para un entendimiento rico y contextual. Regla de oro: las memorias son descriptivas, no predictivas.
Anatomía de una memoria
Una 'memoria' es una pieza atómica de contexto devuelta por el memory manager y usada por el agente como contexto. Aunque el schema exacto puede variar, una memoria generalmente consta de dos componentes: content y metadata.
📄 Content
la sustancia extraída de los datos fuente, en formato framework-agnostic. Estructurada ({"seat_preference": "window"}) o no estructurada ("The user prefers a window seat").
🏷️ Metadata
el contexto sobre la memoria: identificador único, owner y labels que describen contenido y fuente.
Declarative × Procedural (ciencia cognitiva)
Declarative
- hechos, números, eventos
- incluye conocimiento general (semantic) y hechos específicos del usuario (episodic)
- ej. "el usuario prefiere asiento de ventanilla"
Procedural
- habilidades y workflows
- guía acciones demostrando implícitamente cómo ejecutar una tarea
- ej. la secuencia correcta de tool calls para reservar un viaje
Patrones de organización
🗃️ Collections
múltiples memorias autocontenidas en lenguaje natural por usuario — varias por tema, buscadas en un pool mayor y menos estructurado
🪪 Structured user profile
un conjunto de hechos centrales, como una tarjeta de contacto continuamente actualizada — lookup rápido de lo esencial (nombres, preferencias, cuenta)
📜 Rolling summary
UNA memoria única y evolutiva: el resumen de toda la relación usuario-agente, actualizado continuamente — usado para compactar sessions largas
Arquitecturas de storage
🧮 Vector databases
retrieval por similitud semántica (no keywords exactas): las memorias se vuelven embeddings y coinciden por concepto. Excelente para hechos no estructurados
🕸️ Knowledge graphs
memorias como red de entidades (nodos) + relaciones (aristas); retrieval = recorrer el grafo. Ideal para queries relacionales ("knowledge triples")
🔀 Hybrid
entidades del grafo enriquecidas con vector embeddings — búsqueda relacional y semántica simultánea: lo mejor de ambos mundos
Mecanismos de creación
🗣️ Explicit
comando directo del usuario: "recuerda que mi aniversario es el 26 de octubre"
🕵️ Implicit
el agente infiere sin comando: "mi aniversario es la próxima semana, ayúdame con un regalo" → memoria creada
🏠 Internal
gestión integrada en el framework — conveniente, con menos recursos
☁️ External
servicio especializado (Memory Bank, Mem0, Zep): semantic search, entity extraction, summarization automática
Alcance: a quién describe la memoria
👤 User-level
el más común: ligado al user ID, persiste entre sesiones — "el usuario prefiere el asiento del medio"
💬 Session-level
registro persistente de insights de UNA sesión — reemplaza la transcripción verbosa por hechos concisos, aislados a esa conversación
🌐 Application-level
contexto global accesible para todos los usuarios — caso común: memorias procedimentales ("how-to" para el razonamiento del agente)
Las memorias application-level deben ser sanitizadas de contenido sensible — de lo contrario se vuelven un vector de fuga entre usuarios.
Memoria multimodal: origen × contenido
Multimodal source
- el agente procesa texto, imagen o audio — pero la memoria creada es un insight textual
- ej. nota de voz → transcripción → "el usuario expresó frustración por retraso en el envío" (el audio no se almacena)
Multimodal content
- la memoria contiene medios no textuales directamente
- ej. "recuerda este diseño para nuestro logo" → la memoria contiene el archivo de imagen
La mayoría de los managers se enfocan en fuentes multimodales → contenido textual: convertir todo a texto es la forma más simple de mantener un formato buscable.
from google.genai import types client = vertexai.Client(project=..., location=...) response = client.agent_engines.memories.generate( name=agent_engine_name, direct_contents_source={"events": [{"content": types.Content( role="user", parts=[ types.Part.from_text("This is context about the multimodal input."), types.Part.from_bytes(data=CONTENT_AS_BYTES, mime_type=MIME_TYPE), types.Part.from_uri(file_uri="file/path/to/content", mime_type=MIME_TYPE) ] )}]}, scope={"user_id": user_id})
Generación de memoria: el pipeline ETL
Cómo los datos conversacionales raw se vuelven insights estructurados — un ETL dirigido por LLM.
La generación transforma autónomamente datos conversacionales raw en insights estructurados y significativos — un pipeline ETL dirigido por LLM (Extract, Transform, Load). Eso es lo que distingue a los memory managers de los RAG engines y las bases de datos tradicionales: en lugar de que el dev especifique operaciones de base manualmente, el LLM decide cuándo agregar, actualizar o fusionar memorias — abstrayendo la complejidad de gestionar contenido, encadenar llamadas y correr servicios en background.
Ingestion
el cliente provee la fuente de datos raw — típicamente el histórico de conversación
Extraction & filtering
el LLM extrae solo lo que encaja en definiciones de tema predefinidas — sin coincidencia, no se crea memoria
Consolidation
la etapa más sofisticada: resolución de conflictos + deduplicación — merge, delete o create
Storage
la memoria nueva o actualizada se persiste en storage durable (vector DB / knowledge graph)
memories.generate( scope={"user_id": "u_8123"}, direct_contents_source=session_events, # matéria-prima rawconfig={"wait_for_completion": False}, # assíncrono, em background)Un jardín saludable no crece solo — exige curación constante
Llegan nuevas semillas y plantas al jardín: el LLM identifica qué merece ser plantado — y descarta lo que no encaja en los canteros (temas) definidos.
Arrancar las malas hierbas (eliminar lo redundante y conflictivo), podar ramas (refinar y resumir lo existente) y plantar cada planta en el lugar óptimo. Sin curación, el jardín se vuelve maleza — un proceso continuo, en background.
Un memory manager gestionado (ej. Agent Engine Memory Bank) automatiza el pipeline completo — extracción, consolidación y storage — con una única llamada de API asíncrona.
Deep-dive: Extraction
"¿Qué información aquí es lo bastante significativa para volverse memoria?" — filtrado inteligente, no sumarización.
La pregunta fundamental de la extracción es: "¿qué información de esta conversación es lo bastante significativa para volverse memoria?" No es sumarización simple — es filtrado inteligente y dirigido: separar la señal (hechos, preferencias, metas) del ruido (cortesías, relleno).
"Significativo" no es universal — lo define el propósito del agente. Un agente de soporte al cliente extrae números de pedido y problemas técnicos; un coach de bienestar extrae metas de largo plazo y estados emocionales. Personalizar esa definición es la clave de un agente eficaz.
Cómo el LLM sabe qué extraer
🧩 Schema / template-based
un JSON schema o template predefinido (structured output); el LLM construye el JSON con la información correspondiente
📝 Definiciones en lenguaje natural
el LLM se guía por una descripción simple, en lenguaje natural, de lo que es cada tema
🎓 Few-shot prompting
el LLM "ve" qué extraer mediante ejemplos: input + memoria ideal de alta fidelidad. Muy eficaz para temas matizados y difíciles de describir
La mayoría de los managers funcionan out-of-the-box con temas comunes (preferencias, hechos clave, metas) — y muchos permiten temas personalizados. El ejemplo del paper: una conversación sobre una cafetería genera dos memorias de feedback — "el café de filtro estaba tibio" y "la música estaba demasiado alta".
config = MemoryGenerationConfig( memory_topics=[ ManagedTopicEnum.USER_PERSONAL_INFO, # tópico built-inCustomMemoryTopic( name="business_feedback", description="feedback about the coffee shop", ), ], generate_memories_examples=[...], # few-shot: conversa → fatos)
Aunque no es sumarización, el algoritmo puede incorporarla: un rolling summary de la conversación entra en el prompt de extracción, dando contexto condensado para extraer de las interacciones recientes — sin reprocesar el diálogo completo en cada turno.
Deep-dive: Consolidation
La etapa que convierte una colección de hechos en entendimiento curado — auto-curación dirigida por LLM.
La consolidación integra información nueva en una base de conocimiento coherente, precisa y evolutiva. Es la etapa más sofisticada: sin ella, la memoria se vuelve un log ruidoso, contradictorio y poco fiable. Esta "auto-curación" gestionada por LLM es lo que eleva al memory manager más allá de una base de datos simple.
Los cuatro problemas que resuelve
👯 Duplicación
el mismo hecho de varias formas: "necesito un vuelo a NYC" + "estoy planeando ir a New York" — la extracción simple crearía dos memorias redundantes
⚔️ Conflicto
el estado del usuario cambia con el tiempo — sin consolidación, hechos contradictorios conviven en la base
🌱 Evolución
un hecho simple se vuelve más matizado: "interesado en marketing" → "liderando un proyecto de adquisición de clientes en Q4"
⌛ Decaimiento
no toda memoria sigue siendo útil: el agente practica el olvido — poda lo viejo, obsoleto y de baja confianza (prioridad a lo nuevo o TTL)
El proceso en tres pasos
1 · Buscar similares
las memorias existentes similares a las recién extraídas se vuelven candidatas a consolidación
2 · El LLM analiza
memorias existentes + información nueva, juntas: el LLM identifica las operaciones necesarias
3 · Transacción
el memory manager traduce la decisión del LLM en una transacción que actualiza el store
UPDATE
modificar una memoria existente con información nueva o corregida
CREATE
un insight totalmente nuevo y no relacionado → crear una memoria nueva
DELETE / INVALIDATE
la información nueva volvió irrelevante o incorrecta la memoria vieja → eliminar o invalidar
Provenance: linaje y confianza
"Garbage in, confident garbage out" — cada memoria necesita un registro de origen e historial.
"Garbage in, garbage out" es aún más crítico para los LLMs: aquí es "garbage in, confident garbage out". Para decisiones confiables y una consolidación eficaz, el agente debe evaluar críticamente la calidad de sus propias memorias — y la fiabilidad deriva de la provenance: el registro detallado de origen e historial.
una memoria ← varias fuentes
una fuente → varias memorias
confianza = origen + edad
Linaje durante la gestión
⚔️ Resolución de conflictos
las fuentes entran en conflicto — la provenance establece la jerarquía de confianza: priorizar la fuente más fiable, favorecer la información más reciente, buscar corroboración entre múltiples datos.
🧹 Eliminar datos derivados
si el usuario revoca el acceso a una fuente, los datos derivados deben eliminarse. Eliminar toda memoria "tocada" puede ser demasiado agresivo — el enfoque más preciso (y caro) es regenerar las memorias afectadas desde cero usando solo las fuentes válidas restantes.
La confianza evoluciona — y la poda es activa
La confianza no es estática: crece con la corroboración (múltiples fuentes fiables consistentes) y decae con la edad y el conflicto. El memory pruning (olvido activo) identifica y descarta memorias que dejaron de ser útiles — por decaimiento temporal (una reunión de hace 2 años vale menos que la de la semana pasada), baja confianza (una inferencia débil nunca corroborada) o irrelevancia (detalles triviales antiguos frente a las metas actuales). Consolidación reactiva + poda proactiva = base de conocimiento curada, no un log creciente de todo.
Las memorias y sus confidence scores no se muestran al usuario — se inyectan en el system prompt para que el LLM pondere las evidencias, considere la fiabilidad y tome decisiones más matizadas.
Disparando la generación y memory-as-a-tool
El agente decide CUÁNDO generar — un balance entre data freshness, costo y latencia.
Los memory managers automatizan extracción y consolidación después de que la generación se dispara — pero quien decide cuándo intentar generar es el agente. Es una elección arquitectónica crítica: balancear data freshness contra costo computacional y latencia.
Estrategias de trigger
🏁 Session completion
al final de una sesión multi-turno — más económico, memorias de menor fidelidad
🔁 Turn cadence
tras N turnos (ej. cada 5) — punto medio entre frescura y costo
⚡ Real-time
después de CADA turno — memorias detalladas y frescas, mayor costo de LLM/base
🗣️ Explicit command
comando directo del usuario: "recuerda esto" — fidelidad máxima, intención clara
Generación frecuente = memorias frescas y detalladas, pero mayor costo y latencia potencial. Generación infrecuente = económica, pero el LLM resume bloques mucho mayores (menor fidelidad). Y cuidado: no reprocesar los mismos events varias veces — costo innecesario.
Memory-as-a-tool: el agente decide
En el enfoque más sofisticado, la generación se expone como una herramienta (ej. create_memory) cuya definición describe qué tipos de información son significativos. El agente analiza la conversación y llama a la herramienta autónomamente cuando identifica algo que vale la pena persistir — transfiriendo la responsabilidad de identificar lo "significativo" del memory manager al agente/dev.
def generate_memories(tool_context):# opção 1: histórico completo da sessionmemory_service.add_session_to_memory(tool_context.session)# opção 2: só o último turno, assíncronomemories.generate(..., config={"wait_for_completion": False}) runner = Runner(agent=agent, memory_service=VertexAiMemoryBankService())
# aqui o AGENTE extrai (extract_memories) e envia ao Memory Bank# apenas para CONSOLIDAR com as memórias existentesmemories = extract_memories(direct_memories_source={"fact": query}) memory_bank.store(memories) # consolidação delegada ao serviço
Background, siempre
Memory Retrieval
Qué memorias buscar, cuándo buscarlas — y cómo puntuarlas en múltiples dimensiones.
La estrategia de retrieval depende de la organización: un structured user profile es un lookup simple (el perfil entero o un atributo); una collection es un problema de búsqueda complejo — encontrar la información más pertinente en un pool grande y poco estructurado.
El retrieval eficaz es crucial: memorias irrelevantes confunden al modelo y degradan la respuesta; el contexto perfecto produce una interacción notablemente inteligente. El desafío central es balancear utilidad con un presupuesto de latencia estricto.
Las tres dimensiones del scoring
Relevance
¿qué tan relacionada conceptualmente con la conversación actual?
Recency
¿qué tan recientemente fue creada la memoria?
Importance
¿qué tan crítica es en general? (definida en la generación — distinta de relevance)
Confiar solo en relevance vectorial hace que el retrieval muestre memorias conceptualmente similares — pero viejas o triviales. La mejor estrategia es el enfoque combinado: las tres dimensiones juntas.
Técnicas de precisión (y su costo)
✍️ Query rewriting
el LLM mejora su propia query — reescribe input ambiguo en una query precisa o expande una query en varias relacionadas. Mejora la calidad, añade la latencia de una llamada extra
🏆 Reranking
retrieval inicial amplio (ej. top 50) por similitud; luego el LLM reevalúa y reordena el conjunto hasta la lista final, más precisa
🔬 Specialized retriever
fine-tuning del retriever — requiere datos etiquetados y aumenta costos significativamente
1) Si estas técnicas son necesarias y las memorias no quedan obsoletas rápido, usa una capa de caché — almacena resultados caros temporalmente y evita latencia en requests idénticos. 2) El mejor enfoque empieza antes del retrieval: una mejor generación de memoria (un corpus de alta calidad, libre de irrelevancia) es la forma más eficaz de garantizar retrieval útil.
Timing: cuándo buscar
Proactive
- contexto siempre disponible — pero latencia innecesaria en turnos que no lo necesitan
- como las memorias son estáticas durante un turno, pueden cachearse (mitiga el costo)
- ej. ADK
PreloadMemoryToolo unbefore_model_callbackque anexa memorias al system_instruction
Reactive · memory-as-a-tool
- más eficiente y robusto — la llamada extra solo ocurre cuando es necesaria
- riesgo: el agente puede no saber que existe información relevante
- mitigación: describir los tipos de memorias disponibles en la propia herramienta (ej.
LoadMemoryTooloload_memory(query))
# Option 1: PreloadMemoryTool embutida — busca por similaridade em todo turnoagent = LlmAgent( ..., tools=[adk.tools.preload_memory_tool.PreloadMemoryTool()] )# Option 2: callback customizado — mais controle sobre como as memórias são buscadasdef retrieve_memories_callback(callback_context, llm_request): user_id = callback_context._invocation_context.user_id app_name = callback_context._invocation_context.app_name response = client.agent_engines.memories.retrieve( name="projects/.../locations/.../reasoningEngines/...", scope={"user_id": user_id, "app_name": app_name}) memories = [f"* {memory.memory.fact}" for memory in list(response)]if not memories:return # nenhuma memória para acrescentar às System Instructions# anexa as memórias formatadas às System Instructionsllm_request.config.system_instruction += "\nHere is information that you have about the user:\n"llm_request.config.system_instruction += "\n".join(memories) agent = LlmAgent( ..., before_model_callback=retrieve_memories_callback, )
# Option 1: LoadMemoryTool embutida — o agente decide quando buscaragent = LlmAgent( ..., tools=[adk.tools.load_memory_tool.LoadMemoryTool()], )# Option 2: tool customizada — descreva que tipos de informação podem estar disponíveisdef load_memory(query: str, tool_context: ToolContext):"""Retrieves memories for the user. The following types of information may be stored for the user: * User preferences, like the user's favorite foods. ..."""# busca memórias por similaridaderesponse = tool_context.search_memory(query)return response.memories agent = LlmAgent( ..., tools=[load_memory], )
Inferencia con memorias
El paso final: posicionar estratégicamente las memorias recuperadas en la context window.
La posición influye en el razonamiento del LLM, los costos operativos y la calidad de la respuesta. En la práctica, la estrategia híbrida funciona mejor: system prompt para memorias estables/globales (el perfil del usuario, siempre presente); dialogue injection o memory-as-a-tool para memorias transitorias/episódicas (relevantes solo para el contexto inmediato).
Memorias en las System Instructions
Anexar memorias al system prompt con un preámbulo les da alta autoridad y separa el contexto del diálogo — ideal para información estable y global. Típicamente vía template (ej. Jinja) con un bloque <MEMORIES> iterando sobre retrieved_memory.memory.fact.
from jinja2 import Template template = Template("""{{ system_instructions }}<MEMORIES> Here is some information about the user:{% for retrieved_memory in data %}* {{ retrieved_memory.memory.fact }}{% endfor %}</MEMORIES> """) prompt = template.render( system_instructions=system_instructions, data=retrieved_memories )
Over-influence: el agente intenta relacionar TODO tema con las memorias centrales, incluso cuando es inapropiado. Además: requiere un framework que soporte system prompt dinámico en cada llamada; es incompatible con memory-as-a-tool (el system prompt debe estar finalizado ANTES de que el LLM decida llamar a la herramienta de retrieval); y maneja mal las memorias no textuales.
Memorias en el Conversation History
Inyectando directamente en el diálogo — antes del histórico completo o justo antes de la última query del usuario. Riesgos: ruido (más tokens, confusión si son irrelevantes) y dialogue injection (el modelo trata la memoria como algo realmente dicho en la conversación). Cuidado con la perspectiva: si usas role "user" con memorias user-level, escribe en primera persona. Caso especial: retrieval vía tool calls — las memorias llegan como tool output.
def load_memory(query: str, tool_context):"""Search the user's long-term memories."""response = tool_context.search_memory(query)return response.memories # entra no contexto como tool output
¿Y las memorias procedimentales?
El paper se enfocó en declarative — reflejo del mercado comercial actual, cuyas plataformas están arquitecturadas para extraer/almacenar/recuperar el "qué". Pero almacenar el "cómo" no es un problema de information retrieval — es un problema de reasoning augmentation, con su propio ciclo de vida:
⛏️ Extraction
prompts especializados destilan una estrategia reutilizable — un "playbook" — de una interacción exitosa, no solo un hecho
🧬 Consolidation
cura el WORKFLOW: integra nuevos métodos exitosos con las mejores prácticas existentes, remienda pasos fallidos, poda procedimientos obsoletos
🔎 Retrieval
el objetivo no es recuperar datos para responder una pregunta, sino recuperar un PLAN que guía la ejecución de una tarea compleja
Ambos buscan mejorar el comportamiento — pero los mecanismos son fundamentalmente diferentes. El fine-tuning es un proceso lento y offline que altera los pesos del modelo. La procedural memory es adaptación rápida y online: inyectar dinámicamente el "playbook" correcto en el prompt — in-context learning, sin fine-tuning.
Testing y evaluación de memoria
¿Recuerda las cosas correctas? ¿Las encuentra cuando las necesita? ¿Y usar memoria realmente ayuda?
La evaluación de memoria es un proceso de múltiples capas: verificar que el agente recuerde las cosas correctas (calidad), encuentre las memorias cuando las necesita (retrieval) y que usarlas realmente ayude a lograr objetivos (task success). En la academia, benchmarks reproducibles; en la industria, impacto directo en el agente de producción.
🧪 Calidad de generación
🔎 Rendimiento de retrieval
🏁 Éxito de tarea end-to-end
La evaluación no es un evento único: establecer una línea base → analizar fallas → ajustar el sistema (refinar prompts, ajustar algoritmos de retrieval) → reevaluar para medir el impacto. Y más allá de la calidad, estar listo para producción exige rendimiento: retrieval sub-second en el hot path, throughput suficiente para generación asíncrona. Un sistema de memoria exitoso = inteligente + eficiente + robusto.
Memory en producción y seguridad
Del prototipo a la empresa: desacoplamiento, concurrencia, resiliencia — y el archivista corporativo.
Del prototipo a producción, el foco cambia a concerns enterprise-grade: escalabilidad, resiliencia y seguridad. La regla número uno: desacoplar el procesamiento de memoria de la lógica principal — la UX nunca puede ser bloqueada por generación cara.
1 · El agente empuja datos
tras un evento relevante (ej. fin de sesión), una llamada API no bloqueante "empuja" los datos raw
2 · Procesa en background
el servicio acusa recibo, encola internamente y hace el trabajo pesado — LLM, extracción, consolidación
3 · Memorias persistidas
memorias finales escritas en una base durable dedicada (los managers gestionados tienen storage integrado)
4 · El agente recupera
la aplicación consulta el store directamente cuando necesita contexto para una nueva interacción
Las fallas y la latencia en el pipeline de memoria no impactan la aplicación de cara al usuario. El patrón también orienta la elección entre procesamiento online (real-time, frescura conversacional) y offline (batch, ideal para cargar datos históricos).
Concurrencia, fallas y escala global
🔀 Concurrencia
eventos de alta frecuencia sin deadlocks/race conditions cuando múltiples eventos modifican la misma memoria: operaciones transaccionales u optimistic locking, con una message queue robusta como buffer
🩹 Manejo de fallas
resiliencia a errores transitorios: llamada LLM falló → retry con exponential backoff; fallas persistentes → dead-letter queue para análisis
🌍 Global
replicación multi-región integrada — la replicación client-side no es viable (la consolidación exige una visión única y transaccionalmente consistente); el sistema replica internamente y presenta un datastore lógico único
Privacidad y riesgos de seguridad
Las memorias derivan de — e incluyen — datos del usuario. Piensa en un archivo corporativo seguro gestionado por un archivista profesional: preserva conocimiento valioso mientras protege a la empresa.
🔐 Data isolation
la regla cardinal: así como el archivista nunca mezcla archivos confidenciales de distintos departamentos, la memoria está estrictamente aislada por usuario/tenant (ACLs restrictivas). Los usuarios tienen control programático: optar por no generar o eliminar todos sus archivos
🖊️ Redacción de PII
antes de archivar cualquier documento, el archivista redacta información personal sensible — el conocimiento se guarda sin crear responsabilidad legal
☠️ Memory poisoning
el archivista está entrenado para detectar falsificaciones: validar y sanitizar información ANTES de comprometerla a memoria de largo plazo previene que un usuario malicioso corrompa el conocimiento persistente vía prompt injection (salvaguardas como Model Armor)
📡 Riesgo de exfiltración
las memorias compartidas entre usuarios (ej. "how-to" procedimentales) son como un memo para toda la empresa: si la memoria de un usuario se vuelve ejemplo para otro, el archivista hace anonimización rigurosa primero — previniendo fugas entre fronteras de usuario
Conclusión
De un simple turno conversacional a inteligencia persistente y accionable.
El viaje de un turno conversacional a inteligencia persistente está gobernado por la Context Engineering — armar dinámicamente histórico, memorias y conocimiento externo en la context window. Depende de la interacción de dos sistemas distintos e interconectados:
La Session gobierna el "ahora"
- desafío = rendimiento + seguridad: acceso de baja latencia y aislamiento estricto
- compactación vía truncado por tokens y sumarización recursiva
- redacción de PII ANTES de persistir — la seguridad es lo primero
La Memory gobierna el "siempre"
- va más allá del RAG (experto en hechos) para hacer al agente experto en el USUARIO
- pipeline ETL dirigido por LLM: extraction → consolidation → retrieval
- generación asíncrona en background + provenance + salvaguardas contra poisoning = asistentes que aprenden y crecen con el usuario
El contexto es un recurso gestionado, no un accidente
Cada token en la ventana tiene costo, latencia y peso atencional. Arma el payload dinámicamente: máxima relevancia, mínimo ruido.
Sessions y memory son simbióticos, pero distintos
La session es el log cronológico de una conversación; la memory es conocimiento extraído y curado entre conversaciones. Una alimenta a la otra — nunca las confundas.
La confianza se rastrea, se pondera y se poda
La provenance dice de dónde vino; los confidence scores dicen cuánto ponderarla; el olvido activo mantiene la base curada. Memoria sin curación es solo un log con pretensiones.
La memory gobierna el siempre."
Quiz
Ocho preguntas para consolidar el ciclo, las sessions y el pipeline de memoria.
Cheatsheets
Tres artefactos copiables para llevar a tu próximo proyecto de agente.
CONTEXT CYCLE — per-turn checklist ---------------------------------- [ ] FETCH - memories + RAG + recent events (query + metadata) [ ] PREPARE - full payload assembled (blocking, hot path) [ ] INVOKE - LLM + tools, append outputs as they arrive [ ] UPLOAD - persist events, trigger memory gen (background) COMPACTION decision tree history < 4k tokens - keep as-is 4k-16k tokens - keep-last-N / token truncation > 16k / long-running - recursive summarization (async + persist) TRIGGERS: count-based | time-based | event-based GOLDEN RULE: maximum relevance, minimum noise
MEMORY ETL — design recipe -------------------------- INGEST - raw conversation events (from the session store) EXTRACT - topic filter: define "meaningful" per agent purpose (schema / natural-language defs / few-shot examples) CONSOLIDATE - LLM decides: UPDATE | CREATE | DELETE-INVALIDATE dedup + conflict resolution + active forgetting STORE - vector DB / knowledge graph / hybrid TRIGGERS : session-end | every-N-turns | real-time | explicit SCOPE : user-level | session-level | application-level TIMING : generation ALWAYS async in background RULE : memories are descriptive, not predictive
RETRIEVAL — scoring and timing ------------------------------ SCORE = w1*relevance + w2*recency + w3*importance (never vector-similarity alone -> old/trivial memories resurface) TIMING proactive - preload each turn (cacheable, always available) reactive - memory-as-a-tool (agent decides, extra LLM call) PRECISION BOOSTERS (cost up, latency up) query rewriting -> reranking (top-50 -> top-K) -> specialized retriever + caching layer when memories are stable METRICS generation : precision / recall / F1 retrieval : recall@K / latency < 200ms (hot path) end-to-end : LLM judge vs golden answer
Checklists de implementación
Marca lo que ya dominas — tu progreso se guarda en este navegador.
📦Poner sessions en producción
🧠Construir un sistema de memoria
🛡️Endurecer para producción
Glosario
Los términos esenciales del paper, en lenguaje directo.
Continúa el viaje
Los papers complementarios de la serie — cada guía sigue el mismo formato interactivo y trilingüe.
Serie Agents Whitepaper — hub
Todas las guías de la serie en un solo lugar.
The New SDLC with Vibe Coding
El nuevo ciclo de vida de desarrollo de software: del código escrito a la intención orquestada.
Agent Tools & Interoperability
Los 5 protocolos abiertos que conectan agentes a herramientas y entre sí.
Vibe Coding Agent Security and Evaluation
Cómo evaluar y proteger agentes: quality gates, métricas y seguridad en producción.
Spec-Driven Production Grade Development
Desarrollo guiado por specs para llevar el vibe coding a nivel de producción.
Referencias
Las 30 endnotes del paper original, en orden de aparición.
MILAM, Kimberly; GULLI, Antonio. "Context Engineering: Sessions, Memory" — Agents Whitepaper Series, Google, Noviembre 2025.