[!NOTE] Tradução automática Este artigo foi traduzido automaticamente a partir da versão original em inglês.

Memória de Agente de IA: Estado Tipado Orientado por Esquema para Sistemas em Execução Contínua

Agentes que operam por períodos prolongados costumam recuperar informações desatualizadas, pois a memória semântica convencional não dispõe de regras para determinar qual valor é o atual.

Quando um utilizador altera a data limite de um passaporte de 15 de julho para 30 de junho, a busca vetorial pode recuperar ambas as afirmações. Uma camada de memória com estado deve registar que o valor de 30 de junho substitui o anterior.

TL;DR: Trate a memória duradoura do agente como um estado da aplicação tipado. Extraia os candidatos à memória através de uma fronteira de saída estruturada, armazene os registos com escopo de utilizador, janelas de validade, regras de substituição, proveniência e versionamento de esquemas, e recupere apenas a parte mais recente no caminho de leitura. Reserva a busca vetorial para recuperação aproximada. Leia os factos mutáveis a partir de registos atuais e delimitados.


A armadilha da janela de contexto

A janela de contexto representa os dados de entrada disponíveis para uma única chamada do modelo. Uma aplicação pode transmitir mensagens para chamadas posteriores, mas a política da aplicação deve decidir quais factos antigos continuam válidos e quem pode acedê-los.

Agentes em execução contínua precisam de memorizar preferências, status de tarefas, dados de clientes, decisões relativas a ferramentas, notas de conformidade e erros anteriores. A abordagem mais simples consiste em adicionar resumos ou guardar notas antigas num repositório vetorial. Isso funciona até que um dos factos memorizados seja alterado.

Nesse caso, o agente passa a ter dois prazos de passaporte, dois formatos preferidos ou duas decisões de projeto. A busca semântica pode recuperar ambos. Um resumo pode sobrescrever um deles. Um contexto extenso pode incluir o facto desatualizado ao lado do atual. Esses designs permitem a recuperação de texto, mas sem garantir a aplicação do valor atual.

O contrato deve responder a questões concretas:

A Memória de Agente Orientada por Esquema (SGAM) armazena essas respostas como campos e relações, em vez de as deixar implícitas no texto.


O que significa SGAM

Três conceitos com nomes semelhantes definem o âmbito da SGAM.

Diálogo Orientado por Esquema (SGD) refere-se ao conjunto de dados de diálogo orientado a tarefas da Google de 2019. O seu esquema descreve APIs de serviço, intenções e slots, permitindo que um modelo de diálogo acompanhe o estado de serviços que ainda não viu. É um precedente útil para o rastreio baseado em esquemas, embora com escopo limitado a serviços de diálogo.

Memória Orientada por Esquema (SGM) é o termo de investigação utilizado por Mei et al. em According to Me: Long-Term Personalized Referential Memory QA. O artigo compara a Memória Descritiva (DM) em formato de texto livre com itens de memória em formato chave-valor com esquema fixo. Ambas as representações contêm as mesmas informações de origem, mas em estruturas diferentes.

Neste artigo, uso Memória de Agente Orientada por Esquema (SGAM) para designar um padrão de engenharia no qual os esquemas regulam as operações de escrita, atualização, recuperação e eliminação. O esquema define o estado da aplicação e o seu ciclo de vida.

O ATM-Bench demonstra por que a representação é importante. Ele utiliza cerca de quatro anos de dados pessoais provenientes de e-mails, imagens e vídeos. As perguntas exigem referências pessoais, localização, múltiplas provas e atualizações ao longo do tempo. O desempenho diminui quando se utiliza a separação tradicional, enquanto a SGM melhora em relação à DM, pois o mecanismo de recuperação consegue aceder diretamente a campos como hora, fonte, localização, entidades e etiquetas.

SGM versus DM aborda uma questão de armazenamento: a memória deve permanecer em formato de texto livre ou utilizar campos nomeados? Um agente em produção enfrenta outro desafio antes do armazenamento: precisa raciocinar a partir de uma conversa não estruturada para determinar uma atualização adequada na memória. O Schema-Guided Reasoning (SGR) define esse processo: inspecionar as evidências, identificar o sujeito e os atributos, verificar se o fato altera o estado existente e, em seguida, gerar uma proposta de escrita. O SGAM aplica as regras de armazenamento e de ciclo de vida após essa chamada ao modelo.


Separação entre extração do modelo e propriedade da memória

A escrita na memória atravessa três camadas. O Structured Output (SO) garante a estrutura correta do objeto proposto. O Schema-Guided Reasoning (SGR) codifica os passos e a ordem que o modelo deve seguir para chegar a essa proposta. Já o Schema-Guided Agent Memory (SGAM) gere esse objeto como um estado duradouro após a chamada ao modelo.

Uma decisão, rota ou plano geralmente expira com a solicitação atual. Uma nova execução pode ler essa proposta de memória dias depois ou utilizá‑la para escolher uma chamada de ferramenta. Esse período mais longo exige regras de armazenamento que o SGR não oferece.

O SGR restringe uma única chamada ao modelo ao definir sua topologia de raciocínio. Para uma escrita na memória, o esquema pode exigir evidências de origem, um sujeito e atributos normalizados, uma comparação com o estado atual e, somente então, a atualização proposta. Ferramentas como Pydantic ou JSON Schema descrevem esse fluxo. O Structured Output nativo do fornecedor ou um ambiente de decodificação guiado, como o XGrammar, impede que o modelo pule campos ou retorne uma estrutura diferente.

O esquema não consegue garantir uma conclusão correta. Ele torna explícito e inspecionável o caminho de decisão necessário, incluindo as evidências e a comparação que geraram a proposta.

O SGAM decide o que acontece após o objeto ser criado. Deve ser armazenado? Substitui um fato anterior? Qual usuário pode acessá‑lo? É atual ou histórico? Qual episódio de fonte o sustenta?

A tabela abaixo indica a propriedade responsável e o modo de falha de cada camada:

DimensãoSOSGRSGAM
FinalidadeDevolver um objeto que esteja em conformidade com um esquemaOrientar o modelo ao longo de um caminho de raciocínio predefinidoGerir a memória persistente após a chamada ao modelo
ÂmbitoUma resposta geradaUm caminho de raciocínio e decisão numa única chamada ao modeloRegistos utilizados entre chamadas, sessões e execuções
Papel no esquemaDefine os campos de saída, tipos e valores permitidosDefine as fases intermédias de raciocínio e a decisão finalDefine os registos armazenados, relações e seu ciclo de vida
Aplicação da regraBloqueia a decodificação de outputs inválidos segundo o esquemaUtiliza o SO para exigir a execução de cada fase declarada e da decisão finalValidação da aplicação, restrições de base de dados e regras de conflito
DuraçãoA chamada atual, a menos que a aplicação armazene o objetoO rasto de raciocínio é normalmente descartado após a decisãoPermanece até ser atualizado, expirar ou ser eliminado
Modo de falhaFormato válido, mas com significado incorretoOs passos necessários estão presentes, mas o raciocínio ainda pode estar erradoEstado obsoleto, poluído, sem âmbito definido ou impossível de auditar

No caminho de escrita, a sequência é:

SGR reasoning schema + Structured Output -> candidate write -> SGAM policy and persistence

O seguinte excerto ilustrativo de memory_models.py define o objeto transmitido da extração para o serviço de escrita do SGAM:

from datetime import datetime
from pydantic import BaseModel, Field


class MemoryDelta(BaseModel):
    tenant_id: str = Field(description="Isolation boundary, e.g. acme")
    subject: str = Field(description="Normalized entity ID, e.g. mira")
    attribute: str = Field(description="Property being updated")
    value: str = Field(description="New value")
    valid_from: datetime
    source_episode_id: str

MemoryDelta mostra o que foi extraído pelo modelo. O serviço de escrita do SGAM decide ainda se o deve rejeitar, fundir ou armazenar.


Os caminhos de escrita e leitura têm funções distintas

O SGAM dispõe de um caminho de escrita e um de leitura. Apenas o caminho de escrita modifica o estado armazenado. O caminho de leitura seleciona os registos necessários para a solicitação atual.

O fluxo de ingestão corresponde ao caminho de escrita:

  1. Capturar um episódio bruto a partir de mensagens, resultados de ferramentas ou eventos empresariais.
  2. Extrair candidatos estruturados através da saída formatada.
  3. Validar o esquema e rejeitar registos mal formatados.
  4. Resolver conflitos, encerrar factos obsoletos e manter a proveniência.
  5. Cometer o registo no armazenamento do SGAM.

O fluxo de solicitação corresponde ao caminho de leitura:

  1. Partir da pergunta do utilizador.
  2. Decidir se a pergunta requer o estado atual ou um estado em determinado momento.
  3. Filtrar por inquilino, tipo de memória, assunto, atributo e janela de validade.
  4. Adicionar expansão vetorial ou gráfica apenas se a consulta direta ao estado não for suficiente.
  5. Compilar o contexto mais reduzido necessário para o modelo.

Arquitetura de memória de agente guiada por esquema

Leia esse diagrama da esquerda para a direita, em duas faixas. A faixa superior escreve na memória, enquanto a inferior a lê. Ambas utilizam o mesmo armazenamento.


O que deve constar num esquema de memória

Um registo SGAM mínimo requer mais do que text.

tenant_id
memory_id
subject
attribute
value
memory_type
schema_version
valid_from
valid_to
supersedes_memory_id
source_episode_id
confidence
retention_policy

Com estes campos, um novo prazo de passaporte pode substituir o prazo anterior sem apagar o histórico. A mesma tabela permite responder a consultas atuais e em determinado momento, podendo depois rastrear o resultado até ao episódio de origem. schema_version suporta migrações, enquanto retention_policy indica aos job de eliminação quais outros elementos devem ser removidos.

Deve‑se utilizar RAG para recuperar documentos e SGAM para gerir o estado mutável. A busca vetorial continua a ser essencial no sistema para recuperação fuzzy, agrupamento e expansão de resultados. O valor atual de mira.passport_deadline deve provir de um registo de memória delimitado, e não do primeiro bloco que aparecer classificado.


Exemplo de facto obsoleto

Considere um rasto sintético composto por dois episódios, representado por uma linha de base DM e um livro‑razão SGAM:

e1: Mira prefers concise answers. Her passport deadline is 2026-07-15.
e2: Mira corrected the deadline. It is now 2026-06-30.

Uma linha de base DM armazena ambos os episódios como texto livre, pelo que a busca por texto pode retornar e1, uma vez que contém as palavras corretas. O SGAM extrai um facto tipado de cada episódio, indexado por inquilino, assunto e atributo. Deve retornar e2 como estado atual e manter e1 para consultas históricas.

A função seguinte corresponde ao código do caminho de escrita do SGAM. Ela ficaria num módulo de armazenamento como sgam_store.py. O DM não possui um equivalente, pois não mantém uma linha atual por atributo. Antes de o chamador inserir uma substituição, esta função fecha a linha atual:

def close_previous_fact(db: sqlite3.Connection, fact: MemoryFact) -> int | None:
    row = db.execute(
        """
        select fact_id
        from memory_facts
        where tenant_id = ?
          and subject = ?
          and attribute = ?
          and valid_to is null
        order by valid_from desc
        limit 1
        """,
        (fact.tenant_id, fact.subject, fact.attribute),
    ).fetchone()
    if not row:
        return None

    db.execute(
        "update memory_facts set valid_to = ? where fact_id = ?",
        (fact.valid_from, row["fact_id"]),
    )
    return int(row["fact_id"])

Quando e2 chega, a função define valid_to no facto extraído de e1 para o timestamp de e2. Em seguida, o chamador insere o novo facto com um valid_to ainda aberto. Como o DM não tem um passo de atualização correspondente, o texto antigo pode continuar a ter prioridade sobre a correção.

A execução de consultas atuais e históricas sobre prazos com ambas as representações produz resultados diferentes:

Naive text memory:
  returned episode: e1 -> passport deadline is 2026-07-15

SGAM current state:
  mira.passport_deadline = 2026-06-30
  valid_from=2026-06-03T10:00:00Z, source=e2

SGAM point-in-time state:
  on 2026-06-02, mira.passport_deadline = 2026-07-15

Em produção, deve‑se associar esta transação à extração estruturada no caminho de escrita. A transação de base de dados atualiza a validade temporal. O modelo extrai um facto candidato, mas não decide qual linha armazenada permanece atual.


As escolhas de armazenamento seguem o padrão de recuperação

Os projetos utilizam vários nomes para partes deste padrão: armazenamentos de memória, grafos de contexto, perfis, armazenamentos de longo prazo, RAG de grafos e agentes com estado.

Ferramenta ou frameworkCamada principal de armazenamentoMecanismo de estado temporalMecanismo de esquemaNicho prático
Zep / GraphitiNeo4j, FalkorDB, Neptune, suporte a Kuzu legadoIntervalos de validade dos factos e proveniência das fontesTipos de entidade e aresta em Pydantic, arestas temporais, proveniênciaMemória de grafos temporais
LangGraph / LangMemArmazenamentos LangGraph, armazenamentos baseados em PostgresTimestamps e campos pertencentes à aplicação nos registos do armazenamentoArmazenamentos em JSON mais extração de perfis ou coleções em PydanticAplicações de agente já desenvolvidas com LangGraph
Mem0Stack gerida, backends Valkey / Redis / vector em ambientes OSSAtualizações de memória; a política temporal permanece sob responsabilidade da aplicaçãoTipos de memória, categorias personalizadas, prompts de extraçãoMemória de utilizador, agente e sessão como serviço
Letta / MemGPTEstado do agente e blocos de memória baseados em base de dadosBlocos editáveis sem intervalos de validade a nível de campoBlocos de memória rotulados e editáveisAgentes com estado e gestão de contexto ao estilo do SO
CogneeBackends de grafos, vector e relacionaisO histórico depende da ontologia e do backend selecionadoExtração e validação orientadas para a ontologiaMemória de grafos de conhecimento empresarial
LlamaIndex property graphArmazenamentos de grafos de propriedades mais armazenamentos vectoriaisCampos de tempo dependem do esquema do grafos e do armazenamentoSchemaLLMPathExtractor com entidades e relações permitidasExtração de grafos a partir de documentos e rastreios

Graphiti é uma implementação concreta em código aberto de memória relacional e temporal. Ele regista as alterações nos factos, mantém ponteiros para as episódios de origem e suporta recuperação híbrida. LangGraph separa os pontos de verificação por thread dos armazenamentos entre threads. Mem0 apresenta as operações de memória como um serviço gerido. Letta utiliza blocos de contexto editáveis em vez de SGAM a nível de campo, mas continua a tratar o estado do agente como dados persistentes.

Comece pelo modelo de dados. Se a consulta exata de factos for a operação principal, geralmente basta uma tabela relacional com payloads em JSON, colunas de validade, índices por utilizador e um sidecar vectorial. Adicione um grafos apenas quando a navegação por relações fizer parte do produto, e não porque a demonstração com grafos pareça impressionante.

Construir o caminho de escrita antes do grafo

Primeiro, defina o que o produto pode memorizar. A escolha entre grafo e vetor será feita posteriormente.

Um agente de suporte pode guardar o nível da conta, casos abertos e preferências de contacto duradouras. Não deve transformar cada reclamação do utilizador em um estado no perfil. Um agente de programação pode memorizar convenções do repositório e tarefas não resolvidas. Não deve conservar uma nota privada indefinidamente só porque essa nota foi consultada uma vez.

Comece com o caminho de escrita e trate a memória como uma pequena mutação de estado:

  1. Defina o tipo de memória, o assunto, o escopo do utilizador e a classe de retenção.
  2. Extraia os registos candidatos com saída estruturada.
  3. Valide a carga com Pydantic ou com a camada de esquema já utilizada pela sua arquitetura.
  4. Resolva conflitos antes da inserção, incluindo se o novo registo substitui um antigo.
  5. Mantenha um ponteiro de origem para o episódio bruto, resultado da ferramenta, ficheiro, ticket ou confirmação do utilizador que gerou o registo.
  6. Registe a versão do esquema junto de cada registo, em vez de a deixar apenas no código da aplicação.

O primeiro armazenamento SGAM pode ser uma tabela relacional com uma coluna JSON e alguns índices. O grafo torna-se útil quando o produto precisa percorrer relações como cliente-conta, conta-política, tarefa-artefato ou projeto-Decisão.

Caminho imediato e escritas em segundo plano

A extração imediata vale a pena quando a próxima interação depende da nova memória. Se o utilizador disser “lembre-se de que prefiro respostas curtas”, o sistema não precisa de uma tarefa noturna para começar a agir de forma diferente.

A maioria das interações não requer escrita imediata. Guarde o episódio bruto com metadados do utilizador, sessão e ferramenta, e deixe que um processo em segundo plano extraia os registos candidatos mais tarde. Com consolidação baseada em recorrência, o processo armazena temporariamente sinais fracos e promove um facto apenas após evidências semelhantes se repetirem ou o utilizador o confirmar. Isso gera um atraso na atualização dos dados. Isso é aceitável para casos como “o utilizador pede frequentemente exportações em CSV”, mas arriscado em situações como “o cliente alterou o endereço de entrega”.

Mantenha o caminho de leitura determinístico. Imponha primeiro o escopo do utilizador e a validade, e utilize a recuperação por similaridade apenas quando isso puder adicionar contexto útil.

  1. Filtre por utilizador, tipo de memória e janela de validade.
  2. Recupere primeiro o estado estruturado exato, e depois os vizinhos semânticos.
  3. Utilize expansão por vetores ou grafo para obter evidências complementares, entidades relacionadas e exemplos, e não como fonte autorizada dos factos atuais.
  4. Monte o menor conjunto de contexto possível que permita responder à pergunta.

Trate a migração de esquemas como uma alteração no produto, pois ela modifica o que o agente pode recordar, citar ou eliminar. Também pode alterar quais factos históricos são considerados atuais. Planeie scripts de migração, processos de preenchimento retroativo, períodos de leitura dupla e comportamentos de eliminação na mesma versão do produto.


Quando o SGAM justifica a complexidade

Utilize o SGAM quando os factos podem mudar ao longo do tempo:

O SGAM é um exagero quando a memória tem vida curta, é utilizada de forma exploratória ou quando seu recálculo é barato. Se o agente precisar apenas de algumas iterações de continuidade, um ponto de verificação e um histórico de mensagens reduzido são suficientes. Na verificação de qualidade de documentos estáticos, pode ser necessário apenas o RAG. E se o domínio for tão instável que o esquema muda todos os dias, a utilização de memória tipada irá atrasar a equipa.


Lista de verificação de avaliação

Avalie tanto o ciclo de vida da memória como a resposta final. Um sistema pode gerar uma resposta plausível mesmo após ter registado um facto incorreto, recuperado um dado desatualizado ou ultrapassado os limites definidos para um determinado utilizador.

Utilizo a mesma divisão fase a fase descrita no meu artigo de avaliação do RAG. Medimos a fase em que uma falha pode ocorrer, em vez de limitarmos a avaliação apenas ao texto gerado. A abordagem de rastreio do artigo de avaliação de agentes também é aplicável, pois um erro na memória costuma aparecer no histórico de execução antes de chegar à resposta.

Testaria o SGAM com reprodução de cenários. Inseriria uma sequência fixa de episódios no mecanismo de escrita da memória, inspecionaria o registo após cada iteração significativa e, em seguida, faria perguntas sobre o estado atual e sobre momentos específicos, utilizando o armazenamento resultante.

CamadaFalha a ser detetadaMétricas utilizadas
Extração de escritaO agente omitiu um facto, inventou um ou gerou uma estrutura inválidaTaxa de escritas válidas segundo o esquema, precisão/recall da extração, cobertura dos episódios de origem
Gestão de conflitosUm facto desatualizado permaneceu ativo ou um facto antigo válido foi substituídoCorreção da substituição, taxa de duplicatas, correção da invalidação de factos desatualizados
Isolamento e políticasA memória vazou entre utilizadores ou permaneceu ativa além do prazo definido pela políticaFalhas de isolamento por utilizador, correção das exclusões, conformidade com regras de retenção
Recuperação de leituraO registo correto existe, mas o leitor não o recuperouPrecisão do estado atual, precisão em momentos específicos, recall@k entre os registos da memória
Anclagem da respostaA resposta utilizou a memória sem suporte adequado ou citou a fonte erradaVerificação da existência de suporte nos episódios de origem, precisão das citações, correção na resolução de conflitos
OperaçõesO caminho de acesso à memória é demasiado lento, desatualizado ou dispendiosoLatência de escrita p95, atraso na atualização, latência de leitura, custo por consulta

Benchmarks como LoCoMo, LongMemEval e ATM-Bench disponibilizam casos de teste públicos. No entanto, eles não substituem um conjunto de testes específico para o domínio em questão. Um assistente de programação, um bot de suporte ao cliente e um copiloto de conformidade exigem esquemas, filtros, regras de retenção e testes de falha diferentes.

Considerações importantes

SGAM é o meu rótulo para um determinado padrão, e não um padrão técnico estabelecido. Projetos existentes abordam o problema de forma diferente. LangGraph memory e LangMem descrevem mecanismos de armazenamento de curto e longo prazo, perfis, coleções, operações em caminhos críticos e gestores de memória em segundo plano. Zep Graphiti utiliza o termo “Grapho de Contexto Temporal”. Letta permite a persistência de blocos de memória editáveis, enquanto Mem0 oferece uma camada de memória gerida. Microsoft GraphRAG, os Graphs de propriedades do LlamaIndex e o Cognee tratam partes do problema como Graphos de conhecimento.

Um perfil de utilizador, um registo de episódios, um Graph de documentos e um bloco de memória editável por um agente resolvem problemas distintos de recuperação e atualização de dados. Reservo SGAM para a memória duradoura que representa o estado atual da aplicação, exigindo, portanto, esquema estruturado, validade, rastreabilidade da origem dos dados, gestão de conflitos, políticas de retenção e migração.

A memória tipada ainda pode conter erros. Um esquema facilita a inspeção de escritas incorretas, mas não garante a sua fiabilidade. Continua a ser necessário confiar nas fontes, obter confirmação do utilizador para factos sensíveis, definir políticas de gestão de conflitos, realizar exclusões e monitorizar a memória.

A migração de esquemas é um processo trabalhoso. Uma vez que a memória se torne parte do estado da aplicação, torna-se responsabilidade do desenvolvedor gerir a versãoização, os dados antigos, as regras de exclusão e o comportamento associado. Se esse processo for ignorado, os registos antigos permanecerão ativos mesmo após a mudança das políticas semânticas ou de retenção.


Referências