O recall do seu provider de memória estava sendo truncado: spill opt-in e duas outras falhas silenciosas

Você conecta um provider de memória externa ao Hermes — Hindsight, Mem0, Honcho, qualquer um deles. Por umas duas semanas ele lembra de você de verdade. Então um dia você menciona o contrato de API que combinou na semana passada, e ele responde como se nunca tivesse ouvido falar. Você culpa o modelo, ou presume que o provider perdeu a escrita. A história real é mais irritante: o recall foi buscado, e então o próprio Hermes o substituiu pelos primeiros parágrafos, pelos últimos parágrafos e por um caminho de arquivo.
Esse comportamento mudou em 9 de outubro, em três correções integradas que cobrem três falhas silenciosas em torno de plugins de memória externa: recall truncado, providers que somem do hermes memory status e uma instalação que repete a tentativa a cada inicialização. Veja cada sintoma, seu mecanismo e o que fazer a respeito.
Sintoma um: o recall é truncado sem aviso
O Hermes tem um mecanismo geral de “spill”: quando a saída de um hook cruza um limite de tamanho, o texto completo não é colocado no contexto. Uma prévia de início e fim toma seu lugar, com um caminho de arquivo para o resto. Para hooks de plugin comuns, esse padrão é sensato — um plugin falante não deveria devorar seu context window.
A pegadinha era que o mesmo mecanismo se aplicava ao recall de prefetch da memória externa. Então um provider que já tinha aplicado seu próprio orçamento de recall era aparado uma segunda vez pelo Hermes: o meio, ranqueado por relevância, desaparecia de vista, e o modelo via apenas o começo e o fim.
A correção transforma isso em uma escolha explícita (PR #135157):
# ~/.hermes/config.yaml
memory:
prefetch_spill_enabled: false # padrão: o recall externo permanece intacto
Os detalhes valem a pena:
- Padrão false. O recall externo chega inteiro ao modelo. Ainda existe um teto de segurança: recall acima de 10×
hooks.output_spill.max_chars(pelo menos 100.000 caracteres) continua sofrendo spill, então um provider descontrolado não consegue estourar o context window. - Defina como true e você recupera o comportamento antigo: recall grande demais vira uma prévia de início/fim mais um caminho de arquivo. Ele reutiliza o limite, os comprimentos de prévia e o diretório compartilhados de
hooks.output_spill— ehooks.output_spill.enabled: falseainda sobrescreve tudo. - O spill normal de hooks de plugin não muda e permanece ligado por padrão, independentemente dessa configuração de memória.
- A configuração é fotografada no momento em que o provider se registra, então reinicie o Hermes depois de alterá-la; uma conversa em andamento não muda de comportamento no meio do turno.
- A documentação oficial diz sem rodeios: quando seu provider tem seu próprio orçamento de recall, prefira esse. Ele sabe melhor do que uma regra de truncamento o que manter.
Um trade-off honesto: manter o recall completo deixa os prompts maiores. Se você paga por tokens medidos e roda um serviço de memória falante, voltar a ligar prefetch_spill_enabled pode economizar dinheiro — desde que você aceite que o meio do recall fica menos visível.
Sintoma dois: seu provider some do hermes memory status
A segunda correção (PR #135524) é uma linha alterada mais uma linha de docstring, e importa mais do que seu tamanho sugere.
Para decidir se uma pasta de plugin é um provider de memória, o Hermes procura por register_memory_provider ou MemoryProvider no __init__.py dele. Essa é uma varredura barata, sem imports — mas ela só lia os primeiros 8 KB do arquivo. Um provider perfeitamente funcional, com uma docstring de módulo longa, era ignorado: sumia do hermes memory status, e hermes memory setup <name> dizia “not found”.
O plugin de catálogo excel_line passou exatamente por isso, e o contorno na época era sombrio: encurtar a docstring para que o código de registro caísse dentro dos primeiros 8 KB (#135442 / #135473). Esse contorno não é mais necessário. O caminho rápido continua (ainda uma checagem de texto barata de 8 KB); só quando não encontra nada é que ele recorre ao _defines_memory_provider existente, que faz o parse dos módulos de nível superior do pacote sem importá-los. Providers que já davam match não pagam nada extra — só as pastas que passam batido é que pagam por um parse de AST.
Se você escreveu um plugin que instala mas nunca é detectado: pare de apagar sua documentação e atualize.
Sintoma três: o provider se reinstala a cada inicialização
A terceira correção (PR #135529) trata de um loop de novas tentativas que vira bola de neve.
A instalação automática de um provider de memória roda na inicialização do agente — um hermes chat, uma execução de cron, um agente de gateway, um reinício do Desktop, cada um conta. Antes da correção, uma instalação falha era repetida em cada uma dessas inicializações, e cada nova tentativa era registrada como uma falha nova. A telemetria do PR (14 dias, com deduplicação) mostra o que isso produziu:
| plugin | ok | failed | dias com falha de instalação | falhas por dia com falha de instalação |
|---|---|---|---|---|
| hindsight | 130 | 1048 | 204 | 5.1 |
| mnemosyne | 47 | 288 | 83 | 3.5 |
As falhas diárias do Hindsight subiram de 8 → 47 → 170 → 204 entre 29/09 e 02/10, em boa parte o mesmo punhado de falhas sendo contado repetidas vezes, além de um conjunto menor de erros de rede de verdade (uv lock do PM, git clone). A conclusão do PR é sem rodeios: isso é um loop de novas tentativas, não 1.048 falhas distintas.
A semântica agora é limpa: STARTUP_RETRY_SECONDS = 3600.0 em hermes_cli/memory_provider_migration.py — um provider cuja instalação automática falhou não é repetido por nenhum processo durante uma hora. Quando ele volta a subir, ele diz o que rodar:
Its automatic install failed less than an hour ago: run `hermes plugins install hindsight`
O mesmo PR corrigiu um diagnóstico errado relacionado: quando plugins/<name> já existe como um symlink para outro lugar, uma instalação de catálogo agora diz que o espaço está ocupado em vez de culpar o manifest do plugin.
Como verificar sua própria configuração
hermes memory status # qual provider externo está ativo e se está instalado
hermes memory setup # escolha ou configure um provider (também menciona uma instalação ausente)
hermes memory off # desative o provider externo
hermes plugins list # o plugin está presente?
Uma ordem prática de triagem para “ele esqueceu algo”: confirme que o provider está presente com hermes memory status, depois leia memory.provider e prefetch_spill_enabled no config.yaml e, em seguida, decida se o modelo nunca recebeu o recall (configuração) ou se o provider nunca o armazenou (serviço). Para contexto sobre como escolher um backend de memória, veja nosso passo a passo de memória semântica e o recurso de dreaming / consolidação de memória; a superfície completa de comandos está na referência de hermes memory.
Status da release
As três correções foram integradas em 2026-10-09, depois de a v0.21.6 ser lançada em 8 de outubro, então elas estão apenas em origin/main por enquanto — espere a próxima release ou rode hermes update. Para saber como os plugins são revisados e fixados, veja o guia do catálogo de plugins.
A conclusão
As três são falhas silenciosas: nenhum erro, nenhuma linha de log, só um comportamento discretamente pior — recall aparado, um plugin ignorado, uma falha contada mil vezes. Elas sobreviveram tanto tempo porque cada uma vive em uma camada que os usuários não conseguem ver. Se você roda um provider de memória externa, a coisa mais útil que você pode fazer hoje é abrir o config.yaml, olhar memory.prefetch_spill_enabled e decidir se quer recall completo ou um prompt menor.