Memória e Estado
Visão geral: por que “memória” e “estado” importam em agentes de LLM
Agentes de LLM (large language models, modelos de linguagem grandes) são projetados para executar ações em múltiplas etapas: eles interpretam um objetivo, chamam ferramentas, observam resultados, atualizam seu entendimento e continuam. Dois conceitos determinam se isso funciona de forma confiável para além de um único prompt:
- Estado: a representação atual do “que está acontecendo” — o status da tarefa, observações do ambiente, resultados intermediários, restrições e decisões.
- Memória: informações retidas ao longo do tempo para influenciar o comportamento futuro — histórico da conversa, preferências do usuário, resultados anteriores de ferramentas, fatos aprendidos e planos anteriores.
Sem um tratamento explícito de memória/estado, agentes tendem a:
- repetir trabalho (“Qual foi mesmo a resposta da API?”),
- perder objetivos e restrições,
- contradizer saídas anteriores,
- falhar em tarefas de longo horizonte devido a limites de contexto, e
- se comportar de forma imprevisível ao retomar após interrupção.
Este artigo foca em como representar, atualizar e persistir memória/estado para agentes de LLM na prática, com teoria suficiente para tornar escolhas de design fundamentadas. Ele complementa Uso de Ferramentas e Orquestração (como agentes chamam ferramentas e se recuperam de falhas) e Sistemas Multiagentes (como múltiplos agentes coordenam e compartilham informações).
Definições-chave e modelos mentais
Memória vs. estado (distinção prática)
Em implementações de agentes, ajuda separar:
Estado (estado de trabalho)
O retrato autoritativo e estruturado usado para decidir a próxima ação. Exemplos:- etapa atual em um plano
- variáveis (datas, IDs, saídas parciais)
- resultados de chamadas de ferramenta que precisam ser referenciados com precisão
- o que já foi tentado (para evitar loops)
Memória (informação retida)
Informações armazenadas para recuperação posterior, e muitas vezes nem tudo é necessário o tempo todo. Exemplos:- uma transcrição longa da conversa (episódica)
- preferências do usuário (semântica)
- uma biblioteca de incidentes resolvidos ou runbooks
- “lições aprendidas” anteriores de execuções do agente
Uma regra útil: o estado deve ser pequeno, preciso e verificável por máquina; a memória pode ser grande, imprecisa e orientada por recuperação.
Memória de curto prazo vs. longo prazo
Para agentes de LLM, “curto prazo” e “longo prazo” dizem respeito principalmente a onde a informação vive e como é acessada:
Memória de curto prazo: informação dentro da janela de contexto atual do modelo (prompt), incluindo:
- instruções de sistema/desenvolvedor,
- a conversa recente,
- um rascunho / substituto de cadeia de pensamento (chain-of-thought) (frequentemente oculto em sistemas modernos),
- documentos recuperados selecionados, e
- o estado atual serializado.
Memória de longo prazo: informação armazenada fora do modelo e buscada conforme necessário:
- bancos de dados, arquivos, armazenamentos de objetos,
- armazenamentos vetoriais (vector stores) (recuperação baseada em embeddings),
- logs de eventos, traces e transcrições,
- grafos de conhecimento.
Como janelas de contexto são finitas e caras, um problema central de engenharia é decidir o que manter em contexto vs. o que persistir e recuperar.
Tipos de memória (emprestados da ciência cognitiva, úteis no design)
Embora não seja uma analogia perfeita, essas categorias mapeiam bem para sistemas de agentes:
Memória episódica: “o que aconteceu” (experiências com marcação temporal)
- chamadas de ferramenta e resultados
- turnos de conversa
- decisões e justificativas (ou resumos delas)
Memória semântica: “o que é verdade” (fatos e conhecimento)
- preferências do usuário (“prefere respostas concisas”)
- fatos de domínio (“Produto X usa OAuth2”)
- regras/políticas organizacionais
Memória procedural: “como fazer as coisas” (habilidades e rotinas)
- fluxos de trabalho, playbooks, templates
- padrões de invocação de ferramentas (frequentemente implementados em código em vez de texto armazenado)
Na prática, a memória procedural frequentemente vive no código do orquestrador, enquanto a memória episódica/semântica vive em armazenamentos.
Fundamentos teóricos: estado, observabilidade parcial e crença
Estado em tomada de decisão sequencial
O comportamento de um agente é naturalmente enquadrado como tomada de decisão sequencial, comumente formalizada como um Processo de Decisão de Markov (MDP): um estado (s_t) resume tudo o que é necessário para escolher uma ação (a_t) que afeta o próximo estado (s_{t+1}).
Implantações reais de agentes normalmente estão mais próximas de POMDPs (MDPs parcialmente observáveis): o agente não vê o verdadeiro estado do ambiente, apenas observações (saídas de ferramentas, mensagens do usuário). O agente precisa manter um estado de crença (belief state) — uma representação do que ele acredita ser verdade.
Implicação para agentes de LLM: memória/estado não é apenas armazenamento. É o mecanismo pelo qual um agente:
- acompanha hipóteses vs. fatos confirmados,
- lida com informações ausentes,
- evita ações contraditórias, e
- escolhe o que perguntar ou recuperar em seguida.
Representações: de texto não estruturado a estado estruturado
LLMs são treinados para operar sobre sequências de texto (ver Arquitetura Transformer), mas agentes confiáveis frequentemente precisam de representações estruturadas:
- para permitir verificações determinísticas,
- para impedir que injeção de prompt altere a “verdade”,
- para retomar execuções, e
- para suportar chamadas de ferramenta e esquemas.
Um padrão comum é estado híbrido:
- campos estruturados para dados autoritativos (IDs, datas, contadores, booleanos),
- resumos não estruturados para contexto narrativo,
- links/proveniência para documentos-fonte e saídas de ferramentas.
Isso é semelhante, em espírito, a híbridos “neural + simbólico”: modelos neurais para interpretação, estruturas simbólicas para controle.
O que deve estar no estado do agente?
Um estado de agente prático normalmente inclui:
Estado da tarefa
- objetivo, subobjetivos, restrições
- critérios de “concluído”
- marcadores de progresso (etapa atual, etapas restantes)
Estado da conversa
- intenção mais recente do usuário
- perguntas não resolvidas
- acordos firmados (“Entregaremos até sexta-feira”)
Estado de ferramentas/ambiente
- últimas chamadas de ferramenta + resultados (ou ponteiros para eles)
- informações de autenticação/sessão (cuidado com segredos)
- metadados de limite de taxa / tentativas de repetição
Estado de conhecimento
- fatos considerados verdadeiros, com confiança/proveniência
- hipóteses em aberto que precisam de verificação
Estado de segurança e políticas
- ferramentas/ações permitidas
- tags de classificação de dados
- requisitos de redação (redaction)
Exemplo: um esquema mínimo de estado estruturado
{
"run_id": "b3a2...",
"user_id": "u123",
"goal": "Book a flight and hotel for the conference",
"constraints": {
"max_budget_usd": 1800,
"dates": {"depart": "2026-03-10", "return": "2026-03-14"},
"airport": "SFO"
},
"progress": {
"stage": "hotel_search",
"completed_steps": ["collect_constraints", "flight_search"],
"pending_questions": ["Do you prefer Marriott or Hilton?"]
},
"facts": [
{
"key": "conference_city",
"value": "Austin",
"provenance": {"type": "user_message", "message_id": "m17"},
"confidence": 0.95
}
],
"tool_log_refs": ["toolcall_91", "toolcall_92"],
"memory_refs": {
"episodic": ["evt_1001", "evt_1002"],
"semantic": ["pref_7"]
}
}
Esse tipo de esquema facilita validar transições de estado e persistir/retomar execuções com segurança.
Memória de curto prazo: usando a janela de contexto de forma eficaz
Memória de curto prazo é tudo que você decide colocar no prompt do modelo na etapa atual. As principais restrições são:
- capacidade (tamanho da janela de contexto),
- custo (tokens),
- diluição de atenção (texto demais reduz o uso efetivo),
- conteúdo adversarial (riscos de injeção de prompt).
Estratégias comuns de memória de curto prazo
1) Janela deslizante (apenas turnos recentes)
Mantenha as últimas N mensagens e descarte as mais antigas.
- Prós: simples, barato
- Contras: perde restrições importantes anteriores; quebra tarefas longas
2) Sumarização / compactação
Periodicamente sumarize conversas mais antigas em uma forma mais curta.
- Prós: preserva informações-chave; reduz tokens
- Contras: resumos podem omitir detalhes ou introduzir erros
Uma abordagem confiável é sumarizar em campos estruturados, não apenas em prosa. Por exemplo:
- “restrições conhecidas”
- “decisões tomadas”
- “perguntas em aberto”
- “resultados de ferramentas (apenas IDs)”
3) Seleção do “conjunto de trabalho”
Mantenha um pequeno conjunto de itens atualmente relevantes:
- a etapa atual do plano,
- a última saída de ferramenta,
- as restrições necessárias para a próxima decisão.
Isso se assemelha ao cache de CPU: você quer o conjunto de trabalho ativo em memória rápida (prompt) e todo o resto em memória mais lenta (bancos de dados).
Exemplo prático: padrão de prompt para compactação
Quando uma conversa cresce, chame uma etapa de “atualização de estado” que produza um estado estruturado atualizado.
def update_state(llm, prev_state, recent_messages):
prompt = f"""
You are a state-tracking component. Update JSON state using new messages.
Rules:
- Preserve existing fields unless contradicted by new evidence.
- Put uncertain info under "hypotheses".
- Do not invent IDs or facts.
State JSON:
{prev_state}
New messages:
{recent_messages}
Return ONLY valid JSON.
"""
return llm(prompt)
Isso separa geração de chat de manutenção de estado, melhorando a confiabilidade.
Memória de longo prazo: persistência e recuperação
A memória de longo prazo armazena informações fora do prompt e as busca quando necessário. Isso inclui padrões clássicos de Geração Aumentada por Recuperação (Retrieval-Augmented Generation, RAG), mas agentes frequentemente precisam de mais do que “recuperar documentos”:
- logs persistentes de execução,
- perfis/preferências de usuários,
- saídas de ferramentas e arquivos,
- históricos de tarefas para retomada.
Opções de armazenamento (e para que são boas)
- Banco de dados relacional (SQL): estado estruturado autoritativo, transações, restrições
- melhor para: estado de execução, status de workflow, permissões
- Banco de dados de documentos (NoSQL): estado JSON flexível, logs de eventos
- melhor para: esquemas evolutivos, transcrições
- Armazenamento de objetos: artefatos grandes (PDFs, imagens, saídas de ferramentas)
- Banco de dados vetorial: recuperação semântica via Embeddings
- melhor para: “encontrar incidentes / notas relevantes do passado”
- veja também: Bancos de Dados Vetoriais
- Grafo de conhecimento: entidades/relações, cenários com muita proveniência
- melhor para: “quem é dono do quê”, grafos de dependência, governança
Na maioria dos sistemas reais você usará múltiplos armazenamentos: SQL para estado, armazenamento de objetos para artefatos, armazenamento vetorial para recuperação.
O que deve ser armazenado como memória de longo prazo?
Uma política prática é:
Armazenar tudo que é necessário para auditoria e reprodutibilidade:
- chamadas de ferramenta (entradas/saídas), timestamps, versões
- prompts (ou templates + parâmetros), IDs de modelo
- transições de estado do agente
Armazenar seletivamente para personalização:
- preferências estáveis do usuário (com consentimento)
- contexto recorrente (fuso horário, função, estilo de escrita)
Armazenar seletivamente para recordação semântica:
- decisões, conclusões, fatos extraídos
- resumos de interações longas
- links para transcrições brutas (não dependa apenas de resumos)
Estratégias de recuperação: além de “top-k embeddings”
Similaridade por embedding é poderosa, mas imperfeita. Uma boa recuperação para agentes frequentemente combina:
- similaridade semântica (busca vetorial),
- restrições por palavra-chave (BM25 / filtros),
- filtros de metadados (user_id, project_id, intervalo de tempo, tags de segurança),
- recência (preferir informação mais nova),
- importância/saliência (fixar itens críticos),
- diversidade (evitar quase-duplicatas).
Um padrão comum em produção é recuperação híbrida:
- filtrar por permissões e escopo,
- combinar similaridade vetorial + correspondência por palavra-chave,
- reclassificar (re-rank) com um codificador cruzado (cross-encoder) ou um ranqueador baseado em LLM,
- comprimir resultados (extrair apenas trechos relevantes).
Estratégias de persistência para agentes (durabilidade e capacidade de retomada)
Persistência é como você torna um agente robusto a:
- falhas de processo,
- limites de taxa e falhas de ferramentas,
- workflows de longa duração,
- etapas assíncronas de aprovação humana,
- tentativas de repetição e requisitos de idempotência.
1) Checkpointing (snapshots)
Periodicamente persista o estado completo do agente (o JSON estruturado) como um checkpoint.
- Prós: fácil retomar (“carregar último checkpoint”)
- Contras: pode perder causalidade em granularidade fina; pode sobrescrever histórico útil
Checkpointing funciona melhor quando combinado com um log de eventos.
2) Event sourcing (logs append-only)
Persista cada etapa como um evento imutável:
- mensagem do usuário recebida
- ferramenta chamada
- ferramenta retornou
- estado atualizado
- decisão tomada
Para reconstruir o estado atual, reproduza (replay) os eventos (opcionalmente a partir do último snapshot).
- Prós: auditabilidade, depuração, reprodutibilidade
- Contras: mais complexo; requer gestão cuidadosa de esquema/versões
3) Snapshot + log de eventos (mais comum)
- Escreva um evento append-only para cada ação.
- Escreva snapshots ocasionalmente para recuperação rápida.
Esta é uma abordagem padrão em sistemas distribuídos e mapeia bem para traces de agentes.
4) Idempotência e desduplicação
Chamadas de ferramenta e transições de estado devem ser resilientes a retries. Técnicas comuns:
- incluir uma chave de idempotência (idempotency key) por ação,
- armazenar resultados de chamadas de ferramenta indexados por (run_id, step_id),
- detectar etapas repetidas e reutilizar saídas anteriores.
Isso é especialmente importante em padrões de Uso de Ferramentas e Orquestração que envolvem retries/timeouts.
5) Modelos de consistência para execuções multiagentes ou distribuídas
Se múltiplos agentes compartilham memória, você deve decidir:
- escritor único (single-writer) (um agente é dono do estado; outros leem)
- múltiplos escritores (multi-writer) com resolução de conflitos
- consistência transacional vs. eventual
Para ambientes colaborativos, abordagens como CRDTs podem ajudar, mas muitos sistemas evitam complexidade usando:
- estado local por agente + uma base de conhecimento compartilhada somente-leitura,
- ou um coordenador que serializa atualizações.
Veja Sistemas Multiagentes para questões específicas de coordenação.
Juntando tudo: uma arquitetura de referência para memória/estado
Uma arquitetura comum e prática introduz um Gerenciador de Memória (Memory Manager) e um Armazenamento de Estado (State Store) dedicados:
- Armazenamento de Estado (autoritativo): JSON estruturado em SQL/NoSQL
- Log de Eventos (auditoria): eventos append-only
- Armazenamento de Artefatos: saídas de ferramentas, arquivos
- Índice de Memória: armazenamento vetorial construído a partir de eventos/resumos selecionados
- Camada de Recuperação: realiza recuperação filtrada + híbrida
- Construtor de Prompt: monta a memória de curto prazo (conjunto de trabalho)
Exemplo de fluxo para uma etapa do agente
- Carregar o estado estruturado atual (checkpoint).
- Recuperar memórias relevantes de longo prazo (filtrada + híbrida).
- Construir o prompt:
- políticas do sistema,
- objetivo atual e estado estruturado,
- últimos turnos,
- trechos recuperados (com citações),
- instrução para produzir a próxima ação + patch de estado.
- A LLM propõe uma ação (chamada de ferramenta ou pergunta ao usuário) e uma atualização de estado.
- Executar a chamada de ferramenta (se houver).
- Registrar evento(s), atualizar estado e possivelmente atualizar o índice de memória.
- Repetir.
Código ilustrativo mínimo (pseudo-Python)
class AgentRuntime:
def __init__(self, state_store, event_log, retriever, llm, tools):
self.state_store = state_store
self.event_log = event_log
self.retriever = retriever
self.llm = llm
self.tools = tools
def step(self, run_id, user_message=None):
state = self.state_store.load(run_id)
if user_message:
self.event_log.append(run_id, {"type": "user_message", "text": user_message})
query = self._make_retrieval_query(state, user_message)
memories = self.retriever.retrieve(query, filters={"user_id": state["user_id"]})
prompt = self._build_prompt(state, user_message, memories)
proposal = self.llm.generate_json(prompt) # e.g., {"action": ..., "state_patch": ...}
self.event_log.append(run_id, {"type": "model_proposal", "proposal": proposal})
result = None
if proposal["action"]["type"] == "tool_call":
tool_name = proposal["action"]["name"]
args = proposal["action"]["args"]
result = self.tools[tool_name].call(args)
self.event_log.append(run_id, {"type": "tool_result", "tool": tool_name, "result": result})
new_state = self._apply_patch(state, proposal["state_patch"], tool_result=result)
self.state_store.save(run_id, new_state)
self._maybe_index_memory(run_id, new_state, proposal, result)
return new_state
A ideia importante é a separação de responsabilidades:
- atualizações de estado são explícitas e persistidas,
- resultados de ferramentas são registrados em log,
- indexação de memória é seletiva e orientada por políticas.
Modos de falha comuns (e mitigações)
Memória alucinada ou corrompida
O modelo pode “lembrar” coisas que nunca foram verdade, especialmente se ele for solicitado a resumir sem regras rígidas.
Mitigações:
- tratar resumos como derivados, não autoritativos; manter fontes brutas
- armazenar proveniência (IDs de mensagem/ferramenta)
- exigir citações para fatos recuperados
- validar campos do estado (esquemas, restrições)
Estado obsoleto e atualizações contraditórias
Se a recuperação trouxer fatos desatualizados (por exemplo, uma preferência antiga), o agente pode entrar em conflito com instruções recentes do usuário.
Mitigações:
- incluir timestamps e preferir recência
- permitir substituições explícitas (“a mensagem mais recente prevalece”)
- manter um registro canônico de “preferências atuais” separado do histórico
Recuperação excessiva (inundação de contexto)
Recuperar documentos demais aumenta custo e pode degradar desempenho.
Mitigações:
- filtragem agressiva + reranking (reclassificação)
- compressão de resultados de recuperação (extrair apenas trechos relevantes)
- limitar orçamentos de tokens por tipo de memória (episódica vs. semântica)
Vazamentos de segurança e privacidade
Memória de longo prazo pode armazenar acidentalmente segredos ou dados sensíveis.
Mitigações:
- tags de classificação de dados e verificações de controle de acesso no momento da recuperação
- pipelines de redação antes de indexar
- isolamento por tenant
- políticas explícitas de retenção e exclusão (“direito ao esquecimento”)
Injeção de prompt via memória
Se o texto recuperado contiver instruções adversariais, o modelo pode segui-las.
Mitigações:
- separar claramente “dados” de “instruções” no prompt
- usar saídas de ferramenta estruturadas quando possível
- aplicar allowlists de ferramentas no orquestrador (não no prompt)
- aplicar filtragem de conteúdo / pontuação de confiança para fontes de memória
Diretrizes práticas de design
- Torne o estado explícito e estruturado: use esquemas JSON; valide antes de salvar.
- Prefira logs append-only para observabilidade: você precisará depurar o comportamento do agente depois.
- Armazene evidência bruta; resuma por conveniência: resumos são com perda.
- Trate recuperação como um recurso de produto: ajuste ranking, filtragem e compressão; meça.
- Separe tipos de memória:
- preferências (semânticas) não devem ser misturadas com logs transitórios de execução (episódicos)
- Planeje retomada: projete IDs de etapa, chaves de idempotência e checkpoints.
- Não armazene segredos em memória visível ao modelo: mantenha credenciais em cofres seguros e passe apenas handles/tokens quando necessário.
- Use barreiras de política: o orquestrador deve impor permissões de ferramentas independentemente do que o modelo “decide”.
Avaliando o tratamento de memória e estado
A avaliação de agentes não é apenas sobre respostas finais. Para memória/estado, meça:
- Corretude do estado: o estado estruturado corresponde ao ground truth após cada etapa?
- Qualidade de recuperação de memória:
- Recall@k para itens sabidamente necessários
- acurácia de citação (a fonte citada sustenta a afirmação?)
- Taxa de sucesso em tarefas de longo horizonte: o agente consegue concluir tarefas que exigem restrições anteriores?
- Robustez de retomada: o agente consegue retomar após interrupção sem repetir ou divergir?
- Orçamentos de latência/custo: recuperação + tamanho do prompt + chamadas de ferramenta
Um método prático de teste é criar tarefas roteirizadas em que o sucesso exige:
- usar uma preferência declarada 30 turnos atrás,
- retomar após um reinício forçado,
- evitar uma chamada de ferramenta repetida via idempotência,
- resolver memórias conflitantes por recência/proveniência.
Como isso se encaixa em sistemas de agentes de LLM
“Memória e Estado” é a infraestrutura que torna o comportamento do agente coerente ao longo do tempo. Ela interage fortemente com:
- Uso de Ferramentas e Orquestração: retries, idempotência e logs de ferramentas fazem parte de memória/estado.
- Sistemas Multiagentes: memória compartilhada, coordenação e consistência tornam-se desafios centrais de design.
- Geração Aumentada por Recuperação: memória de longo prazo frequentemente usa a mesma pilha de recuperação, mas agentes adicionalmente precisam de controle com estado e persistência.
- Planejamento: planos são uma forma de estado, e a execução do plano depende de atualizações precisas e resultados intermediários armazenados.
Memória/estado bem projetados transformam uma LLM de um gerador de texto sem estado em um agente que consegue agir, lembrar, retomar e melhorar a confiabilidade ao longo de horizontes longos.