Blog

Memória de longo prazo para agentes de atendimento

O cliente já contou tudo três vezes. Na primeira sessão explicou que tem um plano empresarial e prefere ser chamado pelo primeiro nome; na segunda, teve que repetir; na terceira, desistiu e ligou. O problema não é o modelo, é que o agente não tem memória: cada conversa começa do zero, porque a janela de contexto é volátil e morre no fim da sessão. Memória de longo prazo é a camada que faz o agente lembrar do cliente entre sessões, mas ela não é simplesmente "guardar todo o histórico e mandar tudo de novo". Isso estoura a janela, custa uma fortuna em token e ainda enterra o fato relevante debaixo de mil mensagens irrelevantes. Memória bem feita é seletiva: grava só o que é durável, recupera só o que importa para o turno atual e injeta um resumo enxuto, não o transcript inteiro. Este artigo mostra como construir essa camada com a régua no lugar: a diferença entre janela de contexto e memória persistente, o que vale a pena lembrar e o que é ruído, como recuperar por relevância em vez de por recência e como manter a memória atualizada para não responder com um fato que já mudou.

2026-07-11 / IA Aplicada / 13 min

01

Janela de contexto não é memória

A confusão mais comum é tratar a janela de contexto do modelo como se fosse memória. A janela é o que o modelo enxerga naquela chamada: o prompt, o histórico recente da conversa, as instruções. Ela é volátil (some quando a sessão acaba), limitada (tem um teto de tokens) e cara (cada token na janela é cobrado em toda chamada). Memória de longo prazo é o oposto em cada eixo: é persistente (sobrevive entre sessões), potencialmente ilimitada (mora num banco, não no prompt) e barata para guardar. O erro de arquitetura é tentar usar uma no lugar da outra: ou você empilha histórico na janela até estourar, ou finge que o modelo lembra de algo que nunca foi persistido.

A memória de longo prazo não substitui a janela, ela a alimenta. O fluxo é: a memória mora fora do modelo, e a cada turno você recupera dela um punhado de fatos relevantes e os injeta na janela como contexto. A tabela abaixo separa os dois papéis para deixar claro por que nenhum sozinho resolve.

DimensãoJanela de contextoMemória de longo prazo
DuraçãoVolátil, morre na sessãoPersistente, sobrevive entre sessões
TamanhoLimitada por teto de tokensIlimitada (mora em banco)
CustoCara: cobrada por chamadaBarata para guardar, custa só o que recupera
PapelO que o modelo vê agoraDe onde vem o que ele precisa ver

A regra que organiza tudo: a memória é a fonte, a janela é a vitrine. Você guarda muito e mostra pouco. Todo o resto do artigo é sobre como escolher o pouco certo a mostrar, porque despejar a memória inteira na janela é tão ruim quanto não ter memória nenhuma: um agente afogado em contexto irrelevante responde pior do que um agente enxuto e focado.

02

O que lembrar e o que é ruído

Nem toda mensagem merece virar memória. O instinto de gravar o transcript inteiro é o caminho mais curto para uma memória inútil: cheia, cara de recuperar e dominada por conversa fiada. A pergunta certa não é "o que o usuário disse?", é "o que sobre este usuário continua verdade na próxima sessão?". Um fato durável (o plano que ele contratou, a preferência de idioma, uma restrição que ele mencionou) vale ouro porque muda como você atende dali em diante. Uma troca de mensagens sobre um problema já resolvido é ruído: não precisa ser lembrada literalmente, no máximo como um resumo de uma linha.

  • Grave fatos, não frases: "usa o plano empresarial", "prefere português", "tem restrição a e-mail de marketing" são fatos duráveis; a mensagem literal que revelou isso é descartável.
  • Separe o estável do efêmero: preferências, perfil e decisões passadas são estáveis; o humor da conversa de hoje e o assunto pontual já resolvido são efêmeros e não devem persistir.
  • Não persista o que já é dado vivo: status de pedido, saldo e cotação não são memória, são consulta ao sistema de origem na hora; lembrar disso serve dado obsoleto.
  • Resuma, não acumule: em vez de guardar as 40 mensagens de uma sessão, guarde o resumo do que ficou decidido; a memória cresce em conhecimento, não em volume.

A separação prática é entre memória de perfil (fatos duráveis sobre quem é o usuário e o que ele prefere) e memória de episódio (o que aconteceu numa sessão específica, guardado como resumo). A primeira é consultada quase sempre; a segunda, só quando o assunto reaparece. O que nunca deve virar memória é dado vivo: se a resposta depende do estado atual do sistema, ela vem de uma consulta, não da lembrança, senão o agente responde com um saldo de três semanas atrás com a confiança de quem acabou de checar.

03

A anatomia de um fato de memória

Um fato de memória não é só um texto solto. Para ser recuperável, atualizável e confiável, ele precisa de estrutura: a quem pertence, de que tipo é, o conteúdo em si, quando foi gravado e até quando vale. Sem escopo por usuário, você vaza a memória de um cliente para outro. Sem tipo, não dá para recuperar por categoria nem para atualizar o fato certo. Sem validade, um fato que mudou fica servindo eternamente. O formato abaixo é o mínimo que sustenta uma memória de produção.

// memory/record.js
// Um fato de memoria precisa de estrutura para ser recuperado e atualizado.
// Texto solto nao da para escopar por usuario nem para expirar.

export function makeMemory({ userId, kind, content, embedding, ttlDays }) {
  const now = Date.now();
  return {
    userId,                 // escopo: memoria e SEMPRE por usuario, nunca global
    kind,                   // 'perfil' | 'preferencia' | 'episodio' | 'decisao'
    content,                // o fato em uma frase, nao a mensagem literal
    embedding,              // vetor do content, para recuperar por relevancia
    createdAt: now,
    // Fato durável (preferencia) pode nao ter validade; episodio expira.
    expiresAt: ttlDays ? now + ttlDays * 86400000 : null,
  };
}

// Regra de ouro: content e um FATO ("usa plano empresarial"),
// nao um TRECHO de conversa ("entao eu queria saber se o meu plano...").

Repare em três escolhas que salvam o sistema mais tarde. O userId torna a memória sempre escopada: nenhuma busca cruza a fronteira do usuário, o que fecha a porta mais óbvia de vazamento de dado pessoal. O kind permite recuperar por categoria (só as preferências, por exemplo) e atualizar o fato certo em vez de duplicar. E o expiresAt distingue o durável do efêmero: uma preferência não expira, mas o resumo de um episódio pode ter validade, para a memória não inchar com sessões antigas que ninguém vai reabrir. Guardar o content como fato, e não como trecho de conversa, é o que faz a recuperação funcionar: um fato curto e denso casa melhor com a pergunta do que um parágrafo de bate-papo.

04

Recuperar por relevância, não por recência

Com a memória cheia, a pergunta vira: o que dela injetar na janela deste turno? A resposta ingênua é "as últimas N lembranças", mas recência é o critério errado. O fato mais útil para a pergunta de agora pode ter sido gravado há meses (o plano que o cliente contratou), enquanto as lembranças recentes podem ser sobre um assunto que não tem nada a ver. O critério certo é relevância: transforme o turno atual em embedding, busque na memória do usuário os fatos mais próximos e injete só esses. É o mesmo mecanismo de um RAG, mas aplicado à memória de um único usuário em vez de a uma base de documentos.

Recuperacao de memoria por turno

  mensagem do usuario (turno atual)
        |
        v
  gera embedding do turno
        |
        v
  busca na memoria DESTE usuario (userId fixo)
     os fatos mais relevantes (top-k)
        |
        v
  monta um resumo enxuto (nao o transcript)
        |
        v
  injeta o resumo no prompt + historico recente
        |
        v
  modelo responde JA sabendo quem e o cliente

  regra: escopo por usuario + top-k por relevancia + resumo curto
  errado: despejar toda a memoria OU so as lembrancas recentes
// memory/recall.js
// Recupera da memoria SO o que e relevante para o turno atual.
// Escopo por usuario e top-k por similaridade, nunca "tudo" nem "os ultimos".

export async function recall({ embed, store, userId, turn, k = 5 }) {
  const query = await embed(turn);

  // Busca restrita ao usuario: memoria NUNCA cruza a fronteira do userId.
  const hits = await store.nearest({ userId, query, k });

  // Injeta um resumo enxuto, nao o conteudo bruto de cada fato.
  // Menos token na janela, foco no que importa para a pergunta.
  const summary = hits
    .filter((h) => !isExpired(h))
    .map((h) => `- ${h.content}`)
    .join('\n');

  return summary; // vai para o prompt como contexto do usuario
}

Dois detalhes fazem a diferença entre uma recuperação que ajuda e uma que atrapalha. O primeiro é o top-k pequeno: recuperar cinco fatos densos e certeiros é melhor do que despejar cinquenta, porque contexto irrelevante dilui a atenção do modelo tanto quanto a falta de contexto. O segundo é o resumo: você injeta o fato ("usa o plano empresarial"), não o parágrafo de onde ele saiu. Menos token, mais sinal. E a busca é sempre presa ao userId, porque memória que vaza entre usuários é o pior erro possível: servir a preferência ou o histórico de um cliente para outro é um incidente de privacidade, não um bug de qualidade.

05

Atualizar e esquecer: memória que não mente

Memória que só cresce vira mentira com o tempo. O cliente que "usava o plano básico" migrou para o empresarial; o que "preferia ser contatado por e-mail" agora pediu WhatsApp; a restrição que ele tinha deixou de valer. Se a memória guarda o fato antigo lado a lado com o novo, a recuperação pode trazer o errado, e o agente atende com uma verdade vencida. Por isso memória de longo prazo precisa de duas operações que quase sempre ficam de fora: atualizar (substituir um fato quando ele muda) e esquecer (remover o que expirou ou o que o usuário pediu para apagar).

  1. Atualize por fato, não por acúmulo: quando o usuário muda de plano, substitua o fato de plano; não guarde os dois e torça para o mais novo ganhar na recuperação.
  2. Dê validade ao que é temporário: episódios e resumos de sessão devem expirar; preferências duráveis vivem até serem contraditas, não para sempre por padrão.
  3. Respeite o pedido de esquecimento: um usuário pode pedir para apagar dados; a memória tem que ter delete por usuário, não só por conveniência mas por obrigação de privacidade.
  4. Detecte contradição na escrita: ao gravar um fato do mesmo kind, cheque se já existe um que ele contradiz e resolva na hora, em vez de deixar dois fatos rivais na base.

O erro clássico é montar a escrita e a recuperação, comemorar que o agente "lembra", e nunca implementar a atualização. O sistema começa impressionante e apodrece devagar: quanto mais o usuário interage, mais fatos vencidos se acumulam, e mais a recuperação erra ao trazer uma verdade antiga. Atualizar e esquecer são o que mantém a memória alinhada com a realidade do cliente. E o esquecimento não é só higiene técnica: é requisito de privacidade. Um usuário tem o direito de pedir que você apague o que sabe sobre ele, e a memória precisa ser construída assumindo esse pedido desde o primeiro dia.

06

Onde a memória mora e como ela escala

A escolha de armazenamento decide o custo e a latência da memória em produção. Como a recuperação é por similaridade, o coração é uma busca vetorial: os embeddings dos fatos precisam morar onde dá para achar os mais próximos rápido. Mas os fatos também têm metadados (userId, kind, validade) que você filtra antes ou durante a busca, então armazenamento puro de vetor sem filtro por usuário não basta. A combinação prática é um índice vetorial com filtro por userId, mais um armazenamento durável dos fatos com seus metadados.

AspectoDecisãoPor quê
Índice de buscaVetorial com filtro por userIdRecuperação é por relevância, sempre escopada ao usuário
Escopo da buscaSempre um userId por vezMemória nunca pode cruzar a fronteira entre clientes
CrescimentoTTL nos episódios, resumo dos perfisMemória cresce em conhecimento, não em volume bruto
LatênciaTop-k pequeno, resumo curtoRecuperar pouco e denso mantém a chamada rápida e barata

O que mantém a memória barata e rápida em escala não é a tecnologia de banco, é a disciplina de gravar pouco e denso. Uma memória que guarda fatos resumidos, expira episódios e mantém só o perfil durável fica pequena e rápida mesmo com milhões de usuários, porque cada busca toca só a memória de um usuário e traz só um punhado de fatos. Uma memória que guarda transcript bruto de tudo cresce sem limite, encarece cada busca e ainda entrega contexto pior. A escala não é problema de infraestrutura, é consequência da política de escrita.

07

Montar a camada sem virar risco novo

Memória de longo prazo transforma a experiência de atendimento: o agente deixa de tratar cada sessão como a primeira e passa a atender alguém que ele conhece. Mas ela introduz duas classes de risco que não existiam no agente sem memória: vazamento de dado entre usuários e resposta baseada em fato vencido. A ordem de implantação importa tanto quanto o código, e o caminho é construir a segurança antes da esperteza.

  1. Comece pelo escopo por usuário: antes de qualquer recuperação, garanta que toda busca é presa ao userId. Vazar memória entre clientes é incidente de privacidade, não bug de qualidade.
  2. Grave fato, não transcript: implemente a extração de fatos duráveis desde o início; memória cheia de conversa bruta é cara, lenta e ruim de recuperar.
  3. Recupere por relevância com top-k pequeno: injete poucos fatos densos, não a memória inteira nem só as lembranças recentes; contexto irrelevante piora a resposta.
  4. Adicione atualizar e esquecer antes de escalar: sem substituição de fato e sem delete por usuário, a memória apodrece e vira passivo de privacidade.
  5. Instrumente o que a memória injeta: logue quais fatos entraram no prompt (com redação de dado pessoal) para auditar quando o agente responder com base numa lembrança errada.

A diferença entre uma memória que encanta o cliente e uma que vira incidente está inteira no escopo e na política de escrita, não no modelo de embedding. O embedding é commodity; o escopo por usuário, a extração de fatos, a recuperação por relevância e as operações de atualizar e esquecer são o que transforma "guardar histórico" numa camada de produção confiável. Bem feita, a memória de longo prazo é uma das mudanças de maior impacto percebido num agente de atendimento: o cliente sente que está falando com alguém que se lembra dele, sem que o sistema pague isso em token, latência ou risco de privacidade.

FAQ

Perguntas frequentes

Memória de longo prazo não é só mandar o histórico inteiro da conversa no prompt?

Não, e essa é a armadilha mais comum. Empilhar o histórico inteiro na janela de contexto estoura o teto de tokens, custa caro em toda chamada e ainda enterra o fato relevante debaixo de mensagens irrelevantes. Memória de longo prazo é o oposto: os fatos moram fora do modelo, num armazenamento persistente, e a cada turno você recupera só os poucos que importam para a pergunta atual e injeta um resumo enxuto. Você guarda muito e mostra pouco. A janela é a vitrine, a memória é a fonte; despejar a memória inteira na janela é tão ruim quanto não ter memória nenhuma.

Qual o maior risco da memória de longo prazo e como controlar?

São dois. O primeiro é o vazamento entre usuários: se a busca não for escopada por userId, o agente pode servir a preferência ou o histórico de um cliente para outro, o que é um incidente de privacidade, não um bug de qualidade. Controla-se prendendo toda recuperação ao userId, sem exceção. O segundo é a resposta com fato vencido: se a memória só cresce e nunca atualiza, ela guarda o plano antigo lado a lado com o novo e a recuperação traz o errado. Controla-se com atualização por fato (substituir quando muda), validade nos episódios e delete por usuário, que também atende ao direito de esquecimento.

Como decidir o que vira memória e o que é descartado?

A pergunta certa não é "o que o usuário disse?", é "o que sobre este usuário continua verdade na próxima sessão?". Fatos duráveis (plano contratado, preferência de idioma ou canal, restrições, decisões passadas) valem porque mudam como você atende dali em diante, e devem ser gravados como fato curto, não como a mensagem literal. Conversa fiada e assunto pontual já resolvido são ruído: no máximo viram um resumo de uma linha com validade. E dado vivo (status de pedido, saldo, cotação) nunca é memória: vem de consulta ao sistema na hora, senão o agente responde com um valor obsoleto com cara de recém-checado.

Memória de longo prazo faz o agente lembrar do cliente sem estourar contexto

Separar janela de contexto de memória persistente, gravar fato em vez de transcript, recuperar por relevância escopada ao usuário e manter a memória atualizada é o que transforma um agente amnésico num que conhece o cliente. Posso desenhar essa camada no seu agente de atendimento, do escopo por usuário à recuperação e ao esquecimento, com segurança de privacidade e sem inflar o custo de token.