Pular para o conteúdo principal

Documentação oficial desta página · v0.20.6

Metas persistentes (/goal)

O /goal dá ao Hermes um objetivo permanente, que sobrevive entre turnos. Depois de cada turno, um modelo juiz leve confere se a meta foi cumprida pela última resposta do assistente. Se não foi, o Hermes injeta sozinho um prompt de continuação na mesma sessão e segue trabalhando — até a meta ser atingida, você pausar ou limpar, ou o orçamento de turnos acabar.

É a versão do Hermes para o laço Ralph, inspirada diretamente no /goal do Codex CLI 0.128.0, de Eric Traut (OpenAI). A ideia central — manter uma meta viva entre turnos e não parar até cumprir — é deles. A implementação aqui é independente, adaptada à arquitetura do Hermes.

Quando usar​

Use o /goal em tarefas em que você quer o Hermes iterando sozinho, sem você repetir o pedido a cada turno:

  • "Corrija todo erro de lint em src/ e confirme que o ruff check passa"
  • "Porte o recurso X do repositório Y, com testes, e deixe o CI verde"
  • "Investigue por que os identificadores de sessão às vezes mudam na compressão e escreva um relatório"
  • "Monte uma CLI pequena que renomeia arquivos pela data do EXIF, e teste na pasta fotos/"

Tarefas em que o agente faz um turno e para não precisam do /goal. Ele brilha nas tarefas em que você teria que dizer "continue" três vezes.

Metas ou Kanban?​

O /goal e o Kanban mantêm o Hermes trabalhando sem você repetir o pedido, então é tentador achar que um leva ao outro. Não leva — a fronteira é nítida:

  • O /goal é de sessão única. O laço injeta prompts de continuação nesta conversa, até o juiz dizer que acabou. Definir uma meta nunca cria um cartão no kanban, nunca atribui trabalho a outro perfil e nunca se ramifica. Não há repasse para o quadro, nem implícito.
  • O Kanban é um quadro de muitas tarefas. Cada cartão é despachado ao próprio processo trabalhador, com sessão própria. Cartões, dependências, responsáveis e repasses vivem no quadro — não no /goal.
  • A sobreposição é deliberada, e pequena. Um cartão criado com --goal roda o mesmo motor de continuação estilo Ralph do /goal — mas dentro da sessão daquele cartão. Ele pega emprestado o motor, não o quadro.
Você querUse
Iterar numa tarefa nesta conversa até terminar/goal <texto>
Muitas tarefas independentes, com dependências, repasses ou vários perfisKanban — hermes kanban create …
Um cartão no quadro que deve iterar até cumprir os critériosUm cartão de kanban com --goal
observação

Se você quer trabalho no quadro, ponha lá você mesmo (hermes kanban create …) — o /goal não faz isso por você. O contrário também vale: pausar, retomar ou limpar uma meta nesta conversa nunca cria, reivindica nem move um cartão.

Começando​

/goal Corrija todo teste que falha em tests/hermes_cli/ e garanta que o scripts/run_tests.sh passa naquele diretório

O que você vê:

  1. Meta aceita — ⊙ Goal set (20-turn budget): <sua meta>
  2. Primeiro turno roda — o Hermes começa como se você tivesse mandado a meta numa mensagem normal.
  3. O juiz roda — depois do turno, o modelo juiz decide done ou continue.
  4. O laço dispara, se preciso — em continue, aparece ↻ Continuing toward goal (1/20): <motivo do juiz> e o Hermes dá o passo seguinte sozinho.
  5. Termina — no fim, aparece ✓ Goal achieved: <motivo> ou ⏸ Goal paused — N/20 turns used.

Comandos​

ComandoO que faz
/goal <texto>Define (ou substitui) a meta permanente. Começa o primeiro turno na hora, sem precisar de outra mensagem.
/goal draft <texto>Redige um contrato de conclusão estruturado a partir de um objetivo em linguagem comum, e o define. Veja contratos de conclusão.
/goal showImprime o contrato de conclusão da meta ativa.
/goal ou /goal statusMostra a meta atual, a situação e quantos turnos foram usados.
/goal pausePara o laço de continuação, sem apagar a meta.
/goal resumeRetoma o laço (zerando o contador de turnos).
/goal clearApaga a meta.
/goal wait <pid> [motivo]Estaciona o laço num processo de fundo — ele para de cutucar o agente a cada turno enquanto o processo roda, e retoma sozinho quando ele termina.
/goal unwaitTira a barreira de espera e retoma na hora.
/goal gate add <comando>Acrescenta uma trava de qualidade: um comando de shell que precisa passar antes de a meta poder ser julgada concluída. Veja travas de qualidade.
/goal gate ou /goal gate listLista as travas e se cada uma passou.
/goal gate remove <N>Remove a enésima trava (começando em 1).
/goal gate clearRemove todas as travas.

Funciona igual na CLI e em todas as plataformas de gateway (Telegram, Discord, Slack, Matrix, Signal, WhatsApp, SMS, iMessage, webhook, servidor de API e painel web).

Contratos de conclusão​

Um /goal <texto> simples funciona, mas uma meta vaga gera julgamento vago — o juiz só confere o que você disse querer. A orientação do /goal do Codex faz o mesmo ponto: um objetivo duradouro funciona melhor quando ele diz o que significa pronto, como provar, o que não pode quebrar, o que está no escopo e quando parar. O Hermes adapta isso como um contrato de conclusão opcional, em cima do laço de meta.

Um contrato tem cinco campos, todos opcionais:

CampoSignificado
outcomeO único estado final que precisa ser verdade quando terminar.
verificationO teste, comando ou artefato específico que prova o resultado.
constraintsO que não pode mudar nem regredir.
boundariesQuais arquivos, diretórios, ferramentas ou sistemas estão no escopo.
stop_whenEm que condição o Hermes deve parar e pedir sua opinião.

Com um contrato definido, os dois prompts mudam: o prompt de continuação diz ao agente para mirar na verificação e respeitar as restrições, e o prompt do juiz decide done só quando o critério de verificação foi cumprido com evidência concreta (resultado de comando, trecho de arquivo, saída de teste) — e não com uma afirmação vaga de "parece pronto". Isso aperta diretamente o modo de falha mais comum do /goal: conclusão prematura, ou continuação sem fim, num objetivo mal especificado.

Dois jeitos de definir um contrato​

1. Deixe o Hermes redigir (recomendado — adaptado da dica do Codex de deixar o agente redigir a meta):

/goal draft Migre o serviço de autenticação de cookies de sessão para JWT

O Hermes expande a sua frase num contrato completo, pelo modelo auxiliar goal_judge, define e mostra o resultado, para você revisar ou apertar algum campo. Se o modelo auxiliar não estiver disponível, ele cai numa meta livre — a redação nunca impede a definição.

2. Escreva na mão, com linhas de campo: valor:

/goal Migrar a autenticação para JWT
verify: pytest tests/auth passa
constraints: manter o formato da resposta de /login
boundaries: mexer só em services/auth e nos testes dele
stop when: for preciso migrar o esquema do banco

A primeira linha que não é campo vira o título da meta; os prefixos reconhecidos (verify:, verified by:, constraints:, preserve:, boundaries:, scope:, stop when:, blocked: e outros) preenchem o contrato. Uma meta comum com dois pontos por acaso (Corrigir bug: o analisador perde vírgulas) não é destroçada — só os prefixos conhecidos são extraídos.

Use /goal show para revisar o contrato ativo. Os contratos ficam no SessionDB.state_meta, junto da meta, então sobrevivem ao /resume. Metas antigas, de antes deste recurso, carregam normalmente (sem contrato). Contratos e critérios de /subgoal se combinam: submetas entram no contrato como critérios extras, que o juiz também precisa checar.

Acrescentar critérios no meio: /subgoal​

Com uma meta ativa, dá para acrescentar critérios de aceitação com /subgoal <texto>, sem reiniciar o laço. Cada chamada acrescenta um item numerado; o prompt de continuação que o agente vê no turno seguinte inclui a meta original mais um bloco de "critérios adicionais que a pessoa acrescentou no meio do laço", e o prompt do juiz é reescrito para o veredito considerar todas as submetas — a meta não é dada como concluída até o objetivo original e todas as submetas serem cumpridos.

ComandoO que faz
/subgoal <texto>Acrescenta um critério à meta ativa. Exige uma meta ativa.
/subgoal (sem argumento)Mostra a lista numerada de submetas.
/subgoal remove <N>Remove a enésima submeta (começando em 1).
/subgoal clearApaga todas as submetas, mantendo a meta original.

As submetas ficam gravadas junto da meta, então sobrevivem ao /resume. Definir um /goal <texto> novo substitui a meta e limpa as submetas; o /goal clear faz o mesmo.

Use quando você começa um laço ("corrija os testes que falham") e percebe no meio que também quer "e acrescente um teste de regressão para o bug que você acabou de corrigir" — o /subgoal acrescente um teste de regressão aperta o critério de sucesso sem quebrar o laço em andamento.

Travas de qualidade​

Um contrato deixa o juiz mais rígido, mas o juiz ainda é um modelo lendo prosa. Uma trava de qualidade é mais forte: um comando de shell determinístico, que precisa sair com código 0 antes de a meta poder ser concluída. Inspirado no modo autônomo limitado do Prime-Agent (--autonomous-gate).

/goal Corrija os testes instáveis de sessão
/goal gate add scripts/run_tests.sh tests/hermes_cli/test_goals.py

Como funciona, a cada turno:

  1. As travas rodam antes do juiz. Se alguma falha, o juiz não é chamado — uma trava vermelha é evidência determinística de que a meta não acabou. O código de saída e o fim da saída (últimos 3 KB, mais ou menos) viram o prompt de continuação, então o agente itera contra a falha real, e não contra uma impressão.
  2. Todas passaram, o julgamento é normal. O juiz então decide concluído, continuar ou esperar, como antes.
  3. Espaço de trabalho inalterado, sem repetir. Se uma trava falhou e nada mudou desde então (acompanhado por uma impressão digital do git, do HEAD mais o estado da árvore), ela não roda de novo — a falha registrada é repetida e a contagem de tentativas avança. Um agente empacado não queima tempo repetindo uma suíte vermelha idêntica. Fora de um repositório git, as travas sempre rodam de novo.
  4. As tentativas são limitadas. Cada trava tem 3 tentativas e 5 minutos de tempo limite, por padrão. Quando uma esgota as tentativas, a meta pausa sozinha (como no orçamento de turnos), com uma mensagem dizendo para corrigir na mão, remover a trava ou usar /goal resume.

As travas ficam gravadas com a meta (sobrevivem ao /resume e à compressão de contexto), e o gerenciamento (/goal gate …) é seguro no meio de uma execução no gateway — elas só rodam no limite do turno.

Travas e contratos se combinam: use o contrato para moldar no que o agente mira, e as travas para tornar o "pronto" verificável por máquina. Com os dois definidos, as travas rodam primeiro.

Estacionar num processo de fundo​

Algumas metas dependem de algo que leva minutos e roda sozinho — CI num PR enviado, uma compilação longa, uma matriz de testes, uma publicação, uma espera por limite de requisição. Sem ajuda, o laço cutucaria o agente a cada turno com "já terminou?", puro trabalho à toa.

Isso é tratado automaticamente. A cada turno, o juiz recebe os processos de fundo vivos do agente (o registro de terminal(background=true) — pid, identificador de sessão, comando, tempo de vida, saída recente e qualquer gatilho de watch_patterns ou notify_on_complete), junto da meta e da resposta. Quando o progresso depende mesmo de um deles, o juiz devolve um veredito de wait em vez de continue, e o laço estaciona: os turnos seguintes são pulados (sem chamada de juiz, sem continuação, sem consumir turno) até a espera se resolver — e então retoma normalmente, com o resultado em mãos. O juiz também estaciona por tempo (wait_for_seconds), para esperas de recuo. O /goal status mostra ⏳ Goal (parked …) enquanto estacionado.

O juiz escolhe o tipo de espera pelo sinal do próprio processo:

  • wait_on_session <id> — libera quando o gatilho do próprio processo dispara: ele termina, ou (se foi aberto com watch_patterns) o padrão casa. É esta para um vigia, servidor ou consultador de longa duração, que sinaliza no meio (uma compilação que imprime BUILD SUCCESSFUL e continua rodando, ou um vigia com notify_on_complete) e pode nunca terminar sozinho.
  • wait_on_pid <pid> — libera só quando o processo termina.
  • wait_for_seconds <n> — libera depois de um tempo fixo.

Você não digita nada para isso — é decisão do juiz, tomada com o contexto de processos que o laço entrega. Os comandos manuais existem como sobrescrita:

ComandoO que faz
/goal wait <pid> [motivo]Estaciona o laço até o processo daquele PID terminar.
/goal unwaitTira qualquer barreira (do juiz ou manual) e retoma na hora.

A barreira (por pid ou por tempo) fica gravada com a meta, então sobrevive ao /resume. O /goal pause, o /goal resume e o /goal clear derrubam todas. Se o PID já estava morto quando a barreira foi criada (ou morre enquanto ela existe), ou se o prazo passa, a barreira some na verificação seguinte — uma barreira velha nunca trava o laço.

Fluxo típico: o agente envia um PR, abre um vigia de CI com terminal(background=true, notify_on_complete=true) e diz "acompanhando o CI". O juiz vê o vigia ainda rodando, devolve wait no pid dele, e o laço fica quieto — e volta no instante em que o CI termina, julgando a meta contra o resultado real.

Detalhes de comportamento​

O juiz​

Depois de cada turno, o Hermes chama um modelo auxiliar com:

  • o texto da meta permanente
  • a última resposta final do agente (uns 4 KB de texto)
  • um prompt de sistema pedindo uma resposta em JSON estrito, de uma linha: {"verdict": "done" | "continue" | "wait", "reason": "<uma frase de justificativa>"} (vereditos de espera acrescentam wait_on_session, wait_on_pid ou wait_for_seconds; o formato antigo {"done": <bool>, "reason": "..."} ainda é aceito)

O juiz é conservador de propósito: ele marca done só quando a resposta confirma explicitamente que a meta terminou, quando a entrega final está claramente pronta, ou quando a meta é inatingível ou está bloqueada (tratada como concluída, com um motivo de bloqueio, para não queimar orçamento em tarefa impossível).

Falha aberta​

Se o juiz der erro (soluço de rede, resposta malformada, cliente auxiliar indisponível), o Hermes trata o veredito como continue — um juiz quebrado nunca trava o progresso. O orçamento de turnos é a rede de segurança de verdade.

Orçamento de turnos​

O padrão é 20 turnos de continuação (goals.max_turns, no config.yaml). Ao atingir o teto, o Hermes pausa sozinho e diz como seguir:

⏸ Goal paused — 20/20 turns used. Use /goal resume to keep going, or /goal clear to stop.

O /goal resume zera o contador, então dá para seguir em blocos medidos.

Suas mensagens sempre têm prioridade​

Qualquer mensagem de verdade que você mande com uma meta ativa passa na frente do laço de continuação. Na CLI, ela entra em _pending_input antes da continuação enfileirada; no gateway, passa pela fila do adaptador do mesmo jeito. O juiz roda de novo depois do seu turno — então, se a sua mensagem por acaso cumprir a meta, o juiz percebe e para.

Segurança durante a execução (gateway)​

Com o agente já rodando, o /goal status, o /goal pause, o /goal clear, o /goal wait e o /goal unwait são seguros — eles mexem só no estado de controle e não interrompem o turno atual. Definir uma meta nova no meio (/goal <texto novo>) é recusado, com uma mensagem pedindo /stop antes, para a continuação antiga não competir com a nova.

Persistência​

O estado da meta fica no SessionDB.state_meta, sob a chave goal:<id_da_sessão>. Ou seja, o /resume pega de onde você parou — defina uma meta, feche o notebook, volte amanhã, dê /resume, e a meta continua exatamente como estava (ativa, pausada ou concluída).

Cache de prompt​

O prompt de continuação é uma mensagem comum de usuário, anexada ao histórico. Ele não altera o prompt de sistema, não troca conjunto de ferramentas e não mexe na conversa de nenhum jeito que invalide o cache. Rodar uma meta de 20 turnos custa, em cache, o mesmo que 20 turnos de conversa normal.

Configuração​

Acrescente ao ~/.hermes/config.yaml:

goals:
# Máximo de turnos de continuação antes de o Hermes pausar sozinho e pedir
# um /goal resume. Padrão 20. Diminua para laços mais curtos; aumente para
# refatorações longas.
max_turns: 20

Escolher o modelo do juiz​

O juiz usa a tarefa auxiliar goal_judge. Por padrão, ela cai no seu modelo principal (veja Modelos auxiliares). Para mandar o juiz a um modelo barato e rápido, e reduzir custo:

auxiliary:
goal_judge:
provider: openrouter
model: google/gemini-3-flash-preview

A chamada do juiz é pequena (uns 200 tokens de saída) e roda uma vez por turno, então um modelo barato e rápido costuma ser a escolha certa.

Exemplo completo​

Você: /goal Crie quatro arquivos /tmp/note_{1..4}.txt, um por turno, cada um contendo o próprio número

⊙ Goal set (20-turn budget): Crie quatro arquivos /tmp/note_{1..4}.txt, um por turno...

Hermes: Criando /tmp/note_1.txt agora.
💻 echo "1" > /tmp/note_1.txt (0.1s)
Criei /tmp/note_1.txt com o conteúdo "1". Sigo com os demais no próximo turno, como você pediu.

↻ Continuing toward goal (1/20): Only 1 of 4 files has been created; 3 files remain.

Hermes: [Continuing toward your standing goal]
💻 echo "2" > /tmp/note_2.txt (0.1s)
Criei /tmp/note_2.txt. Faltam dois.

↻ Continuing toward goal (2/20): 2 of 4 files created; 2 remain.

Hermes: [Continuing toward your standing goal]
💻 echo "3" > /tmp/note_3.txt (0.1s)
Criei /tmp/note_3.txt.

↻ Continuing toward goal (3/20): 3 of 4 files created; 1 remains.

Hermes: [Continuing toward your standing goal]
💻 echo "4" > /tmp/note_4.txt (0.1s)
Os quatro arquivos estão criados, de /tmp/note_1.txt a /tmp/note_4.txt, cada um com o número.

✓ Goal achieved: All four files were created with the specified content, completing the goal.

Você: _

Quatro turnos, uma invocação de /goal, zero "continue" da sua parte.

Quando o juiz erra​

Nenhum juiz é perfeito. Dois modos de falha para observar:

Falso negativo — o juiz manda continuar, mas a meta já foi cumprida. O orçamento de turnos pega isso. Você vê ⏸ Goal paused e pode dar /goal clear, ou simplesmente mandar outra mensagem.

Falso positivo — o juiz diz que acabou, mas ainda falta trabalho. Você vê ✓ Goal achieved e sabe que não. Mande uma mensagem de continuação, ou redefina a meta com mais precisão: /goal <texto mais específico>. O prompt do juiz é conservador de propósito, para os falsos positivos serem mais raros que os falsos negativos.

Se um veredito parecer pouco convincente, o texto do motivo na linha ↻ Continuing toward goal ou ✓ Goal achieved diz exatamente o que o juiz viu. Isso costuma bastar para diagnosticar se o texto da meta estava ambíguo, ou se a resposta do modelo estava.

Atribuição​

O /goal é a versão do Hermes para o padrão do laço Ralph. O desenho voltado ao usuário — manter uma meta viva entre turnos, não parar até cumprir, com controles de criar, pausar, retomar e limpar — foi popularizado e publicado no Codex CLI 0.128.0, por Eric Traut, do time do Codex na OpenAI. A implementação aqui é independente (registro central de CommandDef, persistência em SessionDB.state_meta, juiz por cliente auxiliar, continuação pela fila do adaptador no gateway), mas a ideia é deles. Crédito a quem tem crédito.