Documentação oficial desta página · v0.20.6
Weixin (WeChat)
Weixin (WeChat)
Conecte o Hermes ao WeChat (微信), a plataforma de mensagens pessoais da Tencent. O adaptador usa a iLink Bot API da Tencent para contas pessoais do WeChat — isso é diferente do WeCom (WeChat Empresarial). As mensagens chegam por long-polling, então nenhum endpoint público ou webhook é necessário.
Este adaptador é para contas pessoais do WeChat (微信). Se você precisa do WeChat corporativo/empresarial, veja o adaptador do WeCom.
O login por QR conecta o Hermes a uma identidade de bot do iLink (por exemplo, a5ace6fd482e@im.bot), e não a uma conta pessoal comum do WeChat totalmente controlável por script. Consequências:
- A identidade de bot do iLink em geral não pode ser convidada para grupos comuns do WeChat como um contato normal pode.
- O iLink normalmente não entrega eventos de grupo comuns do WeChat (incluindo menções com
@à conta pessoal usada no login por QR) para o gateway na maioria das contas do tipo bot. - Mencionar com
@a conta pessoal do WeChat que leu o código QR não é o mesmo que mencionar com@o bot do iLink — o bot é uma identidade separada. - As configurações
WEIXIN_GROUP_POLICY/WEIXIN_GROUP_ALLOWED_USERSdescritas abaixo só têm efeito quando o iLink realmente devolve eventos de grupo para o seu tipo de conta. Se não devolver, as mensagens de grupo nunca vão chegar ao Hermes, seja qual for a política.
Na prática, a maioria das instalações só consegue fazer funcionar de forma confiável as mensagens diretas para o bot do iLink. Se a entrega em grupo não funcionar depois da configuração, a limitação está do lado do iLink, não no Hermes. O gateway registra um WARNING na inicialização sempre que WEIXIN_GROUP_POLICY estiver definido como qualquer coisa diferente de disabled.
Pré-requisitos
- Uma conta pessoal do WeChat
- Pacotes Python:
aiohttpecryptography - A renderização de QR no terminal já vem incluída quando o Hermes é instalado com o extra
messaging
Instale as dependências necessárias:
pip install aiohttp cryptography
# Opcional: para exibir o código QR no terminal
cd ~/.hermes/hermes-agent && uv pip install -e ".[messaging]"
Configuração
1. Rode o assistente de configuração
A maneira mais fácil de conectar a sua conta do WeChat é pelo assistente interativo:
hermes gateway setup
Escolha Weixin quando for perguntado. O assistente vai:
- Pedir um código QR à iLink Bot API
- Exibir o código QR no seu terminal (ou fornecer uma URL)
- Esperar que você leia o código QR com o aplicativo do WeChat no celular
- Pedir que você confirme o login no telefone
- Salvar as credenciais da conta automaticamente em
~/.hermes/weixin/accounts/
Depois de confirmar, você verá uma mensagem assim:
微信连接成功,account_id=your-account-id
O assistente guarda o account_id, o token e a base_url, então você não precisa configurá-los à mão.
2. Configure as variáveis de ambiente
Depois do login inicial por QR, defina no mínimo o ID da conta em ~/.hermes/.env:
WEIXIN_ACCOUNT_ID=id-da-sua-conta
# Opcional: sobrescreve o token (normalmente salvo automaticamente pelo login por QR)
# WEIXIN_TOKEN=token-do-seu-bot
# Opcional: restringe o acesso
WEIXIN_DM_POLICY=open
WEIXIN_ALLOWED_USERS=user_id_1,user_id_2
# Opcional: restaura o comportamento antigo de quebra de mensagens em várias linhas
# WEIXIN_SPLIT_MULTILINE_MESSAGES=true
# Opcional: canal principal para cron e notificações
WEIXIN_HOME_CHANNEL=chat_id
WEIXIN_HOME_CHANNEL_NAME=Home
3. Inicie o gateway
hermes gateway
O adaptador vai restaurar as credenciais salvas, conectar-se à API do iLink e começar o long-polling em busca de mensagens.
Recursos
- Transporte por long-poll — sem necessidade de endpoint público, webhook ou WebSocket
- Login por código QR — configuração por leitura de QR via
hermes gateway setup - Mensagens diretas — políticas de acesso configuráveis; as mensagens em grupo dependem de o iLink realmente entregar eventos de grupo para a identidade conectada (o que muitas vezes não acontece em contas de bot do iLink — veja o aviso acima)
- Suporte a mídia — imagens, vídeo, arquivos e mensagens de voz
- CDN criptografada em AES-128-ECB — criptografia e descriptografia automáticas em todas as transferências de mídia
- Persistência de token de contexto — continuidade de resposta gravada em disco, mantida entre reinícios
- Formatação Markdown — preserva o Markdown, incluindo títulos, tabelas e blocos de código, para que os clientes do WeChat que suportam Markdown possam renderizá-lo nativamente
- Fatiamento inteligente de mensagens — mensagens ficam em uma única bolha quando estão abaixo do limite; só os conteúdos grandes demais são divididos em fronteiras lógicas
- Indicadores de digitação — mostra o status "digitando…" no cliente do WeChat enquanto o agente processa
- Proteção contra SSRF — as URLs de mídia de saída são validadas antes do download
- Deduplicação de mensagens — uma janela deslizante de 5 minutos evita processamento duplicado
- Nova tentativa automática com recuo — recupera-se de erros transitórios da API
Opções de configuração
Defina estas opções no config.yaml, em platforms.weixin.extra:
| Chave | Padrão | Descrição |
|---|---|---|
account_id | — | ID da conta do iLink Bot (obrigatório) |
token | — | Token do iLink Bot (obrigatório, salvo automaticamente no login por QR) |
base_url | https://ilinkai.weixin.qq.com | URL base da API do iLink |
cdn_base_url | https://novac2c.cdn.weixin.qq.com/c2c | URL base da CDN para transferência de mídia |
dm_policy | open | Acesso a mensagens diretas: open, allowlist, disabled, pairing |
group_policy | disabled | Acesso a grupos: open, allowlist, disabled |
allow_from | [] | IDs de usuário liberados para mensagens diretas (quando dm_policy=allowlist) |
group_allow_from | [] | IDs de grupo liberados (quando group_policy=allowlist) |
split_multiline_messages | false | Quando true, divide respostas de várias linhas em várias mensagens de chat (comportamento antigo). Quando false, mantém respostas de várias linhas como uma só mensagem, a menos que passem do limite de tamanho. |
text_batch_delay_seconds | 3.0 | Período de silêncio (em segundos) antes de uma rajada de mensagens de texto rápidas, guardada em buffer, ser despachada como uma única requisição combinada. O iLink entrega as mensagens uma a uma, então esse debounce evita uma invocação do agente por fragmento. Defina 0 para despachar cada mensagem imediatamente. |
text_batch_split_delay_seconds | 5.0 | Atraso estendido de despacho, usado quando o último fragmento está perto do limite de divisão (mensagens longas que o iLink pode ter fatiado). |
Políticas de acesso
Política de mensagens diretas
Controla quem pode mandar mensagens diretas para o bot:
| Valor | Comportamento |
|---|---|
open | Qualquer pessoa pode mandar mensagem direta ao bot (padrão) |
allowlist | Só os IDs de usuário em allow_from podem mandar mensagem direta |
disabled | Todas as mensagens diretas são ignoradas |
pairing | Modo de pareamento (para a configuração inicial) |
WEIXIN_DM_POLICY=allowlist
WEIXIN_ALLOWED_USERS=user_id_1,user_id_2
WEIXIN_ALLOWED_USERS é um filtro de entrada, não um sistema de convites. O
login por QR conecta uma identidade de bot do iLink ao Hermes. Outras pessoas
não leem o código QR do Hermes com as contas delas; elas precisam mandar
mensagem para o bot/contato do iLink conectado pelo WeChat, e o Hermes só vai
processar a mensagem direta se o ID de usuário do Weixin de quem enviou estiver
em WEIXIN_ALLOWED_USERS.
Um fluxo prático de configuração é:
- Pareie o Hermes uma vez com
hermes gateway setupe anote a conta de bot do iLink conectada. - Peça a cada usuário liberado que mande uma mensagem direta para esse bot/contato.
- Leia o ID de quem enviou nos logs do gateway ou no payload do evento de entrada.
- Acrescente esses IDs a
WEIXIN_ALLOWED_USERSe reinicie o gateway.
Se só a conta que leu o código QR consegue falar com o Hermes, confira se os outros usuários estão mandando mensagem para a própria identidade de bot do iLink, e não para a conta pessoal do WeChat que fez o login por QR. O bot do iLink é uma identidade separada, e o roteamento comum de contatos e grupos do WeChat pode ser limitado pelo comportamento do iLink da Tencent.
Política de grupos
Controla em quais grupos o bot responde quando o iLink entrega eventos de grupo para a identidade conectada. Para identidades de bot do iLink criadas por login por QR (por exemplo, ...@im.bot), os eventos de grupo normalmente não são entregues, então esta política pode não ter efeito nenhum — veja o aviso sobre a limitação do bot do iLink no início da página.
| Valor | Comportamento |
|---|---|
open | O bot responde em todos os grupos (se os eventos forem entregues) |
allowlist | O bot só responde nos IDs de grupo listados em group_allow_from (se os eventos forem entregues) |
disabled | Todas as mensagens de grupo são ignoradas (padrão) |
WEIXIN_GROUP_POLICY=allowlist
# ATENÇÃO: esta é uma lista de IDs de conversa de grupo separada por vírgulas, NÃO
# de IDs de usuário dos membros, apesar de o nome da variável conter "USERS".
# Tenha isso em mente ao configurar.
WEIXIN_GROUP_ALLOWED_USERS=group_id_1,group_id_2
A política de grupo padrão do Weixin é disabled (diferente do WeCom, onde o padrão é open). Isso é intencional — contas pessoais do WeChat podem estar em muitos grupos, e identidades de bot do iLink normalmente não conseguem receber mensagens de grupo comuns do WeChat de jeito nenhum. O gateway registra um WARNING na inicialização se você definir WEIXIN_GROUP_POLICY como qualquer coisa diferente de disabled.
Suporte a mídia
Entrada (recebimento)
O adaptador recebe anexos de mídia dos usuários, baixa-os da CDN do WeChat, descriptografa e guarda em cache local para o agente processar:
| Tipo | Como é tratado |
|---|---|
| Imagens | Baixadas, descriptografadas com AES e guardadas em cache como JPEG. |
| Vídeo | Baixado, descriptografado com AES e guardado em cache como MP4. |
| Arquivos | Baixados, descriptografados com AES e guardados em cache. O nome original do arquivo é preservado. |
| Voz | Se há transcrição em texto disponível, ela é extraída como texto. Caso contrário, o áudio (formato SILK) é baixado e guardado em cache. |
Mensagens citadas: a mídia de mensagens citadas (respondidas) também é extraída, para que o agente tenha contexto sobre o que o usuário está respondendo.
CDN criptografada em AES-128-ECB
Os arquivos de mídia do WeChat são transferidos por uma CDN criptografada. O adaptador cuida disso de forma transparente:
- Entrada: a mídia criptografada é baixada da CDN por URLs com
encrypted_query_parame depois descriptografada com AES-128-ECB, usando a chave por arquivo fornecida no payload da mensagem. - Saída: os arquivos são criptografados localmente com uma chave AES-128-ECB aleatória, enviados à CDN, e a referência criptografada é incluída na mensagem de saída.
- A chave AES tem 16 bytes (128 bits). As chaves podem chegar como base64 cru ou em hexadecimal — o adaptador lida com os dois formatos.
- Isso exige o pacote Python
cryptography.
Nenhuma configuração é necessária — a criptografia e a descriptografia acontecem automaticamente.
Saída (envio)
| Método | O que envia |
|---|---|
send | Mensagens de texto com formatação Markdown |
send_image / send_image_file | Mensagens de imagem nativas (via upload para a CDN) |
send_document | Anexos de arquivo (via upload para a CDN) |
send_video | Mensagens de vídeo (via upload para a CDN) |
Toda mídia de saída passa pelo fluxo de upload criptografado para a CDN:
- Gerar uma chave AES-128 aleatória
- Criptografar o arquivo com AES-128-ECB + preenchimento PKCS#7
- Pedir uma URL de upload à API do iLink (
getuploadurl) - Enviar o texto cifrado para a CDN
- Enviar a mensagem com a referência de mídia criptografada
Persistência do token de contexto
A iLink Bot API exige que um context_token seja devolvido junto com cada mensagem de saída para um determinado interlocutor. O adaptador mantém um repositório de tokens de contexto gravado em disco:
- Os tokens são salvos por conta+interlocutor em
~/.hermes/weixin/accounts/<account_id>.context-tokens.json - Na inicialização, os tokens salvos anteriormente são restaurados
- Toda mensagem de entrada atualiza o token guardado para aquele remetente
- As mensagens de saída incluem automaticamente o token de contexto mais recente
Isso garante a continuidade das respostas mesmo depois de reinícios do gateway.
Formatação Markdown
Os clientes do WeChat conectados pela iLink Bot API conseguem renderizar Markdown diretamente, então o adaptador preserva o Markdown em vez de reescrevê-lo:
- Títulos continuam como títulos Markdown (
#,##, ...) - Tabelas continuam como tabelas Markdown
- Cercas de código continuam como blocos de código cercados
- Linhas em branco em excesso são reduzidas a duas quebras de linha, fora dos blocos de código cercados
Fatiamento de mensagens
As mensagens são entregues como uma única mensagem de chat sempre que cabem no limite da plataforma. Só os conteúdos grandes demais são divididos para a entrega:
- Tamanho máximo da mensagem: 4000 caracteres
- Mensagens abaixo do limite ficam intactas, mesmo com vários parágrafos ou quebras de linha
- Mensagens grandes demais são divididas em fronteiras lógicas (parágrafos, linhas em branco, cercas de código)
- As cercas de código são mantidas intactas sempre que possível (nunca divididas no meio do bloco, a menos que a própria cerca passe do limite)
- Blocos individuais grandes demais caem na lógica de truncamento do adaptador base
- Um atraso de 0,3 s entre pedaços evita descartes por limite de taxa do WeChat quando vários pedaços são enviados
Indicadores de digitação
O adaptador mostra o status de digitação no cliente do WeChat:
- Quando chega uma mensagem, o adaptador busca um
typing_ticketpela APIgetconfig - Os tíquetes de digitação ficam em cache por 10 minutos, por usuário
send_typingenvia um sinal de início de digitação;stop_typingenvia um sinal de fim de digitação- O gateway aciona os indicadores de digitação automaticamente enquanto o agente processa uma mensagem
Conexão por long-poll
O adaptador usa long-polling HTTP (não WebSocket) para receber mensagens:
Como funciona
- Conexão: valida as credenciais e inicia o laço de polling
- Poll: chama
getupdatescom um timeout de 35 segundos; o servidor segura a requisição até que cheguem mensagens ou o timeout expire - Despacho: as mensagens de entrada são despachadas de forma concorrente via
asyncio.create_task - Buffer de sincronização: um cursor de sincronização persistente (
get_updates_buf) é salvo em disco, para que o adaptador retome da posição correta depois de reinícios
Comportamento de nova tentativa
Em erros da API, o adaptador usa uma estratégia simples de nova tentativa:
| Condição | Comportamento |
|---|---|
| Erro transitório (1º–2º) | Tenta de novo depois de 2 segundos |
| Erros repetidos (3 ou mais) | Recua por 30 segundos e depois zera o contador |
Sessão expirada (errcode=-14) | Pausa por 10 minutos (pode ser necessário fazer login de novo) |
| Timeout | Refaz o poll imediatamente (comportamento normal de long-poll) |
Deduplicação
As mensagens de entrada são deduplicadas por IDs de mensagem, com uma janela de 5 minutos. Isso evita processamento duplicado durante instabilidades de rede ou respostas de poll sobrepostas.
Trava de token
Só uma instância de gateway do Weixin pode usar um determinado token de cada vez. O adaptador adquire uma trava com escopo na inicialização e a libera no encerramento. Se outro gateway já estiver usando o mesmo token, a inicialização falha com uma mensagem de erro informativa.
Todas as variáveis de ambiente
| Variável | Obrigatória | Padrão | Descrição |
|---|---|---|---|
WEIXIN_ACCOUNT_ID | ✅ | — | ID da conta do iLink Bot (vem do login por QR) |
WEIXIN_TOKEN | ✅ | — | Token do iLink Bot (salvo automaticamente no login por QR) |
WEIXIN_BASE_URL | — | https://ilinkai.weixin.qq.com | URL base da API do iLink |
WEIXIN_CDN_BASE_URL | — | https://novac2c.cdn.weixin.qq.com/c2c | URL base da CDN para transferência de mídia |
WEIXIN_DM_POLICY | — | open | Política de acesso a mensagens diretas: open, allowlist, disabled, pairing |
WEIXIN_GROUP_POLICY | — | disabled | Política de acesso a grupos: open, allowlist, disabled |
WEIXIN_ALLOWED_USERS | — | (vazio) | IDs de usuário separados por vírgula para a lista de permissão de mensagens diretas |
WEIXIN_GROUP_ALLOWED_USERS | — | (vazio) | IDs de conversa de grupo separados por vírgula (não IDs de usuário dos membros) para a lista de permissão de grupos. O nome da variável é herdado do passado — ela espera IDs de grupo, não de usuário. |
WEIXIN_HOME_CHANNEL | — | — | ID de conversa para a saída de cron e notificações |
WEIXIN_HOME_CHANNEL_NAME | — | Home | Nome de exibição do canal principal |
WEIXIN_ALLOW_ALL_USERS | — | — | Sinalizador no nível do gateway para liberar todos os usuários (usado pelo assistente de configuração) |
Solução de problemas
| Problema | Solução |
|---|---|
Weixin startup failed: aiohttp and cryptography are required | Instale os dois: pip install aiohttp cryptography |
Weixin startup failed: WEIXIN_TOKEN is required | Rode hermes gateway setup para concluir o login por QR, ou defina WEIXIN_TOKEN à mão |
Weixin startup failed: WEIXIN_ACCOUNT_ID is required | Defina WEIXIN_ACCOUNT_ID no seu .env ou rode hermes gateway setup |
Another local Hermes gateway is already using this Weixin token | Pare a outra instância do gateway primeiro — só é permitido um poller por token |
Sessão expirada (errcode=-14) | A sua sessão de login expirou. Rode hermes gateway setup de novo para ler um novo código QR |
| Código QR expirou durante a configuração | O QR se renova automaticamente até 3 vezes. Se ele continuar expirando, verifique a sua conexão de rede |
| O bot não responde a mensagens diretas | Confira WEIXIN_DM_POLICY — se estiver em allowlist, quem envia precisa estar em WEIXIN_ALLOWED_USERS |
| O bot ignora mensagens de grupo | A política de grupo é disabled por padrão. Defina WEIXIN_GROUP_POLICY=open ou allowlist — mas note que identidades de bot do iLink criadas por login por QR (...@im.bot) normalmente não conseguem receber mensagens de grupo comuns do WeChat de jeito nenhum. Se os logs do gateway não mostram nenhum evento cru de entrada para mensagens de grupo, a limitação está do lado do iLink, não no Hermes. |
| Falha no download ou upload de mídia | Confirme que o cryptography está instalado. Verifique o acesso de rede a novac2c.cdn.weixin.qq.com |
Blocked unsafe URL (SSRF protection) | A URL de mídia de saída aponta para um endereço privado/interno. Só URLs públicas são permitidas |
| Mensagens de voz aparecem como texto | Se o WeChat fornece uma transcrição, o adaptador usa o texto. Esse é o comportamento esperado |
| Mensagens aparecem duplicadas | O adaptador deduplica por ID de mensagem. Se você vê duplicatas, verifique se há várias instâncias do gateway rodando |
iLink POST ... HTTP 4xx/5xx | Erro de API do serviço iLink. Verifique a validade do seu token e a conectividade de rede |
| O código QR não aparece no terminal | Reinstale com o extra de mensagens: cd ~/.hermes/hermes-agent && uv pip install -e ".[messaging]". Como alternativa, abra a URL impressa acima do QR |