Documentação oficial desta página · v0.20.6
Memória Persistente
O Hermes Agent tem uma memória curada e limitada, que sobrevive entre sessões. É assim que ele lembra suas preferências, seus projetos, seu ambiente e o que já aprendeu.
Como funciona
Dois arquivos formam a memória do agente:
| Arquivo | Para que serve | Limite de caracteres |
|---|---|---|
| MEMORY.md | Anotações do próprio agente — fatos do ambiente, convenções, o que aprendeu | 2.200 caracteres (~800 tokens) |
| USER.md | Perfil do usuário — suas preferências, seu jeito de se comunicar, o que você espera | 1.375 caracteres (~500 tokens) |
Os dois ficam em ~/.hermes/memories/ e entram no prompt de sistema como um retrato congelado no
começo da sessão. O agente cuida da própria memória com a ferramenta memory — pode acrescentar,
substituir ou remover entradas.
Não aponte dois processos de agente para o mesmo diretório do Hermes. As escritas de memória são automáticas e voltam para o prompt de sistema no início da sessão, então dois escritores dividindo o mesmo diretório vão empilhar as entradas um do outro num estado que nenhum dos dois — nem você — escreveu. A memória é separada por perfil de propósito: dê um perfil próprio ao segundo agente e, se eles precisarem de memória compartilhada, use um provedor externo de memória.
Os limites de caracteres mantêm a memória enxuta. A memória não se compacta sozinha: quando uma
escrita passaria do limite, a ferramenta memory devolve erro em vez de descartar entradas em
silêncio. Aí o próprio agente abre espaço — consolidando ou removendo entradas no mesmo turno,
antes de tentar de novo (veja O que acontece quando a memória enche).
Vale notar que o replace também respeita o limite: trocar uma entrada por outra maior ainda pode
estourar, então o conteúdo novo precisa encurtar (ou outra entrada precisa sair).
Como a memória aparece no prompt de sistema
No começo de cada sessão, as entradas são lidas do disco e renderizadas no prompt de sistema como um bloco congelado:
══════════════════════════════════════════════
MEMORY (your personal notes) [67% — 1,474/2,200 chars]
══════════════════════════════════════════════
User's project is a Rust web service at ~/code/myapi using Axum + SQLx
§
This machine runs Ubuntu 22.04, has Docker and Podman installed
§
User prefers concise responses, dislikes verbose explanations
O formato inclui:
- um cabeçalho dizendo qual repositório é (MEMORY ou USER PROFILE);
- a porcentagem de uso e a contagem de caracteres, para o agente saber quanto ainda cabe;
- as entradas separadas pelo sinal de parágrafo
§; - entradas podem ter várias linhas.
Padrão de retrato congelado: o que entra no prompt de sistema é capturado uma vez, no início da sessão, e não muda no meio do caminho. Isso é de propósito — preserva o cache de prefixo do modelo, o que rende desempenho. Quando o agente acrescenta ou remove entradas durante a sessão, as mudanças vão para o disco na hora, mas só aparecem no prompt de sistema na sessão seguinte. As respostas da ferramenta sempre mostram o estado real.
Ações da ferramenta de memória
O agente usa a ferramenta memory com estas ações:
- add — acrescenta uma entrada nova
- replace — substitui uma entrada existente (encontra por trecho, no parâmetro
old_text) - remove — remove uma entrada que não serve mais (também por trecho, em
old_text)
Não existe ação read — o conteúdo da memória entra sozinho no prompt de sistema no início da
sessão. O agente enxerga as memórias como parte do próprio contexto de conversa.
Busca por trecho
As ações replace e remove casam por um trecho curto e único — não é preciso repetir a entrada
inteira. O old_text só precisa identificar exatamente uma entrada:
# Se a memória contém "User prefers dark mode in all editors"
memory(action="replace", target="memory",
old_text="dark mode",
content="User prefers light mode in VS Code, dark mode in terminal")
Se o trecho casar com mais de uma entrada, vem um erro pedindo algo mais específico.
Os dois alvos
memory — anotações do agente
Para o que o agente precisa lembrar sobre o ambiente, os fluxos de trabalho e as lições aprendidas:
- fatos do ambiente (sistema operacional, ferramentas, estrutura do projeto);
- convenções e configuração do projeto;
- manias das ferramentas e contornos descobertos;
- registro de tarefas concluídas;
- técnicas que deram certo.
user — perfil do usuário
Para informação sobre quem você é, o que prefere e como se comunica:
- nome, cargo, fuso horário;
- preferências de comunicação (conciso ou detalhado, formato);
- implicâncias e coisas a evitar;
- hábitos de trabalho;
- nível técnico.
O que guardar e o que deixar passar
Guardar (por iniciativa própria)
O agente guarda sozinho — você não precisa pedir. Ele guarda quando aprende:
- Preferências: "prefiro TypeScript a JavaScript" → vai para
user - Fatos do ambiente: "este servidor roda Debian 12 com PostgreSQL 16" → vai para
memory - Correções: "não use
sudonos comandos de Docker, o usuário está no grupo docker" →memory - Convenções: "o projeto usa tabulação, linha de 120 colunas, docstrings estilo Google" →
memory - Trabalho concluído: "banco migrado de MySQL para PostgreSQL em 15/01/2026" →
memory - Pedidos explícitos: "lembre que minha rotação de chave de API é mensal" →
memory
Deixar passar
- Óbvio ou trivial: "o usuário perguntou sobre Python" — vago demais para servir.
- Fácil de redescobrir: "Python 3.12 aceita f-string aninhada" — dá para buscar na web.
- Despejo de dados: blocos grandes de código, arquivos de log, tabelas — grandes demais.
- Coisa da sessão: caminhos temporários, contexto de depuração de uma vez só.
- O que já está em arquivo de contexto: conteúdo de SOUL.md e AGENTS.md.
Gestão de capacidade
A memória tem limites rígidos para o prompt de sistema não crescer sem controle:
| Repositório | Limite | Entradas típicas |
|---|---|---|
| memory | 2.200 caracteres | 8 a 15 entradas |
| user | 1.375 caracteres | 5 a 10 entradas |
O que acontece quando a memória enche
Quando uma entrada nova passaria do limite, a ferramenta devolve erro:
{
"success": false,
"error": "Memory at 2,100/2,200 chars. Adding this entry (250 chars) would exceed the limit. Consolidate now: use 'replace' to merge overlapping entries into shorter ones or 'remove' stale or less important entries (see current_entries below), then retry this add — all in this turn.",
"current_entries": ["..."],
"usage": "2,100/2,200"
}
O agente então deve:
- ler as entradas atuais (elas vêm na própria resposta de erro);
- identificar o que dá para remover ou consolidar;
- usar
replacepara fundir entradas parecidas em versões mais curtas; - e então fazer o
addda entrada nova.
Boa prática: quando a memória passa de 80% da capacidade (visível no cabeçalho do prompt de sistema), consolidar antes de acrescentar. Por exemplo, fundir três entradas separadas de "o projeto usa X" numa única descrição do projeto.
Exemplos de entradas boas
Compactas e densas em informação funcionam melhor:
# Boa: junta vários fatos relacionados
User runs macOS 14 Sonoma, uses Homebrew, has Docker Desktop and Podman. Shell: zsh with oh-my-zsh. Editor: VS Code with Vim keybindings.
# Boa: convenção específica e acionável
Project ~/code/api uses Go 1.22, sqlc for DB queries, chi router. Run tests with 'make test'. CI via GitHub Actions.
# Boa: lição aprendida, com contexto
The staging server (10.0.1.50) needs SSH port 2222, not 22. Key is at ~/.ssh/staging_ed25519.
# Ruim: vaga demais
User has a project.
# Ruim: prolixa demais
On January 5th, 2026, the user asked me to look at their project which is
located at ~/code/api. I discovered it uses Go version 1.22 and...
Prevenção de duplicatas
O sistema recusa entradas exatamente iguais às que já existem. Se você tentar acrescentar um conteúdo que já está lá, a resposta vem com sucesso e a observação de que nada foi duplicado.
Varredura de segurança
Antes de serem aceitas, as entradas passam por uma varredura em busca de padrões de injeção e exfiltração — afinal, elas entram no prompt de sistema. Conteúdo que casa com padrões de ameaça (injeção de prompt, exfiltração de credenciais, backdoor de SSH) ou que traz caracteres Unicode invisíveis é bloqueado.
Busca em sessões
Além do MEMORY.md e do USER.md, o agente consegue procurar nas conversas passadas com a ferramenta
session_search:
- todas as sessões, da CLI e das plataformas de mensagem, ficam em SQLite (
~/.hermes/state.db), com busca em texto completo por FTS5; - as consultas devolvem as mensagens de verdade, direto do banco — sem resumo do modelo, sem corte;
- o agente encontra coisas discutidas semanas atrás, mesmo fora da memória ativa;
- e consegue rolar para frente e para trás dentro de qualquer sessão que encontrar.
hermes sessions list # navegar pelas sessões passadas
Veja Session Search Tool para os três formatos de chamada (descoberta, rolagem e navegação) e o formato da resposta.
session_search comparado à memória
| Aspecto | Memória persistente | Busca em sessões |
|---|---|---|
| Capacidade | ~1.300 tokens no total | Ilimitada (todas as sessões) |
| Velocidade | Instantânea (já está no prompt) | ~20 ms na consulta FTS5, ~1 ms na rolagem |
| Custo | Custa tokens em toda requisição | Grátis — não chama o modelo |
| Serve para | Fatos importantes, sempre à mão | Achar uma conversa específica do passado |
| Manutenção | Curada pelo agente | Automática — tudo fica guardado |
Memória é para fatos essenciais, que precisam estar sempre no contexto. Busca em sessões é para "a gente falou de X semana passada?", quando o agente precisa recuperar detalhes de conversas antigas.
Jornada de aprendizado (/journey)
A jornada de aprendizado é uma linha do tempo de tudo que o Hermes aprendeu — skills salvas e entradas de memória dispostas no tempo (mais antigas em cima, mais novas embaixo), com um controle de "constelação" que repassa a construção. Os mesmos dados alimentam três superfícies:
- CLI clássica —
hermes journey(com os apelidoshermes learningehermes memory-graph) desenha a linha do tempo no terminal. Opções:--playanima a construção (--fpsajusta a velocidade),--widthe--heightmudam o tamanho,--no-colordesliga a cor e--jsondespeja os dados brutos do grafo. - TUI —
/journey(apelidos/learning,/memory-graph) abre a linha do tempo em sobreposição. - Aplicativo desktop —
/journeyabre o painel do Mapa Estelar, uma visualização interativa dos mesmos nós.
Além de ver, a jornada é também onde você poda e corrige o que o Hermes aprendeu:
| Comando | O que faz |
|---|---|
hermes journey list | Lista os identificadores dos nós — nomes de skills e ids memory:<origem>:<índice> para trechos de memória. |
hermes journey delete <nó> [-y] | Apaga um nó. Skills são arquivadas (dá para restaurar); trechos de memória são removidos. -y pula a confirmação. |
hermes journey edit <nó> | Abre o conteúdo do nó (o SKILL.md da skill ou o trecho de memória) no $EDITOR. |
Os mesmos subcomandos list, delete <id> e edit <id> funcionam pelo comando /journey dentro
da conversa na CLI, e o painel do desktop oferece editar e apagar direto nos nós.
Configuração
# em ~/.hermes/config.yaml
memory:
memory_enabled: true
user_profile_enabled: true
memory_char_limit: 2200 # ~800 tokens
user_char_limit: 1375 # ~500 tokens
write_approval: false # false = escreve livremente (padrão) | true = exige aprovação
Colocar os dois, memory_enabled e user_profile_enabled, em false desliga por completo os
repositórios embutidos: a ferramenta memory sai do schema e o bloco de orientação dela sai do
prompt de sistema, então o modelo nunca fica sabendo de uma ferramenta que não pode usar. Um
provedor externo definido em memory.provider (Hindsight, Mem0, Honcho…) não é afetado e mantém
as próprias ferramentas — use isso quando quiser um backend de terceiros no lugar dos arquivos
embutidos. Listar memory em agent.disabled_toolsets é a chave mais pesada: esconde também as
ferramentas do provedor externo.
Só com memory_enabled: false (perfil do usuário ainda ligado), a ferramenta continua — ela é que
sustenta o perfil — mas o prompt de sistema troca a orientação completa de memória por um bloco
menor, só sobre o perfil. O schema anuncia apenas o alvo user, e escritas diretas ou em fila para
o MEMORY.md desligado são recusadas. A configuração inversa anuncia só o memory e recusa
escritas no USER.md.
Controlar as escritas de memória (write_approval)
Por padrão o agente salva memória livremente — inclusive na revisão de autoaperfeiçoamento que roda
em segundo plano depois de cada turno. Se você prefere aprovar antes, coloque
memory.write_approval: true. É uma trava simples, de liga e desliga, aplicada tanto aos
turnos em primeiro plano quanto à revisão em segundo plano:
write_approval | Comportamento |
|---|---|
false (padrão) | Escreve livremente — a trava está desligada. |
true | Exige aprovação antes de salvar qualquer coisa. Na CLI interativa, as escritas em primeiro plano perguntam ali mesmo (as entradas são pequenas o bastante para ler inteiras). Em todo o resto — plataformas de mensagem, scripts e a revisão em segundo plano — as escritas ficam em fila, para revisão com /memory pending. |
Para desligar a memória de vez (não só travar), coloque
memory_enabled: falseeuser_profile_enabled: false. Com os dois repositórios embutidos desligados, a ferramentamemorysome sozinha.
Revise a fila pela CLI ou por qualquer plataforma de mensagem:
/memory pending # lista as escritas em fila (as automáticas vêm marcadas com [auto])
/memory approve <id> # aplica uma (ou 'all')
/memory reject <id> # descarta uma (ou 'all')
/memory approval on # liga a trava (ou 'off') e grava a escolha
Esta é a resposta para "o agente guardou uma suposição errada sobre mim": ligue
write_approval: true e toda gravação — principalmente as espontâneas, de segundo plano — espera
seu sim ou não antes de entrar no seu perfil.
Avisos da revisão em segundo plano (display.memory_notifications)
Depois de um turno, a revisão de autoaperfeiçoamento pode salvar uma memória ou atualizar uma skill
em silêncio. É o ciclo de aprendizado com consentimento do Hermes: correções repetidas e lições
duradouras viram entradas compactas de memória ou skills, enquanto o write_approval pode segurar
essas escritas para revisão antes que afetem as sessões seguintes. Por padrão aparece uma linha
curta, 💾 Memory updated, para você saber que aconteceu. Dá para escolher o quanto isso fala:
display:
memory_notifications: on # off | on (padrão) | verbose
| Valor | Comportamento |
|---|---|
off | Nenhum aviso na conversa. A revisão continua rodando e continua escrevendo — você só não vê a linha. |
on (padrão) | Linha genérica, do tipo 💾 Memory updated ou 💾 Skill 'foo' patched. |
verbose | Inclui uma prévia compacta do que mudou, como 💾 Memory ➕ User prefers terse replies ou um trecho do diff da skill, no formato "antigo" → "novo". |
Isso controla só o aviso na conversa do gateway. A revisão em si, e as escritas nos seus repositórios de memória e skills, não mudam com essa configuração. Dá para definir por plataforma, em
display.platforms.<plataforma>.memory_notifications.
Rodar a revisão num modelo mais barato (auxiliary.background_review)
Por padrão a revisão roda no seu modelo principal, repassando a conversa — que já está quente no cache de prompt, então são leituras baratas. Com um modelo principal caro, dá para rodar a revisão num modelo mais barato:
auxiliary:
background_review:
provider: openrouter
model: google/gemini-3-flash-preview # auto (padrão) = modelo principal da conversa
Quando você aponta para um modelo diferente do principal, a revisão roda lá por um custo bem menor (3 a 5 vezes, nos testes). Como um modelo diferente não reaproveita o cache do principal de qualquer forma, a bifurcação repassa automaticamente um resumo compacto da conversa (os turnos recentes na íntegra mais um sumário dos antigos), em vez da transcrição inteira — o que reduz o que vai para o cache novo. A captura se mantém: nos testes, a captura de memória ficou idêntica e a de skills quase idêntica à da revisão no modelo principal.
Deixe em auto (ou aponte para o modelo principal) e nada muda — a revisão segue no principal, com
o repasse completo e o cache quente.
Desligar as revisões automáticas (enabled)
Em máquinas movimentadas, a bifurcação de revisão pode consumir uma fatia relevante do total de tokens. Quem administra pode desligá-la sem zerar os intervalos de sugestão:
auxiliary:
background_review:
enabled: true # false = não bifurca automaticamente depois do turno
Com enabled: false, as bifurcações automáticas depois do turno não acontecem; o /refine manual
continua funcionando.
O uso da bifurcação fica registrado em session_model_usage com task='background_review', e uma
linha de conclusão vai para o agent.log
(Background review complete: thread=bg-review calls=… in=… out=… result=…).
Controlar as escritas de skills (skills.write_approval)
As skills usam a mesma trava de liga e desliga, mas a revisão é diferente, porque um SKILL.md é
grande demais para caber numa bolha de conversa:
skills:
write_approval: false # false = escreve livremente (padrão) | true = exige aprovação
Com write_approval: true, as escritas de skill (criar, editar, aplicar patch, gravar arquivo,
apagar) sempre vão para a fila, venham de onde vierem. Você revisa o resumo de uma linha ali
mesmo, mas o diff completo fica fora da conversa:
/skills pending # lista as escritas em fila, com um resumo de uma linha cada
/skills diff <id> # diff unificado completo (melhor ver na CLI ou no painel)
/skills approve <id> # aplica (ou 'all')
/skills reject <id> # descarta (ou 'all')
/skills approval on # liga a trava (ou 'off') e grava a escolha
Numa plataforma de mensagem, aprove pela descrição e pelos metadados, ou abra o /skills diff na
CLI ou no painel — ou ainda o arquivo em fila, em ~/.hermes/pending/skills/<id>.json — quando
quiser ler a mudança inteira. Detalhes em
Gating agent skill writes.
Provedores externos de memória
Para uma memória mais profunda, além do MEMORY.md e do USER.md, o Hermes vem com 8 plugins de provedores externos — Honcho, OpenViking, Mem0, Hindsight, Holographic, RetainDB, ByteRover e Supermemory.
Provedores externos rodam ao lado da memória embutida (nunca no lugar dela) e acrescentam recursos como grafos de conhecimento, busca semântica, extração automática de fatos e modelagem do usuário entre sessões.
hermes memory setup # escolhe um provedor e configura
hermes memory status # mostra o que está ativo
Veja o guia Memory Providers para detalhes de cada provedor, instruções de configuração e comparação.