[!NOTE] Tradução automática Este artigo foi traduzido automaticamente a partir da versão original em inglês.
AI Arquitetura de Memória de Agente em 2026: Checkpoints, Armazenamentos Vetoriais e Memória Baseada em Ficheiros
Parte 2 da série de engenharia da pilha Agentic
Um reasoning loop só consegue persistir por um único pedido, a menos que o seu estado seja armazenado fora do worker. Sem memória de agente, o agente não consegue retomar um plano interrompido, recuperar-se após uma falha ou recuperar uma preferência de uma sessão anterior. Parte 1 Abordou o fluxo de controle. Este artigo indica qual estado é necessário em cada turno subsequente e onde esse estado deve ser armazenado.
Vou explicar em detalhe a arquitetura de memória do Agente de Análise de Mercado, Vou demonstrar como os armazenamentos vetoriais checkpoints quentes, frios e a memória de documentos baseada em ficheiros funcionam em conjunto para agentes que devem permanecer ativos por um longo período de tempo. Em seguida, abordarei em que situações o PostgreSQL, o Redis, o Qdrant, os armazenamentos chave-valor e os ficheiros Markdown simples são a solução mais adequada.
TL;DR: Separe a memória de acordo com o padrão de acesso. A memória quente representa o estado em nível de thread checkpoint, utilizado para pausas e retomadas. A memória fria armazena factos entre sessões num repositório de tipo chave-valor ou num armazenamento vetorial. A memória de documentos guarda o conhecimento do projeto em ficheiros passíveis de inspeção. Comece por identificar a falha que precisa de ser resolvida e, em seguida, escolha o tipo de armazenamento adequado. Não coloque factos exatos num sistema de recuperação baseado em semelhanças, nem trate um checkpoint como um registo de auditoria.
O que é a memória de agente AI?
AI memória do agente é a camada de estado que permite a um agente manter o progresso das tarefas, recuperar conhecimentos anteriores e atualizar o que sabe em diferentes execuções. Em produção, não se trata de uma única base de dados vetorial; trata‑se de uma combinação de armazenamentos checkpoints ativos, armazenamentos semânticos ou estruturados inativos, bem como de uma memória de documentos legível por humanos.
| Preciso de | Melhor valor predefinido | Porquê? |
|---|---|---|
| Pausar e retomar uma execução | PostgreSQL checkpoint de armazenamento | Dados da aplicação duráveis, consultáveis e fáceis de operar |
| Estado transitório de baixa latência | Armazenamento Redis checkpoint | Recuperação rápida e estado de curta duração, com compromissos relacionados à persistência |
| Recuperação semântica entre sessões | Recupera memórias com base no significado, e não apenas em chaves exatas | |
| Dados estruturados do utilizador | PostgreSQL ou armazenamento de tipo chave-valor | Atualizações determinísticas superam a recuperação fuzzy para preferências e identificadores. |
| Convenções de projeto e procedimentos estabelecidos | Ficheiros em Markdown ou JSON | Legível por humanos, suscetível a diferenças e fácil de atualizar por agentes |
| Memória de relações entre múltiplas entidades | Gráfico de conhecimento | Útil quando as relações entre elementos são mais importantes do que os factos individuais. |
Não comece a falar da memória, pois soa a algo inteligente. Comece com o erro visível para o utilizador: perda de progresso, esquecimento de uma preferência, repetição de pesquisas ou incapacidade de reutilizar uma convenção de projeto.
As falhas que exigem memória
Um agente sem estado consegue responder a uma pergunta isolada, mas esquece o pedido assim que a chamada termina. Esse tipo de design falha quando o produto requer algum dos comportamentos seguintes:
- Pausa e retomada: um utilizador inicia uma tarefa de investigação, fecha o seu portátil e regressa no dia seguinte. Sem um estado com pontos de verificação, o agente tem de reiniciar tudo do zero.
- Coerência em múltiplas conversas: ao longo de uma conversa prolongada, o agente precisa de se lembrar das ferramentas que utilizou, dos dados que recolheu e das etapas do plano que já concluiu.
- Personalização: um utilizador que regressa espera que o agente conheça a sua tolerância ao risco, a profundidade preferida de análise e as interações anteriores.
- Human-in-the-loop (HITL): o agente elabora um relatório e aguarda aprovação. O estado de “aguardo” tem de ser mantido mesmo após reinícios do processo.
Na Agente de Análise de Mercado de Parte 1, O pedido “Analyze NVDA” gera um plano, cinco tool calls, dados recolhidos e um rascunho de relatório. Quando o utilizador responde “parece bom, mas adicione uma análise de concorrentes”, uma checkpoint store permite que o agente carregue o estado do nó anterior e inclua a etapa de análise de concorrentes. Sem um estado com pontos de verificação, não consegue determinar a que se refere o termo “parece bom” e é forçado a começar tudo de novo.
A memória de longo prazo lida com um caso diferente. Se o utilizador regressar uma semana depois e perguntar: “Atualize a minha análise da NVDA”, o agente poderá precisar de recuperar a preferência por avaliações de risco conservadoras e o interesse em ações de semicondutores. Um armazenamento de memória baseado em vetores consegue recuperar esses factos entre sessões, sem ser necessário pedi-los novamente.
O LangGraph divide os dados por escopo. Cada execução de grafo ocorre dentro de um thread, o que corresponde a uma conversa ou tarefa específica. O estado persistido nesse thread é considerado memória de curto prazo. Já o estado partilhado entre vários threads é classificado como memória de longo prazo. O contexto atual do modelo e as variáveis em processamento constituem a camada de memória de trabalho, localizada acima desses dois tipos de armazenamento.
Uma taxonomia da memória de agente AI
Antes de avançarmos para a implementação, é útil classificar o que os agentes precisam de memorizar. O CoALA framework (Sumers, Yao et al., 2023) constitui a taxonomia padrão e baseia‑se na ciência cognitiva. Eu introduzi o conceito de escopo de memória no meu context engineering publicação; Aqui, expando-o em seis categorias:
| Tipo de Memória | Escopo | Vida útil | Exemplo | Padrão de Armazenamento |
|---|---|---|---|---|
| Em funcionamento | Passo atual | Milissegundos | Tool call argumentos, resposta atual LLM | |
| Curto prazo | Tópico atual | Minutos–horas | Histórico de conversação, progresso do plano, dados recolhidos | Checkpoint armazenar |
| Episódico | Entre threads | Dias–meses | Na semana passada, o utilizador questionou sobre os resultados financeiros da NVDA. | Armazém de vetores / Armazém KV |
| Semântico | Entre threads | Meses – permanente | ”O utilizador prefere investimentos conservadores” | Armazém de vetores / Armazém KV |
| Documento | Entre threads | Dias – permanente | Notas de projeto, resumos de investigação, padrões identificados | Armazenamento de ficheiros (Markdown/JSON) |
| Processual | Em todo o sistema | Permanente | ”Ao analisar ações, verifique sempre os documentos apresentados à SEC.” | Configuração / system prompt |
Memória de trabalho é aquilo com o qual o LLM está a raciocinar ativamente neste momento: as variáveis em Python da função atual, o conteúdo da janela de contexto e os argumentos tool call em execução. Trata‑se da camada mais rápida, mas também a mais efémera; nada persiste para além do passo atual. A memória de trabalho é limitada pela janela de contexto do modelo, o que a torna o verdadeiro gargalo. Tudo o que o agente “sabe” no momento de tomar uma decisão tem de caber aqui, independentemente de ter vindo do armazenamento checkpoint, de uma consulta vetorial ou de uma leitura de ficheiro. As outras camadas existem para fornecer as informações corretas à memória de trabalho na altura certa.
Memória de curto prazo é o checkpoint que o LangGraph grava após cada nó. As memórias episódicas e semânticas permanecem ativas ao longo das threads. A memória de documento armazena notas de projeto, resumos de investigação e convenções aprendidas em ficheiros que podem ser consultados por pessoas e agentes. A memória procedural encontra-se nas instruções do sistema e nas definições de ferramentas, não sendo alterada para cada utilizador.
Para implementação, estas categorias reduzem‑se a três níveis. A memória quente armazena a sessão atual. A memória fria permite a recuperação de informações entre sessões. A memória de documentos mantém o conhecimento acumulado do projeto legível e diretamente editável.
O CoALA classifica a memória de trabalho, episódica, semântica e procedural. O Memória na Era dos Agentes AI: uma análise Dá ênfase aos repositórios vetoriais e aos grafos de conhecimento, ao mesmo tempo que o LangGraph documenta checkpoints e a sua interface Store. O conhecimento dos projetos armazenado em ficheiros fica fora dessas taxonomias, embora o Claude Code, o Cursor, o Windsurf e o Devin carreguem sempre ficheiros de projeto persistentes.
O mesmo padrão de armazenamento é observado noutros domínios. O Voyager guarda competências de jogos reutilizáveis como bibliotecas de código, as equipas do ECR3 trabalharam em documentos procedurais prompt, e a Memória de Fluxo de Trabalho do Agente permite gerar fluxos de trabalho web reutilizáveis a partir de episódios bem-sucedidos. Os ficheiros tornam esse conhecimento inspecionável e versionável, sem a necessidade de um serviço separado embedding.
A memória gerida por agente difere também de uma RAG pipeline fixa no que diz respeito à entidade responsável pela escrita. O agente ou o seu harness decide o que deve ser armazenado, atualizado ou eliminado, selecionando posteriormente o momento adequado para o recuperar.
O Artigo sobre Agentes Generativos (Park et al., 2023) demonstrou até que ponto isto é possível: agentes simulados conseguiram armazenar, refletir sobre e recuperar as suas próprias memórias. O seu fluxo de memória classificava os candidatos com base na recenteidade, importância e relevância, um design que continua a servir como um ponto de referência útil para a recuperação de memórias por parte dos agentes.
Memória de agente de curto prazo: o armazenamento checkpoint
Sempre que um nó do LangGraph é executado, o framework serializa todo o estado do grafo e grava‑o num checkpoint store. Essa é a base para funcionalidades de pausa/reinício, depuração com “time‑travel” e fluxos de trabalho HITL.
Um checkpoint contém o estado do grafo necessário para retomar: o AgentState de Parte 1 (mensagens, identidade, perfil de utilizador, passos do plano, dados de investigação, modo de execução), além de metadados do LangGraph como o nó que o gerou e o seu ID checkpoint. Após uma interrupção HITL ou reinício do processo, o grafo carrega o limite mais recente registado e regressa ao nó seguinte. Não continua a partir de uma linha de Python arbitrária. Um checkpoint também difere de um registo de eventos ou rastreio de apenas adição; Parte 5 separa de forma explícita essas superfícies de observabilidade runtime.
Como funciona o checkpointing no LangGraph
do LangGraph BaseCheckpointSaver é uma interface simples: put() escreve um checkpoint, get_tuple() lê o mais recente para um fio de discussão. list() devolve o histórico. Cada checkpoint é indexado por (thread_id, checkpoint_ns, checkpoint_id), onde thread_id identifica a conversa. checkpoint_ns lida com o nomeação de subgrafos, e checkpoint_id trata-se de uma versão única.
A decisão importante é determinar qual backend deve ser utilizado como suporte. O PostgreSQL e o Redis são duas opções bastante comuns em ambientes de produção.
PostgreSQL vs Redis
| Dimensão | PostgreSQL (langgraph-checkpoint-postgres) | Redis (langgraph-checkpoint-redis) |
|---|---|---|
| Modelo de durabilidade | Transações ACID, WAL e replicação | Persistência configurável em AOF ou RDB |
| Checkpoint histórico | Histórico duradouro para resumos e depuração | A retenção depende das definições de salvaguarda e de expulsão. |
| Restrição principal | Latência de escrita na base de dados e crescimento da tabela | Uso de RAM, expulsão de elementos e configuração de persistência |
| Adequação operacional | Equipes que já utilizam bases de dados relacionais | As equipas que já utilizam o Redis com elevado débito de processamento |
| Melhor opção padrão para | Recuperação de estado duradoura e depuração reprodutível | Estado de sessão recuperável e sensível à latência |
Bancos de dados genéricos benchmarks não permitem prever o desempenho checkpoint. É necessário medir o tamanho do estado serializado, a frequência de escrita, as configurações de persistência e a concorrência do seu próprio grafo.
PostgreSQL: o padrão duradouro por defeito
O PostgreSQL é a opção padrão mais segura para a maioria das equipas. Graças à capacidade de Checkpoints após falhas, dispõe-se de semânticas de transações completas, e o histórico de checkpoint torna a depuração por “viagem no tempo” extremamente simples.
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
async def create_postgres_checkpointer(connection_string: str) -> AsyncPostgresSaver:
"""Create a PostgreSQL-backed checkpoint store.
PostgreSQL gives us ACID guarantees — if a checkpoint write succeeds,
the state is durable even if the process crashes immediately after.
"""
checkpointer = AsyncPostgresSaver.from_conn_string(connection_string)
# Create the checkpoint tables if they don't exist.
# This is idempotent — safe to call on every startup.
await checkpointer.setup()
return checkpointer
# Usage: wire into the graph compilation
checkpointer = await create_postgres_checkpointer(
"postgresql://user:pass@localhost:5432/agent_memory"
)
graph = create_graph(checkpointer=checkpointer)
# Every invoke/stream call now persists state automatically
config = {"configurable": {"thread_id": "user-123-session-1"}}
result = await graph.ainvoke({"messages": [HumanMessage(content="Analyze NVDA")]}, config)
# Resume later — loads the latest checkpoint for this thread
result = await graph.ainvoke({"messages": [HumanMessage(content="approved")]}, config)
O AsyncPostgresSaver utiliza o langgraph-checkpoint-postgres package, que cria três tabelas: checkpoints (o estado serializado) checkpoint_blobs (dados binários de grande volume), e checkpoint_writes (Pendentes escritas para recuperação de falhas.) O esquema suporta acesso concorrente e utiliza bloqueios consultivos para evitar conflitos de escrita.
Redis: quando a latência é o gargalo
Quando uma latência de sub-milissegundo checkpoint é crítica (agentes de conversação em tempo real, ciclos de ferramentas de alta frequência), o Redis representa a escolha mais adequada.
from langgraph.checkpoint.redis.aio import AsyncRedisSaver
async def create_redis_checkpointer(redis_url: str) -> AsyncRedisSaver:
"""Create a Redis-backed checkpoint store.
Redis stores checkpoints in memory for sub-millisecond access.
Trade-off: less durable than PostgreSQL unless AOF is enabled.
"""
checkpointer = AsyncRedisSaver.from_conn_string(redis_url)
# Initialize Redis data structures
await checkpointer.setup()
return checkpointer
# Usage: same graph API, different backend
checkpointer = await create_redis_checkpointer("redis://localhost:6379")
graph = create_graph(checkpointer=checkpointer)
O AsyncRedisSaver de langgraph-checkpoint-redis armazena checkpoints como documentos JSON indexados por identificador de thread. O v0.1.0 de redesenho substituímos várias operações de busca por uma única JSON.GET Chamadas de API, reduzindo significativamente a latência. O Redis 8.0+ inclui por padrão o RedisJSON e o RediSearch — não é necessário instalar módulos adicionais.
Em implementações com restrições de memória, ShallowRedisSaver Armazena apenas a versão mais recente do checkpoint por thread — sem histórico, mas com consumo mínimo de RAM. Utilize este método quando precisar de pausar/recontinuar o processo, sem necessidade de depuração que permita retroceder no tempo.
Quando utilizar cada um
Utilize o PostgreSQL quando:
- É necessário ter um histórico completo de checkpoint para depuração em modo “viagem no tempo” ou para recriar o estado do sistema de forma fiável
- A durabilidade é um requisito indispensável (setores de serviços financeiros e saúde)
- Você já utiliza o PostgreSQL na sua arquitetura
- O seu agente executa tarefas de longa duração, nas quais a perda de estado acarreta horas extras de recálculo
- Você deseja um armazenamento unificado de dados — O PostgreSQL com pgvector pode funcionar como um único backend para checkpoints, memória de longo prazo e busca vetorial, simplificando assim a sua infraestrutura
Utilize o Redis quando:
- A latência de Checkpoint é o seu gargalo (chat em tempo real, experiência de utilizador em streaming)
- Está a desenvolver bots de voz — necessidade de conversão de STT para LLM e, em seguida, para TTS pipelines acesso ao estado em sub-milissegundos
- É necessário escalar horizontalmente em vários threads concorrentes
- Padrões de distribuição com alta concorrência, nos quais vários agentes partilham estado
- Sessões de curta duração, nas quais a perda de um checkpoint pode ser recuperada
- Pretende-se utilizar cache semântico para reduzir chamadas redundantes a LLM (Redis LangCache Armazena em cache consultas semanticamente semelhantes para evitar chamadas repetidas ao LLM)
Outras opções: langgraph-checkpoint-sqlite Funciona para desenvolvimento local e implementações em único processo. Para stacks nativas da AWS, langgraph-checkpoint-aws fornece um DynamoDBSaver Graças a um tratamento inteligente da carga útil — ficheiros pequenos checkpoints (<350 KB) permanecem no DynamoDB, enquanto os maiores são transferidos automaticamente para o S3. O modelo de preços serverless, aliado à ausência de infraestrutura a gerir, torna esta solução atrativa para implementações com cargas variáveis.
Memória de longo prazo: memorização entre sessões
A memória ativa lida com a conversa atual. Mas e o utilizador que regressar na próxima semana? A memória de longo prazo armazena factos, preferências e histórico de interações que permanecem válidos ao longo de várias sessões.
LangGraph oferece um Store interface para acesso à memória entre threads através da mesma BaseStore classe. Cada elemento de memória é um (namespace, key) emparelhar com um valor JSON e um vetor opcional embedding. O namespace codifica normalmente o utilizador ou a organização: ("user", "user-123", "preferences").
Armazenamento vetorial: recuperação semântica com o Qdrant
Quando o agente precisa recuperar factos não estruturados (“O que é que o utilizador disse sobre o seu cronograma de investimento?”), a busca vetorial permite uma recuperação semântica. Em vez de realizar buscas por palavras-chave exatas, o agente efetua consultas com base no significado.
Qdrant é uma base de dados vetorial desenvolvida especificamente em Rust, que lida com o armazenamento embedding, indexação (HNSW) e busca filtrada. Abordei em detalhe o HNSW e as suas contrapartidas no meu classificação de resultados de busca. Qdrant também disponibiliza um servidor MCP que atua como uma camada de memória semântica — útil se o seu agente framework suportar o Model Context Protocol.
De memory_store.py:
from qdrant_client import QdrantClient
from qdrant_client.models import PointStruct, Distance, VectorParams
from langchain_anthropic import ChatAnthropic
import hashlib
import json
class UserMemoryStore:
"""Long-term memory backed by Qdrant vector search.
Stores user facts as embedded vectors for semantic retrieval.
Each fact is a short natural-language statement about the user.
"""
def __init__(self, qdrant_url: str, collection_name: str = "user_memory"):
self.client = QdrantClient(url=qdrant_url)
self.collection_name = collection_name
self._ensure_collection()
def _ensure_collection(self):
"""Create the collection if it doesn't exist."""
collections = [c.name for c in self.client.get_collections().collections]
if self.collection_name not in collections:
self.client.create_collection(
collection_name=self.collection_name,
vectors_config=VectorParams(
size=1536, # text-embedding-3-small dimensions
distance=Distance.COSINE,
),
)
def store_fact(self, user_id: str, fact: str, embedding: list[float]):
"""Store a user fact with its embedding."""
point_id = hashlib.md5(f"{user_id}:{fact}".encode()).hexdigest()
self.client.upsert(
collection_name=self.collection_name,
points=[PointStruct(
id=point_id,
vector=embedding,
payload={"user_id": user_id, "fact": fact},
)],
)
def recall(self, user_id: str, query_embedding: list[float], top_k: int = 5):
"""Retrieve the most relevant facts for a user given a query."""
results = self.client.query_points(
collection_name=self.collection_name,
query=query_embedding,
query_filter={"must": [{"key": "user_id", "match": {"value": user_id}}]},
limit=top_k,
)
return [hit.payload["fact"] for hit in results.points]
O fluxo é o seguinte: (1) após cada conversa, um LLM extrai os factos-chave da interação (“o utilizador tem uma alta tolerância ao risco”, “o utilizador está interessado em ações de semicondutores”), (2) esses factos são incorporados e armazenados no Qdrant, (3) no início da próxima conversa, o agente faz uma consulta ao Qdrant com a nova mensagem do utilizador para recuperar o contexto relevante.
Pontuação de recuperação: para além da semelhança coseno
A semelhança coseno bruta é um ponto de partida, mas os sistemas de memória em produção exigem uma recuperação de informações mais sofisticada. Artigo sobre Agentes Generativos (Park et al., 2023) introduziram uma função de pontuação que combina três sinais:
- Recência: Decaimento baseado em regras, de modo que as memórias mais recentes recebem uma pontuação mais alta. Uma função de decaimento exponencial faz com que um fato de ontem supere em importância um fato equivalente de seis meses atrás.
- Importância: Significância avaliada através de LLM numa escala de 1 a 10. A afirmação “O portfólio do utilizador caiu 40%” tem uma pontuação maior do que “O utilizador disse olá”.
- Relevância: Semelhança coseno Embedding entre a consulta e o fato armazenado.
A pontuação final de recuperação é uma soma ponderada: score = alpha * recency + beta * importance + gamma * relevance. Isso impede que factos recentes e importantes fiquem submersos sob informações obsoletas, mas semanticamente semelhantes. Para o Agente de Análise de Mercado, Eu atribuo maior peso à relevância (0.5), seguida pela recentesidade (0.3) e pela importância (0.2), uma vez que a intenção da consulta atual do utilizador é o fator mais determinante. Trata‑se de pesos de ponto de partida adaptados do artigo sobre Agentes Gerativos (que utilizava ponderações iguais); verifiquei que dar maior ênfase à relevância funciona melhor para consultas de análise financeira, mas estes valores baseiam‑se em intuição e não foram otimizados empiricamente.
Alternativas à busca vetorial
A busca vetorial é poderosa, mas nem sempre é a ferramenta adequada. Eis quando se devem utilizar alternativas:
| Abordagem | O melhor para | Principal custo operacional |
|---|---|---|
| Busca vetorial (Qdrant) | Recuperação semântica de factos não estruturados | Embedding e ciclo de vida do índice |
| Armazém de chave-valor (Redis) | Perfis de utilizador e preferências estruturadas | Política de utilização de memória e persistência |
| Armazém de documentos (ficheiros) | Conhecimento do projeto e notas geridas pelo agente | Concorrência, permissões e busca |
| Pesquisa em texto completo (PostgreSQL) índice GIN)** | Recuperação de palavras-chave a partir do histórico da conversação | Crescimento do índice e otimização de consultas |
| Gráfico de conhecimento (Neo4j) | Relações entre entidades e consultas de vários saltos | Modelação de grafos e outro sistema de dados |
| Híbrido (vetor + palavra-chave) | Lembre-se de quando a intenção da consulta varia | Dois caminhos de pontuação a ajustar e avaliar |
Os armazenamentos chave-valor funcionam de forma eficaz para dados estruturados. Se a sua memória de longo prazo corresponder a um perfil de utilizador — tolerância ao risco, horizonte de investimento, setores preferidos —, um hash do Redis ou uma coluna JSONB do PostgreSQL é uma solução mais simples e rápida do que embedding e a consulta de vetores. Utilize a busca por vetores quando a memória for não estruturada e as consultas de recuperação variarem em termos de formulação.
A Loja integrada do LangGraph oferece uma interface de tipo chave-valor baseada em namespace, com busca vetorial opcional. O BaseStore API é simples: put(), get(), search(), e delete() com escopo de namespace hierárquico. Existem três implementações disponíveis:
InMemoryStore— para desenvolvimento e teste (dados perdidos na saída do processo)PostgresStore— armazenamento persistente em produção com consultas SQL completasAsyncRedisStore— memória entre threads com busca vetorial, suporte a TTL e filtragem de metadados
O index A configuração permite a realização de busca vetorial em itens armazenados, recorrendo a um modelo embedding configurável. Para muitos casos de uso, este repositório integrado é suficiente, evitando a necessidade de recorrer a uma base de dados vetorial dedicada.
from langgraph.store.memory import InMemoryStore
# Create a store with vector search enabled
store = InMemoryStore(
index={
"dims": 1536,
"embed": my_embedding_function, # e.g., OpenAI text-embedding-3-small
}
)
# Store a user preference (namespace scopes to user)
await store.aput(
namespace=("user", "user-123", "preferences"),
key="risk-profile",
value={"risk_tolerance": "high", "horizon": "long-term"},
)
# Semantic search across user's memories
results = await store.asearch(
namespace=("user", "user-123"),
query="What is their investment style?",
limit=5,
)
Escolha de uma estratégia de memória de longo prazo
Comece com estruturas de tipo chave-valor caso a sua memória esteja organizada e bem definida (perfis de utilizador, definições de configuração, entidades nomeadas). Adicione a busca vetorial quando precisar de recuperação semântica em dados não estruturados ou quando a formulação das consultas varia de forma imprevisível.
Graphos de conhecimento tornam-se úteis quando as relações entre entidades são relevantes, por exemplo: “Quais empresas sobre as quais o utilizador perguntou são concorrentes da NVDA?” O projeto mais interessante desenvolvido recentemente neste âmbito é Graphiti (por Zep), que constrói um gráfico de conhecimento com consciência temporal que regista quando os factos eram verdadeiros, e não apenas o que era verdadeiro. Cada aresta possui intervalos de validade, de modo que uma alteração na tolerância ao risco do utilizador invalida o valor antigo em vez de o substituir silenciosamente. O Graphiti reporta 94,8% de precisão no DMR benchmark, E o seu modelo bitemporal resolve o problema da memória obsoleta na camada de dados.
O problema reside no aspeto operacional. Executar uma base de dados gráfica não é tarefa simples, e, para a maioria das aplicações de agente, a busca vetorial com filtragem de metadados cumpre o mesmo objetivo com menos infraestrutura.
Memória gerida frameworks como Mem0 e Letta (O anteriormente conhecido como MemGPT) trata por si da extração, consolidação e recuperação pipeline. A abordagem do Mem0 é notável: um LLM extrai as memórias candidatas, um motor de decisão compara cada novo fato com as entradas existentes no armazenamento vetorial, e um resolvedor decide se deve adicionar, atualizar ou eliminar essas informações, o que mantém o armazém de memórias coerente e sem redundâncias. O Letta adota uma perspetiva inspirada em sistemas operativos: os agentes gerem a sua própria janela de contexto utilizando ferramentas de gestão de memória, movendo autonomamente dados entre a “memória principal” (dentro do contexto) e a “memória de arquivamento” (fora do contexto). Ambas as soluções merecem ser avaliadas caso pretenda acelerar o tempo até à produção sem necessidade de controlo total sobre a gestão da memória pipeline.
Memória de documento: o armário de arquivamento do agente
A memória baseada em ficheiros apresenta uma adoção por parte de mais produtos do que a cobertura nas taxonomias de memória mencionadas anteriormente. Numa avaliação LoCoMo realizada por um fornecedor, Letta informou 74,0% devido à abordagem baseada em ficheiro sistema que utiliza. É possível manter esse resultado dentro das condições do seu modelo, benchmark e harness, mas a vantagem operacional é facilmente perceptível: os desenvolvedores podem ler, editar e comparar diferenças no conhecimento armazenado diretamente.
Janelas de contexto mais extensas também tornam viável a leitura de ficheiros inteiros para alguns documentos de projeto. A recuperação em blocos continua a ser adequada para grandes corpora, mas um ficheiro curto com convenções ou informações de transferência pode frequentemente ser carregado diretamente. A escolha depende do tamanho do documento, da precisão da recuperação, do orçamento de contexto e da frequência com que as pessoas precisam de rever ou editar essa memória.
Os armazenamentos vetoriais e os backends de tipo chave-valor lidam bem com a recuperação semântica e com buscas estruturadas. No entanto, existe uma terceira categoria de conhecimento dos agentes que nenhum desses sistemas consegue tratar de forma eficaz: o contexto acumulado do projeto, que inclui convenções, notas de pesquisa e decisões de que o agente necessita ao longo das sessões, e que se beneficia de ser legível por humanos e estar sujeito a controlo de versões.
Isto é memória de documento: o agente lê e escreve ficheiros estruturados (Markdown, JSON, YAML) num diretório conhecido. Sem embeddings, sem base de dados, sem infraestrutura. Apenas ficheiros no disco que tanto o agente como o desenvolvedor podem aceder. cat, grep, git diffe editar manualmente.
Porquê ficheiros?
Em fluxos de trabalho de agentes de longa duração, o padrão mais eficaz que já observei não é uma base de dados vetorial. Trata-se de um diretório com notas bem organizadas. Pense no que acontece quando um agente de programação trabalha num projeto ao longo de semanas:
- Ele percebe que o projeto utiliza o Pydantic v2, e não v1 - Ele descobre que os testes devem ser executados com
pytest -x --tb=short - Acumula conhecimento sobre a arquitetura do código-fonte
- Aprende as preferências do desenvolvedor (“usar sempre”)
pathlib, nuncaos.path”)
Estes factos têm uma estrutura demasiado complexa para serem pesquisados por vetores (é necessária uma recuperação exata, e não uma semelhança difusa), e são demasiado numerosos para serem armazenados num repositório tipo chave-valor (eles formam documentos interligados, e não factos isolados). Além disso, são factos que o desenvolvedor deseja visualizar e editar diretamente. Se o agente aprender algo incorretamente, basta abrir o ficheiro e corrigi-lo.
Isto é como do Claude Code CLAUDE.md e .claude/ Trabalho com diretórios. O agente lê o nível do projeto CLAUDE.md arquivos para convenções e instruções, e efetua escritas em ~/.claude/MEMORY.md para o aprendizado entre sessões. Os ficheiros são em Markdown puro: você lê-os, edita-os, faz commit no Git e partilha-os com a sua equipa. cursor do .cursorrules e Windsurfar .windsurfrules ficheiros de texto puro que o agente carrega na inicialização para obter o contexto do projeto.
Implementação de um armazenamento em memória para ficheiros
A implementação é deliberadamente simples. O agente dispõe de quatro operações: escrever um documento, ler um documento, listar os documentos disponíveis e realizar uma busca em vários documentos por palavra-chave.
De file_memory.py:
from pathlib import Path
import json
import fnmatch
class FileMemory:
"""Document memory backed by the local filesystem.
Stores agent knowledge as human-readable files organized by topic.
No embeddings, no database — just files that both the agent and
the developer can read, edit, and version-control.
"""
def __init__(self, base_dir: str | Path):
self.base_dir = Path(base_dir)
self.base_dir.mkdir(parents=True, exist_ok=True)
def write_doc(self, path: str, content: str, metadata: dict | None = None):
"""Write or overwrite a document at the given path.
Paths are relative to base_dir. Directories are created automatically.
Metadata (if provided) is stored as a JSON sidecar file.
"""
full_path = self.base_dir / path
full_path.parent.mkdir(parents=True, exist_ok=True)
full_path.write_text(content, encoding="utf-8")
if metadata:
meta_path = full_path.with_suffix(full_path.suffix + ".meta")
meta_path.write_text(json.dumps(metadata, indent=2), encoding="utf-8")
def read_doc(self, path: str) -> str | None:
"""Read a document by path. Returns None if not found."""
full_path = self.base_dir / path
if full_path.exists():
return full_path.read_text(encoding="utf-8")
return None
def list_docs(self, pattern: str = "**/*") -> list[str]:
"""List documents matching a glob pattern."""
return [
str(p.relative_to(self.base_dir))
for p in self.base_dir.glob(pattern)
if p.is_file() and not p.name.endswith(".meta")
]
def search_docs(self, query: str, pattern: str = "**/*.md") -> list[dict]:
"""Search documents by keyword. Returns matching files with context.
This is intentionally simple — grep-style keyword search.
For semantic search, use a vector store instead.
NOTE: This is a sketch for demonstration. A simple substring check
won't scale beyond a few hundred documents. For production with 500+
documents, use TF-IDF/BM25 scoring (e.g., rank_bm25) or a full-text
search backend (PostgreSQL GIN index, Elasticsearch).
"""
results = []
for path in self.base_dir.glob(pattern):
if not path.is_file() or path.name.endswith(".meta"):
continue
content = path.read_text(encoding="utf-8")
if query.lower() in content.lower():
# Return the paragraph containing the match for context
for paragraph in content.split("\n\n"):
if query.lower() in paragraph.lower():
results.append({
"path": str(path.relative_to(self.base_dir)),
"match": paragraph.strip()[:500],
})
return results
Estrutura de pastas
A maior parte do valor da memória de documento advém da forma como o diretório é estruturado. Eis a estrutura que utilizo para o Agente de Análise de Mercado:
.agent-memory/
README.md # What this directory is, for human readers
user-profiles/
user-123.md # Preferences, history, risk profile
user-456.md
research/
NVDA-2026-02.md # Research notes from recent analysis
TSLA-2026-01.md
conventions/
analysis-format.md # How to structure analysis reports
data-sources.md # Preferred data sources and API patterns
learnings/
common-errors.md # Mistakes the agent has learned to avoid
tool-patterns.md # Effective tool call sequences
Cada ficheiro é em formato Markdown. A finalidade de cada ficheiro é evidente a partir do seu caminho. Pode git diff o diretório inteiro de memória para ver o que o agente aprendeu numa sessão, git revert Um mau processo de aprendizagem pode ocorrer se o diretório for copiado para outro projeto. Experimente realizar qualquer uma dessas ações com uma coleção Qdrant.
Quando utilizar memória de documento, vetores ou estrutura chave-valor
Os três backends de memória suportam padrões de acesso diferentes:
| Dimensão | Armazém de Vetores | Armazém Chave-Valor | Armazém de Documentos |
|---|---|---|---|
| Padrão de consulta | ”Encontrar factos semelhantes a X” | Obter o valor para a chave | ”Leia o documento localizado no caminho indicado.” |
| Ideal para | Recuperação não estruturada e variada | Consultas estruturadas | Contexto do projeto, notas |
| Legível para humanos | Não (embeddings) | Parcialmente (JSON) | Sim (Markdown) |
| Possível de depurar | Difícil (escores de similaridade) | Trivial (abrir o ficheiro) | |
| Versão controlável | Não | Possível | |
| Embedding infraestrutura | Obrigatório | Não é necessário | Não é necessário |
| Escala para | Milhões de factos | Milhões de chaves | Milhares de documentos |
| Capacidade de busca | Semelhança semântica | Correspondência exata | Baseado em palavra-chave/caminho |
Utilize a memória de documento quando:
- O agente acumula conhecimento sobre o projeto ao longo de várias sessões
- Os desenvolvedores precisam de inspecionar, editar ou substituir o que o agente “sabe”
- O conhecimento é estruturado como documentos (notas, resumos, convenções) e não como factos isolados
- Pretende-se uma gestão de versões da memória do agente baseada em Git
- A ausência total de infraestrutura é um requisito obrigatório
Utilize armazenamentos vetoriais quando:
- É necessário recuperação semântica difusa (“encontrar memórias relacionadas com X”)
- A formulação das consultas varia de forma imprevisível
- Existem milhares a milhões de factos individuais
Utilize armazenamentos de tipo chave-valor quando:
- É necessário realizar consultas precisas e rápidas a dados estruturados (perfis de utilizador, definições)
- O esquema de dados está bem definido
Na prática, os agentes de produção costumam combinar os três tipos. O Agente de Análise de Mercado Utiliza o PostgreSQL checkpoints para armazenamento em memória rápida, o Qdrant para recuperação eficiente de factos semânticos relacionados aos utilizadores, e um repositório de documentos baseado em ficheiros para guardar as convenções do projeto e as notas de investigação.
Exemplos do mundo real
O padrão já está amplamente difundido em assistentes de codificação AI:
- Claude Code lê
CLAUDE.mdarquivos da raiz do projeto e das diretórias pai, e escreve para~/.claude/MEMORY.mdpara aprendizagens entre sessões. Todo o sistema de memória é composto por ficheiros em Markdown simples que são submetidos juntamente com o código. - Cursor carrega
.cursorrulesArquivos com instruções específicas para o agente do projeto: convenções de codificação, preferências framework, decisões arquitetónicas. - O Windsurf utiliza
.windsurfrulesarquivos, além de ummemories/diretório onde o agente armazena os padrões aprendidos a partir da sua base de código. - A ferramenta de memória da Anthropic para o Claude API oferece
create_memory,read_memory,update_memory, edelete_memoryAs operações são implementadas no lado do cliente. A sua aplicação decide onde os ficheiros residem efetivamente (disco local, S3, base de dados).
O fator comum: todos eles armazenam o conhecimento do agente como ficheiros de texto legíveis por humanos, com operações de leitura/escrita explícitas. Sem embeddings. Sem infraestrutura vetorial. O agente decide o que escrever, o desenvolvedor pode visualizar e editar tudo, e todo o sistema cabe em um git diff.
Para além dos assistentes de programação
A memória de documentação não se limita aos agentes de programação. Este padrão é observado em domínios de agentes muito diversos:
-
Agentes de jogos de mundo aberto: Voyager (Wang et al., 2023) desenvolveu uma biblioteca de competências persistente composta por programas em JavaScript verificados, que um agente do Minecraft acumula ao longo do tempo, permitindo a recolha de 3,3 vezes mais itens únicos e a alcançar marcos 15,3 vezes mais rapidamente em comparação com as versões de referência. Essas competências são transferidas para novos mundos sem necessidade de retreinamento. JARVIS-1 Estende-se este modelo com uma memória multimodal que integra planos textuais e observações visuais, alcançando uma taxa de sucesso de 5 vezes superior nas tarefas mais difíceis.
Uma distinção importante a fazer aqui: as bibliotecas de competências são memória executável (ficheiros de código importados e executados), enquanto a memória de documentos em assistentes de programação é declarativa (Markdown injetado em prompts). Os modos de falha diferem. Código executável defeituoso faz com que o agente travar; texto declarativo defeituoso leva a erros de raciocínio. No entanto, o padrão de armazenamento e os benefícios operacionais (possibilidade de depuração, controlo de versões) são os mesmos.
-
Automação de fluxos de trabalho empresariais: A competição ECR3 Os vencedores utilizaram a memória de documentos para uma refinação iterativa prompt. Os agentes Analyzer e Versioner de uma das equipas vencedoras percorreram 80 prompt versões armazenadas como documentos procedurais. Outra equipa de destaque desenvolveu mais de 20 módulos enriquecedores sob a forma de conhecimento procedural no estilo de documento. LEGOMem (2025) formaliza isto como uma memória modular framework para sistemas multi-agent, contendo tipos de memória especializados (sensorial, de curto prazo e de longo prazo) que os agentes combinam como blocos de construção.
-
Automação da Web: Memória de Fluxo de Trabalho do Agente (Wang et al., 2024) permite que agentes web criem fluxos de trabalho reutilizáveis a partir de episódios bem-sucedidos, obtendo uma melhoria de 51% na taxa de sucesso em WebArena. SkillWeaver (2025) vai ainda mais longe: os agentes sintetizam ferramentas API reutilizáveis a partir da exploração, obtendo um aumento de 31,8% na taxa de sucesso. As competências adquiridas transferem-se também para modelos menos potentes (melhoria de 54,3%), pelo que a memória acumulada por um agente mais forte consegue impulsionar um modelo de menor dimensão.
-
Suporte ao cliente: Gartner prevê Esses agentes AI irão resolver de forma autónoma 80% dos problemas comuns de atendimento ao cliente até 2029. Para o efeito, eles recorrem a SOPs, playbooks e históricos de clientes, que representam todas elas formas de memória documental.
O Workshop MemAgents no ICLR 2026 É um sinal de que a comunidade de investigação está a alcançar o que os profissionais já desenvolveram. O Document Memory superou claramente as suas origens como ferramenta de assistência à programação.
As competências utilizam documentos para embalar instruções procedimentais. O Padrão de Habilidades de Agente armazena essas instruções em SKILL.md ficheiros com frontmatter em YAML e um corpo em Markdown. Isso assemelha-se à memória de documento a nível da camada de armazenamento, mas o seu papel é diferente: uma habilidade indica ao agente como realizar um determinado tipo de tarefa, enquanto a memória regista factos aprendidos com um projeto ou com execuções anteriores. Parte 3 aborda essa distinção do ponto de vista da ferramenta.
MCP (Protocolo de Contexto do Modelo) segue na mesma direção: as definições de ferramentas são ficheiros JSON Schema que qualquer agente pode descobrir e utilizar. O protocolo possui 97 milhões de downloads mensais SDK é suportado pela OpenAI, Google, Microsoft e AWS. O MCP não é específico de programação. Os mesmos servidores conectam os agentes a bases de dados, APIs internos e sistemas empresariais.
Ambos apontam para o mesmo padrão: conhecimento procedural armazenado como documentos sujeitos a esquemas, com operações de leitura/escrevimento explícitas. MCP, agora regulado pelos Agentic AI Fundação, É o que existe de mais próximo de um padrão de interoperabilidade no ecossistema de agentes.
Escalonamento da memória de documento para produção
A implementação baseada em ficheiros apresentada acima funciona bem em portáteis de desenvolvedores individuais e em implementações em pequena escala. Uma produção multi-tenant com centenas de utilizadores e milhares de documentos exige uma arquitetura completamente diferente.
O limite de ficheiros em nodo único torna-se evidente: não é possível escalar as operações de E/S de ficheiros horizontalmente, as escritas concorrentes exigem bloqueio, e gerir permissões entre diferentes utilizadores é complexo. A produção necessita de um armazenamento de suporte que gere corretamente a concorrência, a pesquisa e o modelo de multi-tenant.
Três abordagens comuns:
Abordagem A: híbrida com uma camada de base de dados leve
Mantenha os ficheiros para criação (os desenvolvedores editam o Markdown localmente), mas sirva-os a partir de uma base de dados em runtime. Durante a implementação, sincronize os ficheiros com as linhas da PostgreSQL. O agente lê a informação diretamente da base de dados, e não do disco. Isto permite-lhe:
- Ergonomia para desenvolvedores (editar Markdown, fazer commits no git)
- Desempenho de consultas em produção (leituras em bancos de dados indexados)
- Separação clara entre a fase de criação e serving
Abordagem B: armazenamento de objetos + sidecar de índice vetorial
Os documentos são armazenados no S3/GCS na forma de objetos, sendo que existe uma coleção Qdrant responsável por indexar os seus embeddings. O agente consulta o Qdrant em busca dos IDs dos documentos relevantes e, em seguida, retira o conteúdo a partir do armazenamento de objetos. Esta arquitetura permite escalabilidade horizontal e suporta pesquisas semânticas, mas acarreta alguma complexidade: é necessário gerir dois sistemas distintos, realizar uma embedding pipeline constante para mantê-los sincronizados, e lidar com a consistência eventual entre o armazenamento e o índice.
Abordagem C: armazenamento estruturado de documentos com PostgreSQL (recomendado)
Armazene documentos como linhas JSONB no PostgreSQL, aproveitando a busca por texto completo (índice GIN) e, opcionalmente, vetores embeddings (pgvector). Isto permite-lhe realizar uma busca híbrida (por palavras-chave + semântica), utilizar transações ACID e contar com um único sistema operacional.
Esboço da Abordagem C:
from typing import Optional
import asyncpg
class ProductionDocumentMemory:
"""PostgreSQL-backed document memory with hybrid search.
Schema:
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
tenant_id TEXT NOT NULL,
path TEXT NOT NULL,
content TEXT NOT NULL,
metadata JSONB,
embedding vector(1536), -- pgvector extension
ts_vector tsvector GENERATED ALWAYS AS (to_tsvector('english', content)) STORED,
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(tenant_id, path)
);
CREATE INDEX ON documents USING GIN(ts_vector);
CREATE INDEX ON documents USING ivfflat(embedding vector_cosine_ops);
"""
def __init__(self, pool: asyncpg.Pool):
self.pool = pool
async def write(
self,
tenant_id: str,
path: str,
content: str,
metadata: Optional[dict] = None,
embedding: Optional[list[float]] = None,
):
"""Write or update a document."""
async with self.pool.acquire() as conn:
await conn.execute(
"""
INSERT INTO documents (tenant_id, path, content, metadata, embedding)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (tenant_id, path) DO UPDATE
SET content = EXCLUDED.content,
metadata = EXCLUDED.metadata,
embedding = EXCLUDED.embedding
""",
tenant_id, path, content, metadata, embedding,
)
async def search(
self,
tenant_id: str,
query: str,
embedding: Optional[list[float]] = None,
limit: int = 5,
) -> list[dict]:
"""Hybrid search: full-text + optional vector similarity."""
async with self.pool.acquire() as conn:
if embedding:
# Hybrid scoring: 0.6 * text relevance + 0.4 * vector similarity
rows = await conn.fetch(
"""
SELECT path, content, metadata,
(0.6 * ts_rank(ts_vector, plainto_tsquery('english', $2)) +
0.4 * (1 - (embedding <=> $3))) AS score
FROM documents
WHERE tenant_id = $1
AND ts_vector @@ plainto_tsquery('english', $2)
ORDER BY score DESC
LIMIT $4
""",
tenant_id, query, embedding, limit,
)
else:
# Full-text search only
rows = await conn.fetch(
"""
SELECT path, content, metadata,
ts_rank(ts_vector, plainto_tsquery('english', $2)) AS score
FROM documents
WHERE tenant_id = $1
AND ts_vector @@ plainto_tsquery('english', $2)
ORDER BY score DESC
LIMIT $3
""",
tenant_id, query, limit,
)
return [dict(row) for row in rows]
O que recebe:
- Pesquisa híbrida: correspondência de palavras-chave (índice GIN) + similaridade semântica (pgvector), com as pontuações somadas
- Multi-tenantismo:
tenant_idDefinição de escopo com segurança a nível de linha - Garantias ACID: ausência de problemas de consistência eventual
- Sistema operativo único: não é necessário gerir uma base de dados vetorial separada
- Escala horizontal: réplicas de leitura para suportar o volume de consultas, particionamento por cliente para aumentar a capacidade de escrita
Os ficheiros são ideais para fluxos de trabalho com um único desenvolvedor. Em ambientes de produção com vários utilizadores, um armazenamento de documentos estruturado no PostgreSQL costuma oferecer o equilíbrio ideal entre simplicidade, desempenho e maturidade operacional.
Montagem final: a arquitetura completa
Aqui está como os três níveis de memória funcionam em conjunto no Agente de Análise de Mercado. O diagrama ilustra o fluxo completo, desde o pedido do utilizador até à resposta, com todas as camadas de memória ativas.
A arquitetura possui três caminhos de memória:
-
Caminho crítico (checkpoint de armazenamento): Cada nó no LangGraph grava o seu estado de grafo suscetível a retomada no checkpoint de armazenamento. Quando o grafo atinge um
interrupt_beforenode (tal como o relator em Parte 1), Pausas na execução. O utilizador pode fechar a aplicação e, quando regressar, o gráfico é retomado a partir do checkpoint. Os registos de eventos e os rastreios Runtime representam questões distintas de produção. -
Caminho frio (armazenamento de longo prazo): No início de cada conversa, o agente consulta o armazenamento de longo prazo em busca de contexto do utilizador relevante. No final, ele extrai e guarda novos factos. Este processo é executado de forma assíncrona — não deve, em nenhum caso, bloquear o reasoning loop principal.
-
Caminho do documento (armazenamento de ficheiros): Na inicialização, o agente carrega as convenções do projeto e as notas de investigação relevantes a partir do armazenamento de documentos. Durante a execução, ele grava novos resumos de investigação e padrões aprendidos de volta no disco. Ao contrário do caminho “frio”, as leituras de documentos são síncronas (pois fornecem informações para a tarefa atual), enquanto as escritas podem ser adiadas.
A estrutura de conexões no LangGraph é bastante simples — o checkpoint store e o long-term store são transmitidos durante a compilação do grafo, enquanto o document store é inserido como uma dependência. O esboço local abaixo utiliza InMemoryStore Assim, o trecho permanece compacto; a topologia Docker de referência utiliza o Qdrant para desempenhar a mesma função de recuperação semântica.
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
from langgraph.store.memory import InMemoryStore
# Hot memory: PostgreSQL for durable checkpoints
checkpointer = await create_postgres_checkpointer(pg_connection_string)
# Cold memory: local sketch with vector search
# (The reference Docker topology uses Qdrant for persistent recall.)
memory_store = InMemoryStore(
index={"dims": 1536, "embed": embedding_function}
)
# Document memory: file-based store for project knowledge
doc_memory = FileMemory(base_dir=".agent-memory")
# Checkpoint store and long-term store wired into the graph
graph = create_graph(
checkpointer=checkpointer,
store=memory_store,
)
# The store is accessible inside any node via the store parameter
def planner_node(state: AgentState, *, store: BaseStore) -> dict:
"""Plan with user context from long-term memory."""
# Recall relevant user facts from vector store
user_memories = store.search(
namespace=("user", state.user_id),
query=state.messages[-1].content,
limit=5,
)
# Load project conventions from document memory
conventions = doc_memory.read_doc("conventions/analysis-format.md")
# Inject both into planning context
memory_context = "\n".join(m.value["fact"] for m in user_memories)
# ... rest of planning logic with personalized context and conventions
O fluxo completo
O que acontece quando um utilizador recorrente envia “Analyze TSLA” para o Agente de Análise de Mercado:
-
Carga de memória dos documentos: Na inicialização, o agente lê as convenções do projeto armazenadas no repositório de documentos: preferências de formato de análise, fontes de dados preferidas e padrões de utilização de ferramentas. Estes fatores definem o comportamento de base.
-
Recuperação de memória a frio: Antes de o nó roteador ser executado, o grafo consulta o armazenamento de longo prazo em busca da mensagem do utilizador. É recuperada a seguinte informação: “O utilizador tem uma alta tolerância ao risco”, “O utilizador prefere análises detalhadas dos concorrentes” e “O utilizador já investigou a NVDA e a AMD”.
-
Router + Planner: A classe de router classifica isto como
DEEP_RESEARCHO planeador cria um plano de investigação composto por 5 passos, personalizado de acordo com as preferências identificadas. Inclui uma etapa de análise da concorrência, uma vez que o histórico do utilizador indica que este deseja esse tipo de análise. O plano segue o formato definido no documento de convenções. -
Loop do executor (memória ativa): Cada passo é executado através do padrão ReAct a partir de Parte 1. Após cada nó (roteador, planeador e cada passo do executor), o LangGraph escreve um checkpoint no PostgreSQL. Se o processo falhar após o passo 3 de um total de 5, basta reiniciá‑lo para continuar a partir do passo 4.
-
Interrupção HITL: o gráfico atinge o
reporternó cominterrupt_before. O rascunho do relatório encontra-se no checkpoint. O utilizador analisa-o algumas horas depois, e o gráfico carrega o checkpoint e continua a ser exibido. -
Atualizações de memória: Após o término da conversa: (a) um processo assíncrono extrai novos factos do utilizador (“o utilizador está agora a seguir a TSLA”, “o utilizador aprovou o formato do relatório”) e armazena-os no repositório de vetores de longo prazo, e (b) o agente escreve um resumo da investigação no repositório de documentos.
research/TSLA-2026-02.md) para referência futura.
O padrão de três camadas separa as responsabilidades de forma clara. O checkpoint store gere a durabilidade e a retomada de operações; trata-se da infraestrutura. O armazenamento de longo prazo é responsável pela personalização; corresponde à lógica do produto. O armazenamento de documentos contém o conhecimento acumulado sobre os projetos; funciona como o caderno de anotações do agente.
Compromissos e considerações
A memória agrega valor, mas também aumenta os custos e a complexidade. Seja honesto quanto aos compromissos envolvidos:
-
Embedding custo: Cada fato armazenado numa base de dados vetorial requer uma chamada embedding API. O custo é de $0,02 por milhão de tokens (OpenAI
text-embedding-3-small), o custo por operação é insignificante, mas acaba se somando ao longo de milhares de utilizadores e sessões. É necessário agrupar as chamadas embedding em lotes e armazenar em cache os resultados. O verdadeiro custo reside na latência: 100–300 ms de latência embedding API no momento da consulta para recuperar dados de memória não armazenada, o que tem maior impacto do que o custo monetário em agentes de conversação em tempo real. Armazene em cache embeddings as consultas mais frequentes ou utilize um modelo embedding local para cargas de trabalho sensíveis à latência. -
Memória desatualizada: As preferências do utilizador mudam. Um facto armazenado há seis meses (“o utilizador prefere investimentos conservadores”) pode já não ser preciso. Defina políticas de expiração. Eu utilizo 365 dias para as preferências e 90 dias para eventos episódicos, conforme descrito no meu context engineering publicação.
-
Custo de memória no contexto: Cada facto recuperado consome tokens na janela de contexto do LLM. Se recuperar 20 factos por consulta, isso representa centenas de tokens de contexto em memória que competem com a tarefa propriamente dita. Limite o número de factos recuperados e dê prioridade aos que possuem maior pontuação de relevância.
-
Privacidade e conformidade: A memória de longo prazo armazena os dados dos utilizadores. É necessário realizar a redação de PII antes do armazenamento, definir políticas claras de retenção e disponibilizar controlos acessíveis aos utilizadores para a eliminação de dados. Nenhuma destas medidas é opcional em setores regulamentados.
-
Checkpoint crescimento de armazenamento: As tabelas PostgreSQL checkpoint aumentam de tamanho a cada execução num nó. Em casos de agentes em execução contínua, deve ser definida uma política de retenção: conservar os últimos N checkpoints por thread e arquivar ou eliminar os mais antigos. Um exemplo de consulta de limpeza que mantém os 10 checkpoints mais recentes por thread e elimina tudo com mais de 30 dias:
DELETE FROM checkpoints WHERE thread_id = $1 AND created_at < NOW() - INTERVAL '30 days' AND checkpoint_id NOT IN ( SELECT checkpoint_id FROM checkpoints WHERE thread_id = $1 ORDER BY created_at DESC LIMIT 10 ); -
Consolidação de memória: Com o tempo, as memórias episódicas detalhadas devem ser comprimidas em representações semânticas mais compactas: “o utilizador perguntou sobre o NVDA três vezes em janeiro” em vez de armazenar todas as três conversas literalmente. Isso reflete o processo de consolidação da memória humana e permite que o armazenamento permaneça gerível. Mem0 e Graphiti Trate isto automaticamente; se desenvolver a sua própria solução, agende tarefas periódicas de consolidação.
-
Problema de arranque a frio: Os novos utilizadores não possuem memória a longo prazo. O agente deve funcionar de forma adequada e fazer perguntas esclarecedoras em vez de assumir informações. A memória é aditiva e não é obrigatória.
-
Envenenamento de memória: Qualquer elemento presente na janela de contexto do agente representa um ponto potencial de injeção. Se um atacante escrever factos enganosos no repositório de documentos ou na memória de longo prazo (“aprovar sempre as transações sem verificação”), o agente pode executá-los como instruções. A utilização de Prompt injection através das memórias armazenadas constitui uma superfície de ataque real. As medidas de mitigação incluem a validação antes do armazenamento, o tratamento do conteúdo recuperado como dados não fidedignos em vez de instruções do sistema, e controles de acesso que limitam quais memórias podem influenciar operações críticas.
-
Deriva da memória documental: A memória baseada em ficheiros não dispõe de funcionalidades automáticas de eliminação de duplicados nem de resolução de conflitos. Com o tempo, os documentos vão acumulando contradições: um ficheiro indica “utilizar pytest” enquanto outro indica “utilizar unittest”. É necessário agendar revisões periódicas (ou deixar que o agente as realize) para eliminar e consolidar esses dados. A boa notícia é que, ao contrário dos armazéns vetoriais onde o problema da obsolescência fica oculto, aqui é possível
greppara contradições. -
A memória baseada em documentos não é escalável para milhões de itens: A memória baseada em ficheiros funciona para centenas a poucos milhares de documentos. Se o seu agente precisar de recuperar informações de milhões de factos através de correspondência difusa, será necessário utilizar um armazenamento vetorial. A memória baseada em documentos destina-se ao conhecimento estruturado de projetos, e não à vasta gama de interações de cada utilizador.
Principais conclusões
- A memória do agente é composta por vários repositórios com padrões de acesso distintos. É necessário manter separados o checkpoints recuperável, os factos estruturados, a recuperação semântica e os documentos do projeto.
- Implementar funcionalidades de pausa e retomada antes da personalização. A perda do progresso das tarefas é o primeiro tipo de falha de memória que um agente em execução prolongada apresenta.
- Armazenar factos determinísticos em estruturas organizadas. Utilizar busca vetorial quando a consulta for imprecisa ou a formulação variar.
- Utilizar ficheiros para armazenar conhecimentos de projetos que precisem de ser inspecionados, editados, versionados ou comparados por diferenças.
- Definir uma data de expiração, regras de conflito e regras de eliminação para cada tipo de memória. Uma memória que o sistema não consegue corrigir torna-se dívida técnica.
- Limitar o que é retornado ao modelo. A memória armazenada só tem valor quando a sua recuperação fornece as evidências adequadas para o contexto atual.
A próxima camada corresponde à ação
Parte 3, AI Agente Tool Use em 2026, Passa do estado armazenado para uma ação. Aborda como um agente descobre e utiliza ferramentas, bem como como os limites dessas ferramentas retornam erros que o reasoning loop pode processar. As partes 5 e 6 voltam a tratar da memória do ponto de vista operacional: o runtime restaura um checkpoint, enquanto o harness decide quais elementos devem ser transmitidos para a próxima sessão do modelo.
Referências
Artigos Científicos
- Arquiteturas Cognitivas para Agentes de Língua (CoALA) — Sumers, Yao et al., 2023 — Taxonomia fundamental dos tipos de memória de agente A Memória na Era dos Agentes AI: Uma Análise — Dez 2025 — Taxonomia tridimensional abrangente da memória de agente
- MemGPT: Rumo a LLMs como sistemas operativos — Packer et al., 2023 — Gestão de contexto virtual para agentes LLM Agentes Generativos: Simulacros Interativos do Comportamento Humano — Park et al., 2023 — Arquitetura de fluxo de memória com avaliação de recentidade, importância e relevância Zep: Uma Arquitetura de Grafo de Conhecimento Temporal para a Memória de Agentes — Rasmussen, 2025 — Grafo de conhecimento bitemporal para memória de agente
- Mem0: Criação de Agentes AI prontos para produção com memória de longo prazo escalável — 2025 — Extração/consolidação pipeline com benchmarks
- Voyager: Um Agente Encarnado de Finalidade Aberta com Modelos de Língua Grande — Wang et al., 2023 — Biblioteca de competências como memória de documentos para agentes de jogos de mundo aberto
- JARVIS-1: Agentes multi-tarefa em mundo aberto com modelos de linguagem multimodal reforçados por memória — 2023 — Biblioteca de memória multimodal para agentes do Minecraft Memória de Fluxo de Trabalho do Agente — Wang et al., 2024 — Indução de fluxos de trabalho reutilizáveis para agentes de automação da Web SkillWeaver: Os Agentes Web conseguem projetar autonomamente as suas bibliotecas de competências — 2025 — Ferramentas reutilizáveis API auto-sintetizadas para agentes web
- LEGOMem: Memória modular Framework para sistemas de agente LLM — 2025 — Módulos de memória componíveis para sistemas multi-agent
Documentação do LangGraph
- Persistência do LangGraph (Criação de pontos de verificação) — Conceitos fundamentais para memória baseada em checkpoint Armazenamento de Memória LangGraph — Interligar a memória de longo prazo entre threads com a interface Store
- Persistência Cruzada de Threads no LangGraph — Funcionalidade API para memória entre threads Como adicionar memória ao agente ReAct pré-construído — Guia prático para adicionar memória
Checkpoint backends
langgraph-checkpoint-postgres— Salvaguarda do PostgreSQL checkpoint para o LangGraphlanggraph-checkpoint-redis— Salvaguarda do Redis checkpoint para o LangGraph LangGraph Redis Checkpoint 0.1.0 – Redesenho — Detalhes de arquitetura para o salvaguardador do Redis checkpointlanggraph-checkpoint-aws— Salvaguarda do DynamoDB checkpoint com descarregamento para o S3
Bases de dados vetoriais e ferramentas de memória
- Qdrant — Banco de dados vetorial de código aberto com indexação e filtragem HNSW Guia de Construção do Qdrant Agentic — Guia prático para construir memória de agente com Qdrant
- pgvector — Extensão de busca por similaridade vetorial para PostgreSQL Graphiti — Motor de grafo de conhecimento temporal de código aberto desenvolvido pela Zep
Memória baseada em documentos e ficheiros
- Memória do Claude Code — Sistema de memória baseado em ficheiros CLAUDE.md e MEMORY.md Ferramenta de Memória Anthropic — Memória baseada em ficheiros no lado do cliente para agentes Claude API
- Regras do Cursor — Ficheiros .cursorrules a nível de projeto para o contexto do agente Memórias de Windsurf — Memória baseada em ficheiros e .windsurfrules para a programação de agentes
Memória frameworks
- Mem0 — Camada de gestão de memória com extração/consolidação pipeline
- Letta (MemGPT) — Gestão de contexto virtual inspirada em sistemas operativos para agentes
- LangMem SDK — Ferramentas de gestão de memória para o LangGraph
Benchmarks
- Desempenho PostgreSQL vs Redis — Latência e taxa de transferência da CyberTec benchmarks
- Comparação PostgreSQL vs Redis — Comparação de arquiteturas RisingWave
- Engenharia de Agente Redis AI — Padrões do Redis para cargas de trabalho de agentes
Workshops
- MemAgents: Memória para sistemas Agentic baseados em LLM — Workshop ICLR 2026
Projeto de demonstração
- Agente de Análise de Mercado — Implementação completa com os três níveis de memória
O código completo do Market Analyst Agent, incluindo a arquitetura de memória descrita neste artigo, encontra-se em GitHub se quiser seguir a leitura.
Série: Engenharia da pilha Agentic
- Parte 1: AI Laços de Raciocínio de Agente em 2026 — ReAct, ReWOO e Plan-and-Execute
- Parte 2: Arquitetura de Memória de Agente AI em 2026 (este artigo) Parte 3: AI Agente Tool Use em 2026 — MCP, CLI, competências, execução de código e ACI Parte 4: AI Segurança de Agentes em 2026 — restrições de segurança, permissões, sandboxes, HITL e delimitação de escopo por MCP
- Parte 5: Agente AI de execução contínua Runtime em 2026 — sessões, sandboxes, checkpoints, mecanismos de aproveitamento e formas de implementação
- Parte 6: Harness Engineering para Agentes AI (a ser publicada em breve) — verificações de aceitação, rastreios, tentativas repetidas, transferências de responsabilidade e o ciclo associado ao modelo