Você já paga por um pensamento que não precisa: reasoning effort em todo seletor de modelo do Hermes

São 23h30 e você pede ao Hermes para renomear formatTs para formatTimestamp em utils/date.ts. Ele termina em sete segundos — e o trace cobra alguns milhares de tokens de pensamento em ultra reasoning effort. O modelo não é o problema. “Ultra” é um default global que você definiu na semana passada para uma revisão de arquitetura, e ninguém tocou nele desde então. O Hermes sempre deixou você ajustar o reasoning effort; os controles é que estavam espalhados entre /reasoning, config.yaml e um submenu do Desktop que só aparecia no hover. Saber que o recurso existe e realmente usá-lo eram dois grupos distintos de pessoas.
Isso mudou com a PR #110346: todo seletor de modelo agora pede o nível de effort logo depois que você escolhe o modelo. Este guia percorre os seis lugares onde você pode definir o effort (execução avulsa, sessão, o flag do /model, os seletores interativos, hermes model e o Desktop), além da precedência entre eles — para que você pague pelo pensamento que uma tarefa exige, não pelo pensamento que você configurou na semana passada.
O que o reasoning effort controla de fato
Reasoning effort é o orçamento de pensamento que um modelo tem permissão de gastar antes de responder. Para modelos que expõem o controle, o nível é traduzido nos parâmetros de thinking/reasoning da requisição; para modelos que não expõem, a configuração é simplesmente inerte.
Existe exatamente uma fonte de verdade para a escada, em hermes_constants.py:
VALID_REASONING_EFFORTS = ("minimal", "low", "medium", "high", "xhigh", "max", "ultra")
Sete níveis, do mais baixo ao mais alto. parse_reasoning_effort() transforma uma palavra digitada em um dict de config: um nível reconhecido vira {"enabled": True, "effort": "<level>"}, uma string vazia ou uma palavra não reconhecida retorna None (ou seja, “use o default do provider”), e none é um desligamento explícito — reasoning_effort: false e none significam ambos “não pense”.
O ponto importante: isso vale por requisição. No mesmo modelo, a diferença de qualidade entre low e ultra costuma ser bem menor que a diferença de latência e custo. Então a pergunta real nunca é “qual nível é o melhor” — é “quantos níveis esta tarefa merece”.
| Escopo | Como você define | Onde isso fica |
|---|---|---|
| Apenas uma execução | hermes --reasoning low -z "..." |
aquele processo, nada gravado |
| Sessão atual (CLI clássico) | /reasoning high |
override da sessão |
| Sessão atual, com troca de modelo | /model X --reasoning high |
pin da sessão |
| Seu default global | /reasoning high --global |
agent.reasoning_effort |
| Todo modelo que você nomear | agent.reasoning_overrides |
por modelo, vence o default global |
| Uma tarefa auxiliar | hermes model → Configure auxiliary models… |
auxiliary.vision.reasoning_effort |
| Todo subagent | delegation.reasoning_effort |
o bloco delegation |
| Um chat no Desktop | a pill de reasoning do composer | aquela sessão |
A alavanca menor: execuções one-shot
Se você está rodando um único comando para um trabalho bem compreendido, não precisa mexer em config nenhuma. O flag --reasoning de nível superior existe exatamente para isso:
# One-shot: um rename. Low dá e sobra.
hermes --reasoning low -z "rename formatTs to formatTimestamp in utils/date.ts"
# Interativo, mas esta sessão está arrumando anotações bagunçadas
hermes chat --reasoning high
O texto de ajuda é explícito: isso sobrescreve o effort efetivo apenas para aquela execução; o nível persistente continua em config.yaml (ou por modelo, em agent.reasoning_overrides). Para scripts shell, jobs de CI e trabalho em lote com arquivos, é a opção mais limpa: o effort viaja junto com o comando em vez de virar discretamente o default de amanhã.
Sessões: /reasoning e /model --reasoning
No CLI clássico, /reasoning é o comando dedicado — ele cuida tanto do nível de effort quanto de como o reasoning é exibido:
/reasoning high # apenas esta sessão
/reasoning high --global # grava agent.reasoning_effort para execuções futuras
/reasoning # sem argumento: escolher interativamente
/reasoning show # mostrar/ocultar o stream de reasoning (full imprime tudo)
/reasoning none # desliga o reasoning
A PR #110346 fez da troca de modelo e da definição de effort um único gesto. O parser do /model agora aceita --reasoning <level>, então uma só requisição carrega a escolha do modelo e o effort dele:
/model openrouter/anthropic/claude-opus-4.8 --reasoning high
Três detalhes que aparecem o tempo todo:
- O escopo acompanha a troca de modelo. Sessão por padrão;
--globalgravaagent.reasoning_effort;--oncecaptura o valor atual, aplica o effort por um único turno e o restaura depois. - O effort é aplicado depois da troca de agent. Isso não é detalhe bobo: o caminho da troca resolve o
reasoning_configde novo a partir doconfig.yaml, então gravar o effort primeiro seria sobrescrito. A ordem é deliberada. - Um nível inválido gera erro em vez de não fazer nada em silêncio.
/model --reasoning turboretorna/model --reasoning takes none, minimal, low, medium, high, xhigh, max or ultra.
Você também pode dispensar os flags por completo. O seletor interativo do /model agora tem três etapas — provider, modelo e uma terceira etapa intitulada Reasoning effort for <model> que lista a escada inteira, mais uma linha none (desabilitar o reasoning) e uma linha “manter o atual”. Quando o mapa de capacidades da rota diz que não há controle de reasoning, essa terceira etapa fica oculta em vez de oferecer um botão que não faz nada.
A TUI Ink (hermes --tui) roda o mesmo fluxo de três etapas; a etapa 3 é rotulada Reasoning effort (step 3/3) e emite modelo, provider, effort e escopo como um único comando de gateway. Em plataformas de mensageria (Telegram, Slack e companhia), /model --reasoning passa pelo mesmo aplicador que o /reasoning usa, então os dois não conseguem divergir.
hermes model: o passo de effort para o modelo principal e cada tarefa auxiliar
hermes model é o ponto de entrada que a maioria das pessoas usa primeiro (veja a referência do hermes model). Antes da PR #110346, ele perguntava sobre effort apenas em rotas Copilot, e o fluxo de auxiliares nunca perguntava nada.
Agora:
- Depois que o modelo principal é salvo, um passo compartilhado vem em seguida: os sete níveis, Disable reasoning e Skip para manter o valor atual. Modelos que o catálogo marca como sem controle de reasoning pulam essa etapa.
- A lista de providers ganhou uma linha Reasoning effort for the current model… para quando você quer mudar apenas o effort.
- Configure auxiliary models… (provider → modelo) termina com o mesmo passo de effort, mais uma linha Provider default que deixa o nível a cargo do provider. Esses valores são guardados como
auxiliary.<task>.reasoning_effort, oudelegation.reasoning_effortno caso da delegação. - A lista de tarefas mostra o nível ali mesmo, por exemplo
openrouter · model · high, e Reset all to auto limpa todos os overrides de uma vez. - Blocos que deliberadamente não têm essa chave — os slots do MoA e
memory_query_rewrite— pulam a etapa. Não faz falta: eles apenas configuram profundidade em outro lugar.
Por que isso importa mais do que parece: compressão, geração de título e checagens de aprovação rodam em todo turno. Baixar essas tarefas de high para minimal (ou desligá-las) economiza mais dinheiro do que ajustar o nível do modelo principal jamais vai economizar.
Desktop: a pill do composer e o effort por tarefa em Settings
O seletor de modelo do Desktop fica no composer, logo à esquerda do microfone. Antes da PR #109907, o único controle de effort era um submenu no hover dentro de uma linha de modelo; a pill combinada exibia Deepseek V4 Flash · Med, os usuários liam aquilo como “este modelo só faz medium”, e o submenu continuava sem ser descoberto.
Agora o effort tem seu próprio affordance:
- Uma pill de reasoning ao lado da pill de modelo mostra o nível realmente em vigor nesta superfície (primeiro o valor da sessão, senão o default da config) e abre diretamente as linhas Thinking / Fast / Effort. Ela se oculta quando o catálogo reporta
reasoning: falsepara o modelo ativo, e permanece visível enquanto as capacidades ainda são desconhecidas, para nunca piscar durante o fetch do catálogo. - A pill de modelo não dobra mais o effort no próprio rótulo; cada controle diz uma coisa só.
O effort por tarefa do lado do Desktop precisou de mais duas PRs. A #110435 adicionou um select Reasoning em cada linha em Settings → Model → Auxiliary models: inherit · main model effort (o default, que remove o override daquela tarefa), Off, ou um nível — gravando a mesma chave auxiliary.<task>.reasoning_effort que o hermes model grava. O contrato de API por trás disso vale conhecer: omitir o campo deixa o override como está, passar um null explícito o limpa (volta a herdar), passar um nível o define. Um valor desconhecido como turbo retorna um 400 listando todos os níveis aceitos, em vez de ser jogado no lixo.
A PR #110535 fechou o ciclo dos pins de auxiliares no Desktop: todos os 11 slots podem receber pin, salvar configurações não relacionadas não reescreve nem derruba mais esses pins (as escritas de config passaram a ser por seção, em vez de gravar de volta no disco um snapshot totalmente expandido), e quando uma tarefa de revisão é encaminhada para outro modelo, o reasoning effort dela é respeitado em vez de ser engolido pela configuração da sessão pai.
Uma pegadinha: o app Desktop lembra localmente um preset de effort/fast por modelo. Isso é uma conveniência do app e não muda crons nem subagents — para esses, use hermes model ou o arquivo de config.
Como as camadas se empilham e onde model_overrides se encaixa
Precedência, do mais forte para o mais fraco (é também a ordem de resolução em runtime): override de sessão (/reasoning --session, /model --reasoning) → override por modelo agent.reasoning_overrides → default global agent.reasoning_effort. Um config.yaml para copiar:
agent:
# O default global; é a linha que `/reasoning high --global` grava
reasoning_effort: medium
# Por modelo: as chaves toleram variação de escrita (exata, pontos/traços
# intercambiáveis, prefixo de provider opcional), a primeira correspondência vence,
# e ela bate o default acima.
# Não há suporte a `hermes config set` para esta chave — edite o YAML direto.
reasoning_overrides:
"openrouter/anthropic/claude-opus-4.8": high
"deepseek/deepseek-v4-flash": low
auxiliary:
compression:
reasoning_effort: minimal # resumir histórico não exige pensamento profundo
title_generation:
reasoning_effort: none # títulos: simplesmente desligue
vision:
reasoning_effort: "" # vazio = default do provider
delegation:
reasoning_effort: low # subagents; deixe vazio para herdar do pai
model_overrides tem outro papel aqui (veja o guia de model_overrides): é onde vivem os metadados de modelo — context_window, supports_vision, supports_reasoning e afins. Ele não define o effort, mas decide se o controle de effort existe: quando o mapa de capacidades diz que uma rota não tem controle de reasoning, o passo do hermes model, a terceira etapa do seletor /model e a pill do Desktop se ocultam todos juntos. Então, se você está em um modelo local ou novíssimo que o catálogo nunca ouviu falar, declare as capacidades primeiro e os controles de effort vão aparecer.
Duas exceções que vale internalizar:
background_review.reasoning_efforté ignorado enquanto a revisão fica no modelo principal. Nesse caso o fork herda a config de reasoning da conversa palavra por palavra, que é o que mantém os bytes da requisição dele no prefixo de prompt-cache do pai. Para ter um modelo e um effort diferentes, defina também o provider/model da revisão — caso contrário, o Hermes te avisa uma vez, de propósito.- O effort do MoA é configurado por slot dentro do preset, não no bloco auxiliary:
moa.presets.<name>.reference_models[].reasoning_efforteaggregator.reasoning_effort. Cada referência pode rodar na própria profundidade e o aggregator pode ir mais fundo — é por isso que os blocos do MoA não têm chavereasoning_effort, por design.
Uma configuração inicial que se paga sozinha
Se você prefere não guardar toda a cadeia de precedência na cabeça, faça estas cinco coisas:
- Deixe o modelo principal em
medium. Suba o nível para uma tarefa específica com/model ... --reasoning highem vez de editar o default global. - Rode
hermes model→ Configure auxiliary models… e coloque compression emminimale title_generation desligada. Elas rodam a cada turno, então se pagam imediatamente. - Defina
delegation.reasoning_effort: low. Subagents normalmente executam uma tarefa que já foi decomposta; eles não precisam replanejá-la. - Use
hermes --reasoning low -z "..."para scripts e trabalhos one-shot, para que uma necessidade temporária nunca vire um default permanente. - Se uma execução longa empacar, verifique o orçamento de turnos antes de recorrer a mais pensamento — é sobre isso o guia de max_turns. E em rotas de plano gratuito, a configuração sem API key combina bem com
minimal.
A versão curta
Reasoning effort não é um botão de ajuste em que “mais alto é melhor”; é um problema de escopo. Em um único config.yaml você tem botões separados para a sessão, por modelo, por tarefa auxiliar e por subagent. A PR #110346 levou esses botões para os seletores que você já usa — o que resta é decidir quantos níveis cada trabalho merece, para que aquela revisão do mês passado pare de pagar tarifa ultra por um rename deste mês.