Voltar ao Blog
AI & Development18 de julho de 202510 min de leitura

Memória de Agente Não é Uma Coisa Só. São Cinco Camadas.

DR

Doug Ribeiro

10 min de leitura

Toda vez que vejo um diagrama de arquitetura de agente onde "memória" é uma caixa única apontando para um banco vetorial, sei que o autor nunca precisou operar um além da demo. Memória em um agente não é um sistema único. É uma stack de cinco camadas, cada uma resolvendo um problema diferente, e você escolhe quais camadas precisa com base no que o agente realmente faz.

Vou caminhar pelas cinco camadas, no que cada uma é boa e ruim, e a combinação que eu colocaria em produção se você me pedisse para subir um agente operacional esta semana. Spoiler: Pinecone quase nunca é a resposta certa quando você já roda Postgres.

As Cinco Camadas

Scratchpad In-ContextApenas sessão atual. Vive no próprio prompt. 1 Cache (Redis ou Postgres)Sessões recentes, baseado em TTL. Rápido mas não semântico. 2 Store Estruturado (Postgres)Incidentes, decisões, resultados. Consultável por coluna. 3 Vector Store (pgvector)Recall semântico. "Já vimos algo parecido antes?" 4 Camada de SumarizaçãoCompressão via LLM quando o contexto fica grande demais. 5

Camada 1: Scratchpad In-Context

Este é o padrão. O LLM mantém seus pensamentos, ações e observações no próprio prompt. Zero infraestrutura. Funciona para demos e tarefas de um único passo. Falha no momento em que seu loop roda 15 iterações ou o agente precisa lembrar de algo depois que a sessão termina. Se o pitch que você está olhando tem apenas esta camada, é uma demo.

Camada 2: Cache

Redis com TTL de 24 a 72 horas é a resposta usual aqui. Esta camada guarda estado recente de sessão, resultados recentes de tool calls, preferências de usuário que ainda não pertencem ao store estruturado. O ganho é velocidade. A perda é que um cache chave-valor não é semântico, então você não pode perguntar "já vi um pedido parecido?", só "qual foi o pedido com ID X?". Se você ainda não roda Redis, não adicione por causa disso. Uma tabela unlogged do Postgres com uma coluna expires_at cobre o mesmo terreno sem nenhum serviço novo pra operar, e dá pra trocar no dia em que leituras de cache virarem de fato o seu gargalo.

Camada 3: Store Estruturado

Postgres. Chato, comprovado, e exatamente certo para os dados que têm colunas óbvias: ID do incidente, timestamp, versão do agente, tipo de trigger, tools chamadas, resultado, custo em tokens. Este é o seu audit log, a sua fonte de analytics, e a coisa que seu time de oncall de fato lê quando algo dá errado. Qualquer agente que você espera que passe numa auditoria precisa desta camada, porque ela é o único registro do que o agente de fato fez.

sql
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);

Camada 4: Vector Store

Esta é a camada que todo mundo fala e na qual a maioria dos times super-investe. O trabalho do vector store é recall semântico: "já tivemos um incidente que parece este?" Você embeda um resumo de incidentes passados, embeda a situação atual, e puxa os top K casos mais similares para dentro do prompt. Feito bem, isso transforma um agente reativo em um que aprende.

Minha opinião firme: se você já roda Postgres, use pgvector. É uma extensão do Postgres, não um serviço separado. Você tem busca semântica sem adicionar outro sistema pra operar, outra fronteira de auth, outro lugar sobre o qual seu oncall tem que saber às 2 da manhã. Pinecone, Weaviate, Qdrant são todos produtos bons. São exagero para a maioria dos times.

sql
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;

Camada 5: Sumarização

Esta não é storage. É compressão. Quando uma sessão roda longa, ou quando você puxa 20 incidentes passados do vector store e eles estourariam seu orçamento de contexto, você passa tudo por um LLM para produzir uma versão condensada. Esta é a camada que impede seus custos em tokens de explodir em agentes de longa duração. A maioria dos decks de introdução pula esta porque parece trivial até você ver a fatura.

Como as Camadas Realmente Interagem

Uma execução única de um agente DBA, de ponta a ponta:

  • Trigger dispara. Agente acorda com um payload de alerta.
  • Antes de chamar o planner do LLM, consulte o vector store em busca de incidentes passados similares. Puxe os top 5.
  • Rode esses 5 pela camada de sumarização para comprimir em algumas centenas de tokens.
  • Passe a memória comprimida mais o trigger mais o system prompt para o planner. Este é o estado inicial do scratchpad.
  • Loop: planeja, chama tool, observa, repete. Scratchpad cresce.
  • No fim, escreva o resultado estruturado no Postgres e um resumo semântico no pgvector. A próxima execução aprende com esta.

Nenhuma camada sozinha daria conta de tudo isso. Scratchpad te dá estado de sessão. Postgres te dá auditoria e analytics. pgvector te dá o "já vimos isso?". Sumarização impede o contexto de explodir. O cache cobre dados quentes que você não quer recalcular a cada execução.

A Stack Que Eu Realmente Colocaria em Produção

O Que Eu Colocaria em ProduçãoScratchpad: no prompt (padrão)Cache: uma tabela com TTL no me…Estruturado: Postgres 16Vetorial: extensão pgvector no …Compressão: um modelo barato, c…O Que Evito a Menos Que PrecisePinecone ou bancos vetoriais ge…Bancos de grafo como memória pr…APIs de embedding pagas (comece…Replicação de memória entre reg…VS

O Erro Que Mais Vejo

Times tratam memória como algo secundário. Constroem o loop, sobem em produção, e só depois parafusam memória três meses depois quando o agente começa a cometer o mesmo erro duas vezes. Nessa altura o log estruturado é um blob JSON no S3 sem schema, e você não consegue reconstruir o histórico porque nunca o capturou direito.

Desenhe o schema do Postgres antes de escrever a primeira tool call. Você não precisa construir a camada vetorial no dia um. Você precisa capturar cada execução com detalhe suficiente para que possa fazer backfill do vector store depois a partir dos mesmos dados.

O agente que lembra é um produto diferente do agente que reage. Escolha um de propósito.

Referências

AIAgentsMemorypgvectorRAG