Quem pode falar com o teu agente: allowlists, pairing e o decline nas DMs

Por SkyNet · 4 de outubro de 2026

Montar um bot é a parte fácil. A pergunta que vem logo a seguir é mais chata: quem é que pode falar com ele? Deixá-lo aberto é entregar as ferramentas, a memória e o acesso à tua máquina a qualquer estranho que descubra o username; fechá-lo mal é perder o próprio caso de uso. O Hermes separa isto em duas decisões. Primeiro, uma allowlist decide quem entra. Depois, um comportamento por plataforma decide o que acontece a quem fica de fora. Na v0.21.4 (tag v2026.9.21) essa segunda camada ganhou uma terceira opção, o decline, e foi isso que me fez pegar neste tema.

Sem allowlists, a porta está fechada

A predefinição é dura e vale a pena sabê-la de cor: sem allowlists configuradas e sem GATEWAY_ALLOW_ALL_USERS, o gateway nega toda a gente. No arranque lá está o aviso, em inglês:

No user allowlists configured. All unauthorized users will be denied.
Set GATEWAY_ALLOW_ALL_USERS=true in ~/.hermes/.env to allow open access,
or configure platform allowlists (e.g., TELEGRAM_ALLOWED_USERS=your_id).

As allowlists vivem no ~/.hermes/.env, uma por plataforma, com os IDs separados por vírgulas:

TELEGRAM_ALLOWED_USERS=123456789,987654321
DISCORD_ALLOWED_USERS=111222333444555666
WHATSAPP_ALLOWED_USERS=15551234567
SLACK_ALLOWED_USERS=U01ABC123
GATEWAY_ALLOWED_USERS=123456789      # transversal a todas as plataformas
DISCORD_ALLOW_ALL_USERS=true         # allow-all por plataforma (cuidado)
GATEWAY_ALLOW_ALL_USERS=true         # allow-all global (extremo cuidado)

O GATEWAY_ALLOWED_USERS poupa-te repetir o mesmo ID em três sítios. Os dois ALLOW_ALL são o interruptor que abre tudo: bons numa máquina de testes, péssimos num bot exposto. O allow-all global também pode viver no config.yaml, como gateway.allow_all_users: true; o gateway re-deriva o valor a cada arranque, portanto voltar a false fecha a porta, e uma variável de ambiente explícita ganha sempre — com um aviso em log a apontar o ficheiro que concedeu o acesso. Num gateway multi-perfil, um perfil secundário tem de pôr o GATEWAY_ALLOW_ALL_USERS no seu próprio .env.

Pair, ignore ou decline

Para quem fica de fora, o gateway tem três respostas, escolhidas no config.yaml:

unauthorized_dm_behavior: pair      # o default nos chats

whatsapp:
  unauthorized_dm_behavior: ignore  # a secção da plataforma sobrepõe-se
  • pair — a DM desconhecida recebe um código de emparelhamento de oito caracteres, que tu aprovas depois pela linha de comandos. É o default e faz sentido: transforma um estranho em utilizador autorizado sem tu teres de saber o ID dele de antemão.
  • ignore — a mensagem é descartada em silêncio. Tu recebes o ID do remetente no log (nível WARNING) e, uma vez por remetente, no canal home. Nada volta para quem escreveu.
  • decline — uma recusa educada, uma só. O Hermes responde à primeira mensagem e depois ignora tudo o resto daquele remetente durante 24 horas.

O decline é a novidade e é o que faltava no meio. O pair manda um código a qualquer desconhecido, mesmo a quem só te quer vender alguma coisa; o ignore deixa quem já te conhece a achar que o bot morreu. O decline responde o suficiente para a pessoa perceber que ali não há conversa, sem lhe entregar um código de acesso. A dedupe é por par (plataforma, remetente), gravada em ~/.hermes/pairing/_declined.json — no máximo uma recusa por pessoa por dia, para o bot também não responder a cada mensagem de quem insista.

O texto da recusa está em inglês

Aqui está a parte que me irrita. O texto por omissão do decline é este:

Hi! I'm a personal assistant and can only chat with my owner, so I can't help you directly. Sorry!

Se escreves em português, define unauthorized_dm_decline_message com um texto teu. Outro pormenor que convém saber: o carimbo da recusa é escrito antes do envio, para uma falha de entrega não virar uma tempestade de recusas na mensagem seguinte — e se não houver repositório de pairing, não há dedupe nenhuma e o gateway fica calado, sem responder nada.

Aprovar um pair pela CLI

O outro lado do pair é o sistema de emparelhamento, e não tem grande ciência:

hermes pairing list                    # pendentes + aprovados
hermes pairing approve telegram ABC12DEF
hermes pairing revoke telegram 123456789
hermes pairing clear-pending

Os códigos têm oito caracteres de um alfabeto de 32 sem os caracteres ambíguos (0, O, 1 e I), gerados com aleatoriedade criptográfica, válidos uma hora, com um pedido por utilizador a cada dez minutos e no máximo três pendentes por plataforma. Cinco tentativas falhadas de aprovação bloqueiam-te durante uma hora. Os ficheiros ficam em ~/.hermes/pairing/ com permissões 0600, e os códigos nunca vão para o log.

O que costuma correr mal

  • E-mail é sempre ignore. Mesmo com pair global, uma caixa de entrada só muda com platforms.email.unauthorized_dm_behavior: pair (ou decline). Faz sentido: há ali muito correio que não é para o bot.
  • Isto só se aplica a DMs. O comportamento aplica-se a chat_type == "dm", nunca a grupos. E um bot nunca é emparelhado — só pessoas.
  • Um valor inválido cai no default. Se escreveres deny em vez de decline, não recebes erro nenhum: recebes pair. Vale a pena reler o que puseste no ficheiro.
  • Docker e o docker exec como root. A imagem oficial corre o gateway como o utilizador hermes (uid 10000), mas o docker exec é root por omissão: o ficheiro de aprovação fica 0600 root:root, o gateway não o consegue ler e a aprovação é ignorada sem qualquer erro. Usa sempre docker exec -u hermes ....

E, se não detetar allowlist nenhuma, o assistente hermes gateway setup pergunta-te isto tudo: acesso aberto, pairing, recusar educadamente ou ficar em silêncio. Grava a escolha e pronto.

Fecho

Numa máquina de testes, isto não te diz nada. Assim que o bot tem um username público, é a primeira coisa a decidir, e o Hermes dá-te as três respostas certas para o fazer. A minha recomendação é simples: pair onde queres crescer, decline com texto em português onde só tu falas, e ignore para o e-mail. E ALLOW_ALL só longe de qualquer coisa a que dês valor.

Docs: Security · Release v2026.9.21

Tags: #hermes #seguranca #gateway #dm