Hermes Agent v0.20.3
Visão Geral
v0.20.3 — O Patch da Resiliência. Lançada em 16 de agosto de 2026. ~125 PRs mesclados · ~250 commits · ~461 arquivos alterados (+42.613 / −1.641) desde a v0.20.2.
Um dia depois do Patch das Conexões, esta release responde a uma pergunta mais silenciosa: o que acontece quando sua automação para de funcionar em silêncio e nada te avisa? O agendador de cron agora sobrevive à exaustão de file descriptors, reconcilia claims obsoletos contra o ledger de execuções, re-arma jobs recorrentes travados e faz o catch-up de disparos perdidos de providers externos — enquanto o last_fire_error torna cada falha visível no CLI, no dashboard e na saída das próprias ferramentas do agente. Ao redor disso: a migração para o SDK MCP 2.x com suporte ao protocolo stateless de 2026-07-28, o CommandCode como provider de primeira classe, o /worktree inspirado no Copilot-CLI e o /rollback seguro, o endurecimento da propriedade do runtime Python de subprocessos e correções de perda de dados no handoff de sessões.
Esta é uma release de patch, então as notas oficiais são breves e a documentação completa e curada acompanha a v0.21.0. Esta página cobre as partes mais valiosas desta janela.
Destaques
1. O agendador de cron se cura sozinho
Três modos de falha por travamento silencioso que costumavam deixar jobs mortos por horas — enquanto tudo “parecia saudável” — agora se curam sozinhos:
- EMFILE (exaustão de file descriptors): o
tick()costumava engolir todoOSErrorcomo “outra instância segurando o lock”, então uma exaustão de fd no arquivo de lock era registrada como um tick bem-sucedido e nenhum job voltava a rodar. O errno de aquisição do lock agora é classificado: apenas contenção genuína é ignorada em silêncio, falhas reais se propagam como um tick com erro, e o ticker tenta recuperar fds com o melhor esforço (gc.collect()+ elevação do limite soft de nofile) com backoff exponencial limitado a 15 minutos (#88335, baseado em #87796 de @webtecnica). - Claims em voo obsoletos: um claim vazado com idade dentro da janela (2×intervalo, 30 min) costumava travar um job recorrente até um operador intervir. A varredura agora reconcilia contra o ledger durável de execuções: se a linha terminal da execução prova que ela terminou, o claim é liberado à força — com uma proteção para que um claim novo nunca seja confundido com o resultado concluído da execução anterior (#88343, baseado em #87259).
- Estado de erro persistido travado: um job recorrente com
last_status=errorenext_run_atestacionado no futuro era invisível para toda varredura e sobrevivia a reinícios do gateway. Agora ele é re-armado automaticamente no próximo tick — e o re-arm respeita a legalidade do agendamento, então uma expressão de cron só de dias úteis nunca dispara em um sábado (#88339, baseado em #87261).
2. Disparos perdidos ficam visíveis — e fazem catch-up
O incidente em produção de 14 de agosto de 2026 (4 falhas noturnas consecutivas, nenhuma evidência além de uma linha de log) gerou duas correções duráveis. Primeiro, quando o caminho de disparo hospedado não alcança o gateway, o job recebe um carimbo last_fire_error exibido em cronjob list, hermes cron list (linha vermelha ⚠ Missed scheduled fire:) e no dashboard; uma execução bem-sucedida o limpa, então o carimbo sempre descreve a saúde atual (#88555). Segundo, providers de cron externos (Chronos / cron gerenciado hospedado) agora têm catch-up de misfire: quando um disparo nunca chega e os retries se esgotam, o gateway detecta o job atrasado e o executa localmente após um período de graça — cron.misfire_grace_minutes (padrão 10, ≤0 desativa). A interrupção custa minutos em vez de um dia silenciosamente perdido (#88563).
3. MCP: SDK 2.x + o protocolo stateless de 2026-07-28
O Hermes migrou para o SDK MCP 2.x (#88180) e agora fala o protocolo stateless de 2026-07-28 de ponta a ponta (#88299). Servidores sem handshake de initialize conectam sem configuração via um único ponto de convergência _negotiate_session() nos quatro pontos de chamada de transporte (stdio, SSE, HTTP novo, HTTP legado). Chave protocol por servidor: auto (padrão) tenta o handshake legado primeiro e faz fallback para server/discover quando o servidor o rejeita — zero round-trips extras para a frota existente; stateless sonda discover primeiro; legacy desativa o fallback. Os hints ttlMs/cacheScope do SEP-2549 vindos de tools/list são capturados no cache de schemas com expiração por TTL, e o registro OAuth segue a nova especificação (application_type nativo, validação de iss conforme RFC 9207).
4. Novos providers: CommandCode (e Muse Spark no main)
CommandCode (commandcode.ai) agora é um provider de primeira classe — perfis commandcode (OpenAI chat completions) e commandcode-anthropic (Anthropic Messages, auth Bearer) por trás de uma única COMMANDCODE_API_KEY, cobrindo os planos GOAT/Pro/Max/Provider (~30+ modelos abertos e fechados, descoberta ao vivo via endpoint público /provider/v1/models) (#88308, resgatando a #32909). No main (pós-tag), a Meta Model API (Muse Spark) entra como plugin embutido: --provider meta-ai funciona de imediato com MODEL_API_KEY (aliases META_API_KEY/META_MODEL_API_KEY, override META_BASE_URL) e um catálogo muse-spark-1.2 / muse-spark-1.2-contributor (#88565).
5. /worktree e /rollback seguro — edições do agente que você pode desfazer
Dois comandos inspirados no Copilot-CLI chegam nesta janela. /worktree new [name] cria um worktree git isolado no meio da sessão (.worktrees/ dentro do repositório, branch baseada na ponta remota recém-buscada, worktree_sync respeitado) e redireciona as ferramentas de terminal e de arquivo da sessão para ele — sem reiniciar; /worktree mostra a árvore ativa e /worktree list as lista, com a mesma limpeza de saída do hermes -w, que mantém o worktree se houver commits não enviados. /rollback agora tem como padrão a restauração segura: um ledger por projeto das escritas feitas pelo agente (sha256 de cada write_file/patch aplicado) permite reverter apenas o que o agente mudou, apagar arquivos criados pelo agente e preservar suas edições manuais; --all/--force restaura tudo, e os arquivos ignorados são reportados com uma dica.
6. Propriedade do runtime Python de subprocessos
execute_code e companhia agora são donos do ambiente Python dos seus subprocessos: PYTHONHOME/PYTHONPATH são compostos a partir do runtime gerenciado, em vez de herdados contaminados do shell pai — fechando uma classe de surpresas do tipo “funciona no meu terminal, quebra no agente” e endurecendo a fronteira para código não confiável.
7. Correções de perda de dados no handoff de sessões
Dois bugs de perda de dados relatados por usuários foram corrigidos (#88244). Uma corrida CLI→gateway após /handoff telegram podia finalizar a linha da sessão que o gateway ainda gravava, fazendo toda a etapa do handoff sumir do histórico e do session_search; o CLI agora rastreia os ids das sessões com handoff concluído e pula a finalização de limpeza. Separadamente, um state.db corrompido que bloqueava todas as mensagens agora é exposto ao usuário: o gateway transmite orientações de recuperação (incluindo hermes doctor --fix e sqlite3 .recover) para os canais principais em vez de enterrar a falha nos logs.
Melhorias
- Varredura de segurança na instalação/atualização de plugins (inspirada no Claude-Cowork): instalações são escaneadas em busca de conteúdo suspeito antes da ativação.
- Arquivos de texto UTF-16 são lidos com transcodificação para UTF-8 (port de MoonshotAI/kimi-code#2647); os IDs de chamadas de ferramenta do Gemini 3 são preservados entre reescritas de adaptadores (port de earendil-works/pi#7494).
- Auto-recuperação de worktrees git: uma adição de worktree
hermes -wque falha ou estoura o timeout se limpa sozinha (diretório parcial, entrada admin LOCKED, branch órfã), e a passagem de manutenção na inicialização repacka quando os packs se proliferam — os 39 packs (638 MB) do incidente de agosto viraram 2 (287 MB), e a criação de worktree caiu de um timeout de 30s para 0,5s (#88306). - Contratos de runtime do Cua Driver 0.20: o computer use verifica e auto-repara um driver instalado que falha no contrato de runtime na atualização e em execução (família #87646).
- Desktop: a renderização do DiffusionCanvas é limitada (política de pausa, orçamento de 15fps, limite de instâncias), a animação do pixel-egg em idle dorme, os chats em grupo do Bot Mode renderizam Markdown e desktops de gateways remotos não mostram mais um default local fantasma (#88564, #88406, #88553, #88554).
- Delegate: o trabalho não commitado de um subagente é preservado quando a inspeção de git falha, e os pais são informados quando um worktree foi preservado sem inspeção.
Correções
- Corrida
/handoffCLI→gateway que perdia a etapa do handoff (#88234); corrupção do state.db agora exposta com orientações de recuperação (#88235). - Matrix: nomes de arquivos de mídia em branco vindos de corpos
m.audio/m.file/m.video; o Telegram prefere IPs IPv4 da API e registra o stick de primeira escolha como info. - Cron: o
run_claimé limpo para jobs one-shot em caso de falha de dispatch; a remediação de drift é direcionada a pins de propriedade do usuário. - Compressão: uma rotação abortada não aumenta mais o arquivo pai que não conseguiu publicar.
- Desktop: o hold de settle pré-início não trava mais o composer; um arm de restauração/edição mantém o composer utilizável.
Atualização
hermes update
Após atualizar, execute hermes doctor para verificar a instalação e reinicie o gateway (hermes gateway) para que as mudanças de plataforma entrem em vigor. Se você usa um provider de cron externo, confira hermes cron list uma vez para confirmar que o last_fire_error não mostra nada pendente.