v0.21.2

Hermes Agent v0.21.2


Visão Geral

v0.21.2 — The state.db Patch Release. Lançada em 11 de setembro de 2026. 947 commits não-merge · 1.869 arquivos alterados (+182.504 / −15.564) · 312 PRs mesclados · 140 contribuidores desde a v0.21.1.

A v0.21.0 reescreveu a forma como o armazenamento de sessões lida com suas conexões, e parte dessa reescrita deixou o state.db frágil em uma parcela das instalações: um segundo writer podia cancelar os locks do primeiro, uma base perfeitamente saudável podia ser julgada corrompida, e uma única linha ruim bastava para derrubar o sessions list. A v0.21.2 fecha toda essa classe de falhas. Seis PRs respondem por 44 issues encerradas e atacam camada por camada a propriedade dos locks, a recuperação de WAL, os caminhos de leitura e o diagnóstico, para que a base ou funcione ou falhe de forma clara e específica — nunca em silêncio, e nunca levando a conversa junto.

Em volta dessa campanha, os quatro dias desde a v0.21.1 também trouxeram uma leva de reforços no isolamento entre profiles, o fim da tempestade de inicializações de backends no desktop, um cofre de credenciais que o agente pode usar sem nunca ver um segredo, um índice de plugins revisado e com SHA fixado junto de uma página Plugins unificada no Desktop, e um nível gratuito da Nous com primeira execução guiada. Esta página percorre a janela nessa ordem.


Destaques

1. A campanha de confiabilidade do state.db: seis PRs, 44 issues encerradas

Cada modo de falha abaixo foi reproduzido, corrigido e deixou uma guarda para que a mesma forma não volte em silêncio.

  • Chega de segundos writers. O gateway do profile escrevia o estado das salas gerenciadas no state.db raiz a cada 5 segundos; o dashboard abria um handle de escrita na inicialização; a guarda de ciclo de vida do cron fazia um open() cru contra uma base viva, o suficiente para cancelar os locks POSIX do gateway; e o doctor --fix fazia checkpoint enquanto ainda existia um detentor vivo. Hoje as salas gerenciadas ficam em shared-state.db, o dashboard abre primeiro em modo somente leitura, a guarda passa pelo registro de conexões gerenciadas, e o doctor --fix recusa qualquer checkpoint cuja segurança não consiga provar (#108076).
  • Bases WAL saudáveis não travam mais. Desapareceu uma série de formas em que uma base que funcionava era declarada morta: um dentry (deleted) do OpenZFS, close() competindo com append_message, o pool de leitura entregando conexões em modo journal não confirmado, um disk I/O error transitório no WSL2 fazendo o get_session falhar logo na primeira tentativa, e o aviso de “state.db locked” ainda sendo emitido depois de os locks terem sido liberados (#108082).
  • Um índice de busca corrompido não mata mais o turno. Erros que afetavam apenas o índice de texto completo eram tratados como corrupção do arquivo inteiro e o sistema falhava fechado. Agora eles são classificados como fts_index: a busca degrada, o índice é reconstruído depois, e o transcript fica intacto. O mesmo PR faz o doctor distinguir com honestidade corrupção estrutural de corrupção de índice, adiciona uma sonda de escrita FTS que pega a forma de índice obsoleto em que todas as verificações passam mas toda escrita falha, impede que o .recover deixe de iniciar por causa de tabelas shadow FTS5 órfãs, recupera bases cujo header foi zerado, e faz o polling de analytics do dashboard devolver 503 em vez de 520.000 tracebacks por dia (#108130).
  • Uma única linha ruim não derruba mais o sessions list, o export nem os insights. Um timestamp em TEXT ou uma epoch de 1e30 derrubavam a lista inteira; um marker JSON malformado derrubava o json_extract; mais de 999 ids derrubavam a exclusão em massa e o prune. Agora todo leitor passa por coerce_epoch() — a linha ruim aparece como ? com um WARNING que nomeia a sessão — além de guardas json_valid, listas IN fatiadas e hidratação em lote nos exports (#108086).
  • Sessões não se ligam mais à base de outro profile, nem a leem. A inicialização do backend do desktop podia fixar o state.db do profile errado numa corrida de override do HERMES_HOME; o session_search com um ID cru varria silenciosamente todos os profiles e devolvia conversas de outras pessoas; o guia de recuperação apontava para o arquivo errado; e excluir um profile deixava handles abertos (WinError 32) (#108074).
  • Abrir o state.db não toma mais um lock de escrita quando não há nada a escrever. Um processo hermes avulso abrindo atrás de um gateway ocupado travava de 4 a 20 segundos e então reportava “database is locked”. Agora leva 0,01 segundo (#108067).

Se o seu state.db já foi danificado pela 0.21.0 ou 0.21.1, comece por aqui:

hermes doctor
hermes sessions recover --inspect-only

2. Isolamento entre profiles reforçado

A v0.21.2 transforma a fronteira entre profiles de convenção em algo aplicado: os bots de um profile secundário não herdam mais a allow-list do profile padrão (#107616); os adaptadores não enviam mais credenciais ao host do profile padrão (#107617); servidores MCP em stdio não recebem mais os segredos do vault do profile padrão (#107630); a entrega de MEDIA: não pode mais carregar o .env / auth.json / state.db de outro profile (#107609); callbacks de drive do Feishu e respostas do webhook /p/<profile>/ ficam dentro do profile roteado (#107620, #107626); e um profile secundário não recebe mais o bearer Nous de um profile irmão (#107611).

Resumindo, a regra é simples: se um processo pertence a um profile, ele não alcança arquivos nem segredos de outro profile, nem faz requisições com a identidade de outro.

3. Acabou a tempestade de inicializações de backends no desktop

O Bot Mode iniciava ou discava um backend para cada profile na inicialização e a cada tick do roster; passar o mouse pela lista de Bots iniciava um backend por linha; e trocar de profile podia criar primaries duplicados. Agora a criação e o reúso de backends seguem um ciclo de vida explícito, a renderização do roster não tem efeitos colaterais, e trocar de profile entrega o mesmo primary em vez de uma cópia nova (#108069, #108107, #108118, #108134, #107969, #108112). O que você percebe como usuário é que um cold start do desktop não soa mais como ventoinha decolando e gateway sobrecarregado ao mesmo tempo.

4. Um cofre de credenciais em que o agente não consegue ver

O agente agora consegue fazer login, pagar e preencher endereços a partir do 1Password, do Bitwarden ou do vault local do Hermes sem nunca ver o segredo; códigos de dois fatores vêm de segredos de autenticador salvos, ou são pedidos na sua própria UI (#106480, #107585). Plugins git privados também são instalados com credenciais salvas (#106981). Em outras palavras, os segredos vão do cofre direto para o site ou repositório de destino: o agente orquestra, vê “concluído” ou “falhou”, e nunca o texto em claro.

5. Um catálogo de plugins e uma única página Plugins

Os plugins agora têm um índice revisado com SHA fixado, com CLI, CI de admissão, documentação e dashboard (#69446). O Desktop ganha uma única página Plugins que gerencia plugins de agente e de desktop num só lugar — instalar, navegar pelo catálogo e fixar por commit sem sair dela (#107212, #107314, #107321). O Radio sai como plugin opcional do SDK (#107072).

6. Nível gratuito da Nous e primeira execução guiada

Inferência e conectores gratuitos funcionam de cara, com login em um único comando (#105258, #105260), e o /login funciona direto no chat (#105261); as ferramentas de conector (Gmail, Linear, Notion e outras) são encontráveis via tool_search (#106842); e com HERMES_GUEST_ONBOARDING=1 definido, a primeira execução vira um fluxo guiado que deixa contas, conectores e modelos configurados antes da primeira conversa (#107697, #107958, #107985, #108211).

export HERMES_GUEST_ONBOARDING=1

Melhorias

A v0.21.2 é um patch release: as mudanças abaixo não viram manchete, mas fazem parte do mesmo trabalho de fazer o state.db parar de mentir.

  • Ordem de rebuild e publicação: um state.db recém-criado não publica mais suas tabelas FTS antes de tomar o lock de rebuild (#106311).
  • Gerações de WAL e saída: handles que perderam uma geração de WAL não fazem mais checkpoint de frames obsoletos ao sair (#106315, #106840), e uma base que não pode ser verificada fica intocada durante a inicialização do WAL (#106568).
  • Quarentena em vez de abertura destrutiva: uma base cujo header foi sobrescrito vai para quarentena junto com o seu WAL, em vez de ser aberta de forma destrutiva (#106587), e handles em quarentena recusam VACUUM e FTS optimize (#106343, #106349).

Correções

  • Gateway e plataformas: uma chave display: solta no config.yaml não derruba mais cada turno (#106305); mensagens finais de faixa enfileirada rejeitadas pela plataforma são registradas e reentregues (#106316); um envio de WebSocket travado não bloqueia mais todos os eventos atrás dele (#106581); o primeiro turno não espera mais a sondagem da toolchain de Python (#106556); com bots_require_mention ativo, bots do Telegram precisam ser mencionados com @, o que interrompe o ping-pong entre bots (#106534); o Matrix renderiza LaTeX (#106515); o Signal renderiza tabelas Markdown (#106538); respostas do WhatsApp mantêm a citação em mensagens de visualização única (#106541); respostas só de mídia reportam SUCCESS em todas as plataformas (#106557).
  • Providers e roteamento: o /model e o roteamento automático auxiliar não podem mais faturar um provider que você não escolheu (#107366); o Hermes nunca cai em silêncio para um provider sem credenciais (#107281); modelos Bedrock Claude/Converse/Mantle sobrevivem ao /model, ao fallback e à recuperação (#107621, #107658); as Bedrock Guardrails realmente se aplicam (#107815); um 400 de imagem por orçamento de patch no Codex é retentado com a imagem reduzida (#106525); provider primário sem permissão mais fallback não oscilam mais (#106549); o raciocínio de replay recusado pelo Azure Foundry é classificado e aparado (#106718); um refresh de OAuth do MCP não apaga mais o refresh token (#106185); o cliente da Anthropic envia exatamente uma credencial (#107978); o DeepSeek V4.1 Flash entra nos seletores do Nous Portal e do OpenRouter (#107489); OpenAI e FAL suportam GPT Image 2.5 (#105988); Opus 5 e Fable 5.1 entram no seletor nativo da Anthropic (#106636).
  • Loop do agente e compaction: um callback periódico bloqueado não trava mais o refresh do lease (#106308); um /steer no meio do turno é gravado como linha user própria (#106317, #106344); recusas por limite de memória em inferência local vão para backoff em vez de compactar o histórico (#106307); um estouro de contexto após streaming parcial encerra o turno (#106567); continuações por comprimento param quando o texto anterior já encheu a janela (#106571); a compaction não expira mais em silêncio nos retries de aux (#106866); chaves de model_thresholds podem ser qualificadas por provider (#108061); alternar entre Desktop e TUI não reconstrói mais o system prompt, o que preserva o prompt cache (#105844); a CLI mantém um sidecar api_content para que até a persistência precoce preserve o cache (#105842).
  • CLI, TUI e Desktop: o hermes -z --resume retoma a sessão (#106313); teclas estendidas trazem Shift+letra e Cmd+Shift+Z aos terminais (#90674, #105493); timeouts do browser_exec matam a árvore de processos inteira (#106589); a checagem de atualização consulta a API do GitHub uma vez por dia em vez de rodar um git fetch a cada 30 minutos (#107648); o hermes update informa o motivo real e não trava mais no fetch (#108053); no Desktop, o idioma da UI sobrevive ao reinício de uma atualização (#106476), autorizações OAuth expiradas ganham re-login em um clique (#106965), o modo HUD volta a mostrar a conversa e sempre devolve a janela (#107491, #107423), o backend encerra quando o processo pai do Desktop encerra (#107977), atualizações no Windows param de reportar falhas falsas (#106175, #107183), o WSLg renderiza em GPUs do Windows (#106528) e a configuração rápida por QR do Telegram chega portada do dashboard (#107242).
  • Cron e Kanban: um “run now” fora da hora cheia não cancela mais a próxima execução agendada (#106306); uma execução manual morta não bloqueia mais a próxima janela de 5 minutos (#106733); uma tarefa alterada de única para recorrente continua disparando (#106532); tarefas sem modelo fixado rodam o modelo capturado na criação (#106499); o --clone-all não copia mais tarefas de cron (#106478); o kanban promote recusa uma tarefa pai inacabada (#106550); o kanban_request_review recusa um reviewer profile desconhecido (#106547).
  • Ferramentas e memória: um servidor MCP em stdio que morre no meio da chamada não reexecuta a chamada de ferramenta (#106546); uma revisão de fundo apenas com skills não pode mais apagar entradas de memória (#106310); memórias do mem0 não perdem mais turnos longos (#106542); o tool_search devolve vazio em vez de cinco ferramentas sem relação que compartilham uma palavra (#106676); sudo remoto com NOPASSWD não pede mais aprovação (#107939); leituras de RSS e Reddit não vêm mais ativadas por padrão (#105873).
  • Manutenção: backups do config.yaml são concentrados num único diretório limitado backups/config/ (#106388); o hermes backup mantém apenas os 3 zips mais recentes (#106455); o hermes setup --reset faz backup da config real (#106453); a retenção do debug share no caminho de fallback do dpaste cai para 1 dia (#106531).

Atualização

Instalações existentes se atualizam no lugar:

hermes update

Instalação nova:

curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash

Deploys gerenciados devem ser atualizados pelas próprias ferramentas de deploy, usando a nova tag.

Se o state.db já foi danificado pela 0.21.0 ou 0.21.1: rode primeiro o hermes doctor — ele agora separa corretamente corrupção estrutural de corrupção de índice — e, quando um rebuild não basta, ele aponta para hermes sessions recover --inspect-only (limitado ao profile).

O diff completo está em v2026.9.7…v2026.9.11.

← Hermes Agent Changelog