Dê Memória Semântica ao Hermes Agent com LanceDB: Instalação, Configuração, Benchmark

Uma das experiências mais frustrantes com um agente de IA é ele esquecer as coisas. Na segunda-feira você diz: “uso pnpm workspaces e faço deploy via wrangler.” Na sexta-feira, em uma sessão nova, ele não faz ideia do que você está falando. O Hermes Agent até tem memória integrada (MEMORY.md / USER.md em ~/.hermes/memories/) e recall entre sessões — mas, no fundo, é correspondência lexical. Diga “deploy” como “ship it”, ou “pnpm” como “o gerenciador de pacotes”, e a memória simplesmente não é encontrada.
Em agosto de 2026, a LanceDB lançou um plugin oficial de memória semântica para o Hermes Agent — hermes-agent-memory — que transforma isso em um problema puramente de engenharia: os fatos são armazenados como vetores em uma tabela LanceDB local, e o recall faz a correspondência por similaridade semântica em vez de palavras-chave. No benchmark LongMemEval do plugin, o recall puramente vetorial marca 0.661 de precisão / 0.795 de Recall@5, claramente à frente da busca de sessão FTS5 integrada do Hermes, com 0.533 / 0.659.
Este post guia você por toda a instalação, explica como funcionam as quatro ferramentas de memória, como escolher entre os modos de recuperação híbrida e faz uma leitura cuidadosa dos números do benchmark.
1. Entenda primeiro a arquitetura de memória do Hermes
Antes de instalar qualquer coisa, gaste dois minutos entendendo como a camada de memória do Hermes foi desenhada — caso contrário, você pode instalar tudo e ficar se perguntando por que nada funciona.
A memória do Hermes é uma arquitetura de providers. agent/memory_provider.py define uma interface abstrata MemoryProvider, e agent/memory_manager.py a orquestra (prefetch, sync, shutdown). Dois hooks importam mais:
on_pre_compress(messages)— extrai o que vale a pena manter antes de a compressão de contexto rodar;on_session_end(messages)— uma passada final de extração ao fim de uma sessão.
O comando interativo hermes memory setup varre os providers instalados em plugins/memory/, deixa você escolher um e grava memory.provider: <name> em ~/.hermes/config.yaml (a linha 277 de hermes_cli/memory_setup.py é exatamente essa gravação). Em outras palavras: o backend de memória é um registro plugável. De fábrica, o Hermes vem com oito providers: mem0, hindsight, honcho, supermemory, byterover, retaindb, holographic e openviking.
O plugin LanceDB usa o mesmo canal: ele se registra como memory provider, é instalado em ~/.hermes/plugins/lancedb/ via hermes plugins install e depois é selecionado no hermes memory setup.
Quer testar sem mexer na sua configuração atual?
hermes profile create lancedb-democria um perfil isolado; adicione-p lancedb-demoa todos os comandos abaixo e roderm -rf ~/.hermes/profiles/lancedb-demoquando terminar.
2. Instalação: quatro passos, cerca de cinco minutos
Passo 1: Instale o plugin
hermes plugins install lancedb/hermes-agent-memory
Isso faz um shallow clone de https://github.com/lancedb/hermes-agent-memory.git em ~/.hermes/plugins/lancedb/. Rode o mesmo comando de novo mais tarde para puxar atualizações.
Passo 2: Instale as dependências de runtime no Python do próprio Hermes
O Hermes carrega plugins dentro do próprio interpretador, então as dependências precisam ir para a venv do Hermes — não para um virtualenv separado:
# Se você usou o instalador de uma linha:
uv pip install --python ~/.hermes/hermes-agent/venv/bin/python3 lancedb openai pyyaml
Nota: o interpretador do Hermes é compartilhado entre todos os perfis, então este passo não tem a flag
-pe só precisa rodar uma vez. A configuração padrão não precisa de stack de ML local — os embeddings passam pela API da OpenAI. Só se você habilitar o reranker cross-encoder é que precisará desentence-transformers(que arrasta ~2GB de torch).
Passo 3: Ative o provider
hermes memory setup
# escolha "lancedb" no menu interativo
Espere uma saída assim, com memory.provider: lancedb gravado em ~/.hermes/config.yaml:
# ✓ LanceDB memory configured (embedding dim: 1536)
# Start a new session to activate.
Os embeddings usam por padrão o modelo text-embedding-3-small da OpenAI (1536 dimensões), então é preciso ter uma OPENAI_API_KEY disponível.
Passo 4: Verifique (não pule este passo)
O relato mais comum de “a memória não está funcionando” é simplesmente o provider não estar ativo — se memory.provider não estiver definido, o Hermes cai silenciosamente para as notas integradas e você nunca verá as ferramentas lancedb_*. Confirme que está ligado:
hermes memory status # procure por: Provider: lancedb, installed ✓, available ✓
hermes plugins list # deve listar "lancedb"
hermes chat -q "Hello" # o agent.log deve conter "lancedb provider initialized"
Se memory status não mostrar nada (ou mostrar o provider errado), rode hermes memory setup de novo e escolha lancedb novamente.
3. As quatro ferramentas de memória
Uma vez ativo, o agente ganha quatro novas ferramentas:
| Ferramenta | Finalidade |
|---|---|
lancedb_recall |
Recall vetorial (padrão) ou híbrido sobre a memória do workspace; retorna IDs, trechos, scores e IDs dos turnos de proveniência |
lancedb_remember |
Armazena um fato durável, tipado como preference / entity / event / case / pattern / general; deduplicado por hash de conteúdo |
lancedb_read |
Busca uma memória pelo ID, opcionalmente com os turnos de proveniência dos quais ela foi extraída |
lancedb_forget |
Exclusão em duas etapas: action: preview lista os candidatos pela descrição; depois action: delete com o ID exato |
O bloco de system prompt do provider diz ao modelo quando usar cada ferramenta: lancedb_remember só quando o usuário pedir explicitamente para lembrar, e sempre preview antes de qualquer exclusão — assim o agente não apaga uma memória importante por acidente.
Além das chamadas explícitas, existe um pipeline de extração automática: quando uma sessão acumula turnos suficientes (padrão min_turns: 3), fatos duráveis são extraídos da conversa por um LLM auxiliar, tanto antes da compressão de contexto quanto no fim da sessão. Mesmo que você nunca diga “lembre disto”, informações úteis a longo prazo acabam persistidas — é esse o mecanismo do “o agente fica mais inteligente quanto mais você o usa”.
4. Modos de recuperação: vetorial vs híbrido
O recall é o coração da memória semântica, e o plugin dá a você duas camadas de controle:
1. Modo de busca (por chamada): vector (padrão) ou hybrid (vetorial + full-text BM25), sobrescrito a cada chamada pelo parâmetro mode do lancedb_recall.
2. Fusão híbrida (config global): no modo hybrid, a forma como as pernas vetorial e full-text se combinam é definida por plugins.lancedb.retrieval.reranker.type:
rrf(padrão) — Reciprocal Rank Fusion, fusão baseada em rank com pesos iguais;linear— combinação linear ponderada;reranker.weight(padrão 0.7) pende para a perna vetorial;cross-encoder— reranqueia um pool superamostrado com um modelo sentence-transformers local; melhor qualidade, mais lento.
Exemplo de configuração (~/.hermes/config.yaml — grave apenas as chaves que quiser sobrescrever):
plugins:
lancedb:
retrieval:
mode: hybrid # vector (default) | hybrid
top_k: 10
reranker:
type: linear # rrf | linear | cross-encoder
weight: 0.7
Também existe um modo
ftspuramente lexical, mas os autores recomendam explicitamente não usá-lo: a correspondência apenas por palavras-chave tende a trazer linhas coincidentes e irrelevantes que poluem o contexto do agente. O recall semântico vive novector/hybrid.
5. Backends de embedding: não só OpenAI
Na configuração padrão, a única chamada remota é a API de embeddings — todo o resto é local. Aponte o cliente compatível com OpenAI para qualquer endpoint que fale o mesmo formato e pronto, sem mudar código. Alguns exemplos práticos:
# Modelo não-OpenAI via OpenRouter
plugins:
lancedb:
embedding:
model: google/gemini-embedding-001
base_url: https://openrouter.ai/api/v1
api_key_env: OPENROUTER_API_KEY
# Totalmente local: Ollama
plugins:
lancedb:
embedding:
model: nomic-embed-text
base_url: http://localhost:11434/v1
api_key_env: OLLAMA_API_KEY # any value works for local Ollama
Trocar de modelo de embedding exige cuidado: se a dimensão do novo modelo não bater com a tabela existente, o plugin falha de forma ruidosa em vez de retornar nada silenciosamente. A solução é apagar ~/.hermes/lancedb/memories.lance/ e deixar a próxima sessão recriar a tabela (tudo bem se você não se importar com as memórias antigas).
O LLM auxiliar usado para extração de fatos também pode apontar para um modelo mais barato, pelo roteamento auxiliar do próprio Hermes (roteamento de provider, fallback e esgotamento de créditos tratados para você):
auxiliary:
lancedb_extraction:
provider: openrouter
model: google/gemini-3-flash
6. Lendo o benchmark: o recall semântico é realmente melhor?
O repositório do plugin traz um harness de QA de conversas longas LongMemEval-S (60 casos estratificados, respondidos por gpt-5.4, avaliados por gpt-5.4-mini, top-k 5). Ele compara as opções de recall que um usuário do Hermes realmente tem:
| Variante | Precisão | Recall@5 | MRR@5 | Query p50 |
|---|---|---|---|---|
| hermes-session-search (baseline FTS5/BM25 integrada) | 0.533 | 0.659 | 0.639 | 0.002s |
| lancedb-vector (padrão) | 0.661 | 0.795 | 0.682 | 0.207s |
| lancedb-hybrid-rrf | 0.610 | 0.650 | 0.635 | 0.235s |
| lancedb-hybrid-linear | 0.610 | 0.718 | 0.676 | 0.246s |
| lancedb-hybrid-cross-encoder | 0.678 | 0.754 | 0.689 | 0.702s |
Conclusões notáveis:
- O recall semântico vence claramente a baseline lexical: 0.661 vs 0.533 de precisão, 0.795 vs 0.659 de Recall@5 — a paráfrase (deploy vs ship) é exatamente onde o BM25 fica cego, e a recuperação vetorial é muito mais robusta, a ~0.2s por consulta.
- O RRF com pesos iguais na verdade atrapalha (0.610 < 0.661): hits lexicais ruidosos deslocam bons resultados vetoriais. É por isso que o padrão de fábrica é
vector, e nãohybrid. - Se você quer sinal lexical, use
linear, não RRF: a fusão ponderada recupera o Recall@5 para 0.718 com um custo mínimo de latência. - O cross-encoder lidera em qualidade (0.678 / 0.754), mas o p50 sobe para ~0.7s e ele exige torch — para setups tolerantes a latência e sensíveis a precisão.
Os autores classificam esses números como ilustrativos: a precisão absoluta acompanha o modelo que responde (aqui o gpt-5.4), mas a ordem relativa dos métodos de recuperação é estável. O harness também mede apenas o substrato de recuperação (recall verbatim dos turnos originais), não o ciclo completo de extração de fatos — no uso real, a recuperação guiada por fatos pode ir ainda melhor.
7. Layout de armazenamento e auto-compactação
Tudo é local, sem serviço externo:
| Caminho | Conteúdo |
|---|---|
~/.hermes/lancedb/memories.lance/ |
Dataset LanceDB (fragments, manifest, índices). Tabela única memories; a coluna kind separa linhas de fato e de turno |
~/.hermes/lancedb/.last_optimize_version |
Arquivo sentinela: table.version no último optimize() bem-sucedido |
~/.cache/huggingface/ |
Cache do reranker cross-encoder; só existe quando reranker.type: cross-encoder está habilitado |
Quer fuçar no store diretamente, estilo SQL:
uv run --project ~/.hermes/hermes-agent python -c "
import lancedb
db = lancedb.connect('~/.hermes/lancedb')
df = db.open_table('memories').to_pandas()
print(df[['kind', 'category', 'content']].head())
"
As cargas de trabalho de agentes são dominadas por escritas de linha única, e cada add/delete do Lance é um commit — sem intervenção, pequenos fragments e arquivos de versão se acumulam para sempre. A auto-compactação do plugin (ligada por padrão) compara a versão com o arquivo sentinela e roda table.optimize(cleanup_older_than=timedelta(days=7)) em uma thread daemon quando o delta cruza optimize_every_commits (padrão 50). Um lock não bloqueante garante um optimize por vez e os writers nunca são bloqueados. Desabilite (maintenance.enabled: false) e o dataset crescerá sem limite — geralmente não recomendado.
8. Referência rápida de solução de problemas
hermes plugins listnão mostralancedb: confira se o symlink~/.hermes/plugins/lancedbresolve para o repositório.- O agente só grava a memória integrada, sem ferramentas
lancedb_*: o provider não está ativo. Rodehermes memory status— você quer verProvider: lancedbcomavailable ✓; se estiver vazio, rodehermes memory setupde novo. - O recall falha com erro de autenticação: os embeddings chamam a API da OpenAI — garanta que
OPENAI_API_KEYestá definida (no ambiente ou em~/.hermes/.env). - O diretório
.lancenão para de crescer: confirmemaintenance.enabled: truee que~/.hermes/lancedb/.last_optimize_versionavança entre sessões;lancedb optimize startingnoagent.logsignifica que a compactação está rodando. - Mudou
embedding.modele o recall não retorna nada: incompatibilidade de dimensão. Apague~/.hermes/lancedb/memories.lance/para recriar a tabela.
Conclusão
O plugin LanceDB preenche a lacuna mais importante na memória de longo prazo do Hermes Agent: recall pelo significado, não pela palavra-chave. Cinco minutos para instalar, zero ajuste fino nos padrões, todos os dados locais — em troca de ~24% a mais de precisão (0.661 vs 0.533) e um grande salto de Recall@5 no LongMemEval. Para trabalhadores do conhecimento, significa que “as coisas que você disse uma vez voltam mesmo quando você pergunta de outro jeito”.
Leituras relacionadas:
- Quer memórias destiladas em uma base de conhecimento legível para humanos? Veja transformando conversas do Hermes em notas Obsidian.
- Os armazenamentos de memória também crescem — gerenciando sessões e espaço em disco: guia de otimização de armazenamento do Hermes.
- Mais dicas do dia a dia para tirar o máximo do seu agente: dicas de produtividade do Hermes Agent.
- Ainda não instalou o Hermes? Comece pelo guia de instalação.