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:

  1. Estado da tarefa

    • objetivo, subobjetivos, restrições
    • critérios de “concluído”
    • marcadores de progresso (etapa atual, etapas restantes)
  2. Estado da conversa

    • intenção mais recente do usuário
    • perguntas não resolvidas
    • acordos firmados (“Entregaremos até sexta-feira”)
  3. 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
  4. Estado de conhecimento

    • fatos considerados verdadeiros, com confiança/proveniência
    • hipóteses em aberto que precisam de verificação
  5. 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
  • 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:

  1. filtrar por permissões e escopo,
  2. combinar similaridade vetorial + correspondência por palavra-chave,
  3. reclassificar (re-rank) com um codificador cruzado (cross-encoder) ou um ranqueador baseado em LLM,
  4. 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

  1. Carregar o estado estruturado atual (checkpoint).
  2. Recuperar memórias relevantes de longo prazo (filtrada + híbrida).
  3. 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.
  4. A LLM propõe uma ação (chamada de ferramenta ou pergunta ao usuário) e uma atualização de estado.
  5. Executar a chamada de ferramenta (se houver).
  6. Registrar evento(s), atualizar estado e possivelmente atualizar o índice de memória.
  7. 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.