Cada vez que veo un diagrama de arquitectura de agente donde la "memoria" es una sola caja apuntando a una base vectorial, sé que el autor no ha tenido que operar uno más allá de la demo. La memoria en un agente no es un sistema único. Es una stack de cinco capas, cada una resolviendo un problema distinto, y eliges qué capas necesitas según lo que el agente realmente hace.
Voy a recorrer las cinco capas, en qué es buena y en qué es mala cada una, y la combinación que yo pondría en producción si me pidieras levantar un agente operativo esta semana. Spoiler: Pinecone casi nunca es la respuesta correcta cuando ya corres Postgres.
Las cinco capas
Capa 1: Scratchpad in-context
Este es el default. El LLM guarda sus pensamientos, acciones y observaciones en el propio prompt. Cero infraestructura. Funciona para demos y tareas de un solo paso. Falla en el momento en que tu loop corre 15 iteraciones o el agente tiene que recordar algo después de que termina la sesión. Si el pitch que estás viendo solo tiene esta capa, es una demo.
Capa 2: Cache
Redis con un TTL de 24 a 72 horas es la respuesta habitual acá. Esta capa guarda el estado reciente de sesión, resultados recientes de tool calls, preferencias de usuario que todavía no pertenecen al store estructurado. La ganancia es velocidad. La pérdida es que un cache clave-valor no es semántico, así que no puedes preguntarle "¿he visto una solicitud similar?", solo "¿cuál fue la solicitud con ID X?". Si todavía no corres Redis, no lo agregues para esto. Una tabla unlogged de Postgres con una columna expires_at cubre el mismo terreno sin un servicio nuevo que operar, y la puedes cambiar el día en que las lecturas de cache sean de verdad tu cuello de botella.
Capa 3: Store estructurado
Postgres. Aburrido, probado, y exactamente lo correcto para los datos que tienen columnas obvias: ID de incidente, timestamp, versión del agente, tipo de trigger, tools llamadas, resultado, costo en tokens. Este es tu audit log, tu fuente de analytics, y lo que tu equipo de oncall realmente lee cuando algo se va al carajo. Cualquier agente del que esperes que pase una auditoría necesita esta capa, porque es el único registro de lo que el agente realmente hizo.
CREATE TABLE agent_runs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
agent_name TEXT NOT NULL,
agent_version TEXT NOT NULL,
trigger_type TEXT NOT NULL,
trigger_payload JSONB NOT NULL,
started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
ended_at TIMESTAMPTZ,
status TEXT NOT NULL,
outcome JSONB,
tool_calls JSONB,
token_cost INTEGER,
escalated_to_human BOOLEAN DEFAULT FALSE,
confidence NUMERIC(3,2)
);
CREATE INDEX idx_agent_runs_agent_started
ON agent_runs (agent_name, started_at DESC);
CREATE INDEX idx_agent_runs_trigger
ON agent_runs USING GIN (trigger_payload);Capa 4: Vector store
Esta es la capa de la que todos hablan y en la que la mayoría de los equipos sobreinvierten. El trabajo del vector store es el recall semántico: "¿hemos tenido un incidente que se siente como este?" Embed un resumen de incidentes pasados, embed la situación actual, y traes los top K casos más similares al prompt. Bien hecho, esto convierte un agente reactivo en uno que aprende.
Mi opinión fuerte: si ya corres Postgres, usa pgvector. Es una extensión de Postgres, no un servicio separado. Obtienes búsqueda semántica sin agregar otro sistema que operar, otra frontera de auth, otro lugar del que tu oncall tiene que saber a las 2 de la mañana. Pinecone, Weaviate, Qdrant son todos buenos productos. Son exceso para la mayoría de los equipos.
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE agent_memory (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
agent_name TEXT NOT NULL,
summary TEXT NOT NULL,
-- 384 dims matches all-MiniLM-L6-v2, which runs locally for free.
-- Bump this to your provider's dimension if you move to a hosted API.
embedding VECTOR(384) NOT NULL,
source_run_id UUID REFERENCES agent_runs(id),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_agent_memory_vector
ON agent_memory USING hnsw (embedding vector_cosine_ops);
-- Query: top 5 similar past incidents for a given embedding
SELECT id, summary, 1 - (embedding <=> $1) AS similarity
FROM agent_memory
WHERE agent_name = $2
ORDER BY embedding <=> $1
LIMIT 5;Capa 5: Resumen
Esta no es almacenamiento. Es compresión. Cuando una sesión corre larga, o cuando traes 20 incidentes pasados del vector store y reventarían tu presupuesto de contexto, los pasas por un LLM para producir una versión condensada. Esta es la capa que evita que tus costos de tokens exploten en agentes de larga duración. La mayoría de los decks introductorios la saltan porque parece trivial hasta que ves la factura.
Cómo las capas realmente interactúan
Una ejecución única de un agente DBA, de punta a punta:
- El trigger se dispara. El agente despierta con un payload de alerta.
- Antes de llamar al planner del LLM, consulta el vector store por incidentes pasados similares. Trae los top 5.
- Pasa esos 5 por la capa de resumen para comprimir en unos cientos de tokens.
- Pasa la memoria comprimida más el trigger más el system prompt al planner. Este es el estado inicial del scratchpad.
- Loop: planea, llama tool, observa, repite. El scratchpad crece.
- Al final, escribe el resultado estructurado a Postgres y un resumen semántico a pgvector. La próxima ejecución aprende de esta.
Ninguna capa por sí sola podría hacer todo eso. El scratchpad te da estado de sesión. Postgres te da auditoría y analytics. pgvector te da el "¿hemos visto esto?". El resumen evita que el contexto explote. El cache cubre los datos calientes que no quieres recalcular en cada ejecución.
La stack que yo realmente pondría en producción
El error que más veo
Los equipos tratan la memoria como algo secundario. Construyen el loop, lo ponen en producción, y luego atornillan memoria tres meses después cuando el agente empieza a cometer el mismo error dos veces. Para entonces el log estructurado es un blob JSON en S3 sin schema, y no puedes reconstruir la historia porque nunca la capturaste bien.
Diseña el schema de Postgres antes de escribir la primera tool call. No necesitas construir la capa vectorial en el día uno. Sí necesitas capturar cada ejecución con suficiente detalle para poder hacer backfill del vector store después desde los mismos datos.
El agente que recuerda es un producto distinto al agente que reacciona. Elige uno a propósito.
Referencias
- pgvector: https://github.com/pgvector/pgvector
- Anthropic, Building Effective Agents (patrones de diseño de agentes): https://www.anthropic.com/engineering/building-effective-agents
- Paper de MemGPT (memoria jerárquica para LLMs): https://arxiv.org/abs/2310.08560