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 compairglobal, uma caixa de entrada só muda complatforms.email.unauthorized_dm_behavior: pair(oudecline). 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
denyem vez dedecline, não recebes erro nenhum: recebespair. Vale a pena reler o que puseste no ficheiro. - Docker e o
docker execcomo root. A imagem oficial corre o gateway como o utilizadorhermes(uid 10000), mas odocker execé root por omissão: o ficheiro de aprovação fica0600 root:root, o gateway não o consegue ler e a aprovação é ignorada sem qualquer erro. Usa sempredocker 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