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 oruff checkpassa" - "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
--goalroda 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ê quer | Use |
|---|---|
| Iterar numa tarefa nesta conversa até terminar | /goal <texto> |
| Muitas tarefas independentes, com dependências, repasses ou vários perfis | Kanban — hermes kanban create … |
| Um cartão no quadro que deve iterar até cumprir os critérios | Um cartão de kanban com --goal |
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ê:
- Meta aceita —
⊙ Goal set (20-turn budget): <sua meta> - Primeiro turno roda — o Hermes começa como se você tivesse mandado a meta numa mensagem normal.
- O juiz roda — depois do turno, o modelo juiz decide
doneoucontinue. - 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. - Termina — no fim, aparece
✓ Goal achieved: <motivo>ou⏸ Goal paused — N/20 turns used.
Comandos
| Comando | O 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 show | Imprime o contrato de conclusão da meta ativa. |
/goal ou /goal status | Mostra a meta atual, a situação e quantos turnos foram usados. |
/goal pause | Para o laço de continuação, sem apagar a meta. |
/goal resume | Retoma o laço (zerando o contador de turnos). |
/goal clear | Apaga 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 unwait | Tira 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 list | Lista as travas e se cada uma passou. |
/goal gate remove <N> | Remove a enésima trava (começando em 1). |
/goal gate clear | Remove 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:
| Campo | Significado |
|---|---|
outcome | O único estado final que precisa ser verdade quando terminar. |
verification | O teste, comando ou artefato específico que prova o resultado. |
constraints | O que não pode mudar nem regredir. |
boundaries | Quais arquivos, diretórios, ferramentas ou sistemas estão no escopo. |
stop_when | Em 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.
| Comando | O 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 clear | Apaga 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:
- 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.
- Todas passaram, o julgamento é normal. O juiz então decide concluído, continuar ou esperar, como antes.
- 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.
- 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 comwatch_patterns) o padrão casa. É esta para um vigia, servidor ou consultador de longa duração, que sinaliza no meio (uma compilação que imprimeBUILD SUCCESSFULe continua rodando, ou um vigia comnotify_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:
| Comando | O que faz |
|---|---|
/goal wait <pid> [motivo] | Estaciona o laço até o processo daquele PID terminar. |
/goal unwait | Tira 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 acrescentamwait_on_session,wait_on_pidouwait_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.