Подключите Hermes к WeChat (微信) — персональной платформе обмена сообщениями от Tencent. Адаптер использует iLink Bot API от Tencent для личных аккаунтов WeChat — это отличается от WeCom (корпоративного WeChat). Сообщения доставляются через long-polling, поэтому не требуется публичный endpoint или webhook.
Этот адаптер предназначен для **личных аккаунтов WeChat** (微信). Если вам нужен корпоративный WeChat, воспользуйтесь [адаптером WeCom](./wecom.md).
warning iLink bot identity — обычные группы WeChat могут не работать
QR-логин подключает Hermes к идентификатору iLink бота (например, a5ace6fd482e@im.bot), а не к полноценному скриптируемому личному аккаунту WeChat. Последствия:
Идентификатор iLink бота, как правило, не может быть приглашён в обычные группы WeChat так, как это работает с обычными контактами.
iLink обычно не доставляет события обычных групп WeChat (включая @-упоминания личного аккаунта, использованного для QR-логина) на gateway для большинства бот-аккаунтов.
@-упоминание личного аккаунта WeChat, отсканировавшего QR-код, не равнозначно @-упоминанию iLink бота — бот является отдельной сущностью.
Настройки WEIXIN_GROUP_POLICY / WEIXIN_GROUP_ALLOWED_USERS ниже вступают в силу только когда iLink действительно возвращает события групп для вашего типа аккаунта. Если это не так, групповые сообщения никогда не достигнут Hermes независимо от политики.
На практике в большинстве развёртываний надёжно работают только личные сообщения (DM) iLink боту. Если групповая доставка не работает после настройки, ограничение на стороне iLink, а не Hermes. Gateway логирует WARNING при запуске, если WEIXIN_GROUP_POLICY установлен в любое значение, отличное от disabled.
Предварительные требования
Личный аккаунт WeChat
Пакеты Python: aiohttp и cryptography
Терминальный рендеринг QR-кода включён при установке Hermes с дополнением messaging
Установите необходимые зависимости:
pipinstallaiohttpcryptography
# Опционально: для отображения QR-кода в терминале
pipinstallhermes-agent[messaging]
Настройка
1. Запустите мастер настройки
Самый простой способ подключить ваш аккаунт WeChat — интерактивная настройка:
hermesgatewaysetup
Выберите Weixin при появлении запроса. Мастер выполнит следующее:
Запросит QR-код у iLink Bot API
Отобразит QR-код в вашем терминале (или предоставит URL)
Дождётся, пока вы отсканируете QR-код мобильным приложением WeChat
Попросит подтвердить вход в телефоне
Автоматически сохранит учётные данные аккаунта в ~/.hermes/weixin/accounts/
После подтверждения вы увидите сообщение:
微信连接成功,account_id=your-account-id
Мастер сохраняет account_id, token и base_url, так что вам не нужно настраивать их вручную.
2. Настройте переменные окружения
После первичного QR-логина укажите как минимум ID аккаунта в ~/.hermes/.env:
WEIXIN_ACCOUNT_ID=your-account-id
# Опционально: переопределить токен (обычно авто-сохраняется из QR-логина)# WEIXIN_TOKEN=your-bot-token# Опционально: ограничить доступWEIXIN_DM_POLICY=open
WEIXIN_ALLOWED_USERS=user_id_1,user_id_2
# Опционально: восстановить устаревшее поведение разбиения многострочных сообщений# WEIXIN_SPLIT_MULTILINE_MESSAGES=true# Опционально: домашний канал для cron/уведомленийWEIXIN_HOME_CHANNEL=chat_id
WEIXIN_HOME_CHANNEL_NAME=Home
3. Запустите gateway
hermesgateway
Адаптер восстановит сохранённые учётные данные, подключится к iLink API и начнёт long-polling сообщений.
Возможности
Long-poll транспорт — не требует публичного endpoint, webhook или WebSocket
QR-логин — подключение через сканирование QR-кода с помощью hermes gateway setup
Личные сообщения (DM) — настраиваемые политики доступа; групповая переписка зависит от того, доставляет ли iLink групповые события для подключённой учётной записи (часто не работает для iLink бот-аккаунтов — см. предупреждение выше)
Поддержка медиа — изображения, видео, файлы и голосовые сообщения
AES-128-ECB шифрованный CDN — автоматическое шифрование/дешифрование всех медиа-передач
Персистентность контекстных токенов — непрерывность ответов после перезапусков, сохраняемая на диск
Форматирование Markdown — сохраняет Markdown, включая заголовки, таблицы и блоки кода, чтобы клиенты WeChat, поддерживающие Markdown, могли отображать его нативно
Умная разбивка сообщений — сообщения остаются одним «пузырём» при размере ниже лимита; только превышающие лимит разбиваются по логическим границам
Индикаторы набора текста — отображает статус «печатает…» в клиенте WeChat, пока агент обрабатывает запрос
Защита SSRF — исходящие медиа-URL проверяются перед загрузкой
Дедупликация сообщений — скользящее окно в 5 минут предотвращает двойную обработку
Автоматические повторные попытки с экспоненциальной задержкой — восстановление после временных ошибок API
Параметры конфигурации
Установите их в config.yaml в разделе platforms.weixin.extra:
Ключ
По умолчанию
Описание
account_id
—
ID аккаунта iLink Bot (обязательно)
token
—
Токен iLink Bot (обязательно, авто-сохраняется из QR-логина)
base_url
https://ilinkai.weixin.qq.com
Базовый URL iLink API
cdn_base_url
https://novac2c.cdn.weixin.qq.com/c2c
Базовый URL CDN для передачи медиа
dm_policy
open
Доступ к DM: open, allowlist, disabled, pairing
group_policy
disabled
Доступ к группам: open, allowlist, disabled
allow_from
[]
ID пользователей, разрешённых для DM (при dm_policy=allowlist)
group_allow_from
[]
ID групп, разрешённых (при group_policy=allowlist)
split_multiline_messages
false
Если true, разбивает многострочные ответы на несколько сообщений чата (устаревшее поведение). Если false, сохраняет многострочные ответы как одно сообщение, если они не превышают лимит длины.
Политики доступа
Политика DM
Определяет, кто может отправлять личные сообщения боту:
Значение
Поведение
open
Любой может писать боту в DM (по умолчанию)
allowlist
Только ID пользователей из allow_from могут писать в DM
Определяет, в каких группах бот отвечает когда iLink доставляет групповые события для подключённой учётной записи. Для iLink бот-идентификаторов, подключённых через QR-логин (например, ...@im.bot), групповые события обычно не доставляются вовсе, поэтому эта политика может не иметь эффекта — см. предупреждение об ограничениях iLink бота в начале страницы.
Значение
Поведение
open
Бот отвечает во всех группах (если события доставляются)
allowlist
Бот отвечает только в группах из списка group_allow_from (если события доставляются)
disabled
Все групповые сообщения игнорируются (по умолчанию)
WEIXIN_GROUP_POLICY=allowlist
# ПРИМЕЧАНИЕ: это список ID групповых чатов, разделённых запятыми, а НЕ ID пользователей,# несмотря на то, что имя переменной содержит "USERS". Учтите это при настройке.WEIXIN_GROUP_ALLOWED_USERS=group_id_1,group_id_2
Политика групп по умолчанию — `disabled` для Weixin (в отличие от WeCom, где по умолчанию `open`). Это сделано намеренно — личные аккаунты WeChat могут быть во многих группах, а iLink бот-идентификаторы обычно вообще не могут получать обычные групповые сообщения WeChat. Gateway логирует `WARNING` при запуске, если вы устанавливаете `WEIXIN_GROUP_POLICY` в любое значение, отличное от `disabled`.
Поддержка медиа
Входящие (получение)
Адаптер получает медиа-вложения от пользователей, загружает их с CDN WeChat, расшифровывает и кеширует локально для обработки агентом:
Тип
Обработка
Изображения
Загружаются, расшифровываются AES и кешируются как JPEG.
Видео
Загружается, расшифровывается AES и кешируется как MP4.
Файлы
Загружаются, расшифровываются AES и кешируются. Исходное имя файла сохраняется.
Голос
Если доступна текстовая расшифровка, она извлекается как текст. В противном случае аудио (формат SILK) загружается и кешируется.
Цитируемые сообщения: Медиа из цитируемых (на которые дан ответ) сообщений также извлекается, поэтому агент имеет контекст того, на что отвечает пользователь.
AES-128-ECB шифрованный CDN
Медиа-файлы WeChat передаются через шифрованный CDN. Адаптер обрабатывает это прозрачно:
Входящие: Зашифрованные медиа загружаются с CDN по URL с encrypted_query_param, затем расшифровываются с помощью AES-128-ECB, используя ключ для каждого файла, предоставленный в payload сообщения.
Исходящие: Файлы шифруются локально случайным ключом AES-128-ECB, загружаются на CDN, и зашифрованная ссылка включается в исходящее сообщение.
Ключ AES составляет 16 байт (128 бит). Ключи могут приходить в виде raw base64 или hex — адаптер обрабатывает оба формата.
Для этого требуется пакет Python cryptography.
Никакой настройки не требуется — шифрование и дешифрование происходят автоматически.
Исходящие (отправка)
Метод
Что отправляет
send
Текстовые сообщения с форматированием Markdown
send_image / send_image_file
Нативные сообщения с изображениями (через загрузку на CDN)
send_document
Файловые вложения (через загрузку на CDN)
send_video
Видеосообщения (через загрузку на CDN)
Все исходящие медиа проходят через процесс шифрованной загрузки на CDN:
Генерация случайного ключа AES-128
Шифрование файла с помощью AES-128-ECB + PKCS#7 padding
Запрос URL для загрузки у iLink API (getuploadurl)
Загрузка шифротекста на CDN
Отправка сообщения со ссылкой на зашифрованное медиа
Персистентность контекстных токенов
iLink Bot API требует, чтобы context_token возвращался с каждым исходящим сообщением для данного собеседника. Адаптер ведёт сохраняемое на диск хранилище контекстных токенов:
Токены сохраняются для каждой пары аккаунт+собеседник в ~/.hermes/weixin/accounts/<account_id>.context-tokens.json
При запуске ранее сохранённые токены восстанавливаются
Каждое входящее сообщение обновляет сохранённый токен для отправителя
Исходящие сообщения автоматически включают последний контекстный токен
Это обеспечивает непрерывность ответов даже после перезапусков gateway.
Форматирование Markdown
Клиенты WeChat, подключённые через iLink Bot API, могут отображать Markdown напрямую, поэтому адаптер сохраняет Markdown вместо его преобразования:
Заголовки остаются как Markdown-заголовки (#, ##, ...)
Таблицы остаются как Markdown-таблицы
Блоки кода остаются как fenced code blocks
Лишние пустые строки схлопываются в двойные переносы строк вне fenced code blocks
Разбивка сообщений
Сообщения доставляются как одно сообщение чата, если они укладываются в лимит платформы. Только превышающие лимит разбиваются для доставки:
Максимальная длина сообщения: 4000 символов
Сообщения ниже лимита остаются целыми, даже если содержат несколько абзацев или переносов строк
Блоки кода сохраняются целыми, когда это возможно (никогда не разбиваются внутри блока, если только сам блок не превышает лимит)
Отдельные блоки, превышающие лимит, обрабатываются логикой усечения базового адаптера
Задержка между чанками в 0,3 с предотвращает сбросы из-за лимитов WeChat при отправке нескольких частей
Индикаторы набора текста
Адаптер отображает статус набора текста в клиенте WeChat:
При получении сообщения адаптер запрашивает typing_ticket через API getconfig
Тикет набора текста кешируется на 10 минут для каждого пользователя
send_typing отправляет сигнал начала набора; stop_typing отправляет сигнал остановки набора
Gateway автоматически запускает индикаторы набора текста, пока агент обрабатывает сообщение
Long-Poll подключение
Адаптер использует HTTP long-polling (не WebSocket) для получения сообщений:
Как это работает
Подключение: Проверяет учётные данные и запускает цикл опроса
Опрос: Вызывает getupdates с таймаутом 35 секунд; сервер удерживает запрос до поступления сообщений или истечения таймаута
Обработка: Входящие сообщения обрабатываются конкурентно через asyncio.create_task
Синхронизация буфера: Постоянный курсор синхронизации (get_updates_buf) сохраняется на диск, чтобы адаптер возобновлял работу с правильной позиции после перезапусков
Поведение при повторных попытках
При ошибках API адаптер использует простую стратегию повторных попыток:
Условие
Поведение
Временная ошибка (1–2 раза)
Повтор через 2 секунды
Повторяющиеся ошибки (3+)
Ожидание 30 секунд, затем сброс счётчика
Сессия истекла (errcode=-14)
Пауза 10 минут (может потребоваться повторный вход)
Таймаут
Немедленный повторный опрос (обычное поведение long-poll)
Дедупликация
Входящие сообщения дедуплицируются по ID сообщения в 5-минутном окне. Это предотвращает двойную обработку при сетевых сбоях или перекрывающихся ответах опроса.
Блокировка токена
Только один экземпляр Weixin gateway может использовать данный токен одновременно. Адаптер получает блокировку с областью действия при запуске и освобождает её при остановке. Если другой gateway уже использует тот же токен, запуск завершается с информативным сообщением об ошибке.
Все переменные окружения
Переменная
Обязательная
По умолчанию
Описание
WEIXIN_ACCOUNT_ID
✅
—
ID аккаунта iLink Bot (из QR-логина)
WEIXIN_TOKEN
✅
—
Токен iLink Bot (авто-сохраняется из QR-логина)
WEIXIN_BASE_URL
—
https://ilinkai.weixin.qq.com
Базовый URL iLink API
WEIXIN_CDN_BASE_URL
—
https://novac2c.cdn.weixin.qq.com/c2c
Базовый URL CDN для передачи медиа
WEIXIN_DM_POLICY
—
open
Политика доступа к DM: open, allowlist, disabled, pairing
WEIXIN_GROUP_POLICY
—
disabled
Политика доступа к группам: open, allowlist, disabled
WEIXIN_ALLOWED_USERS
—
(пусто)
ID пользователей через запятую для DM allowlist
WEIXIN_GROUP_ALLOWED_USERS
—
(пусто)
Разделённые запятыми ID групповых чатов (не ID участников) для группового allowlist. Имя переменной устаревшее — ожидаются ID групп, а не ID пользователей.
WEIXIN_HOME_CHANNEL
—
—
ID чата для вывода cron/уведомлений
WEIXIN_HOME_CHANNEL_NAME
—
Home
Отображаемое имя домашнего канала
WEIXIN_ALLOW_ALL_USERS
—
—
Флаг уровня gateway для разрешения всем пользователям (используется мастером настройки)
Устранение неполадок
Проблема
Решение
Weixin startup failed: aiohttp and cryptography are required
Установите оба: pip install aiohttp cryptography
Weixin startup failed: WEIXIN_TOKEN is required
Запустите hermes gateway setup для QR-логина или установите WEIXIN_TOKEN вручную
Weixin startup failed: WEIXIN_ACCOUNT_ID is required
Укажите WEIXIN_ACCOUNT_ID в вашем .env или запустите hermes gateway setup
Another local Hermes gateway is already using this Weixin token
Сначала остановите другой экземпляр gateway — разрешён только один poller на токен
Сессия истекла (errcode=-14)
Ваша сессия входа истекла. Повторно запустите hermes gateway setup для сканирования нового QR-кода
QR-код истёк во время настройки
QR-код автоматически обновляется до 3 раз. Если он продолжает истекать, проверьте сетевое подключение
Бот не отвечает на DM
Проверьте WEIXIN_DM_POLICY — если установлен allowlist, отправитель должен быть в WEIXIN_ALLOWED_USERS
Бот игнорирует групповые сообщения
Политика групп по умолчанию — disabled. Установите WEIXIN_GROUP_POLICY=open или allowlist — но учтите, что iLink бот-идентификаторы, подключённые через QR-логин (...@im.bot), обычно не могут получать обычные групповые сообщения WeChat. Если в логах gateway нет сырых входящих событий для групповых сообщений, ограничение на стороне iLink, а не Hermes.
Не удаётся загрузить/скачать медиа
Убедитесь, что установлен cryptography. Проверьте сетевой доступ к novac2c.cdn.weixin.qq.com
Blocked unsafe URL (SSRF protection)
Исходящий медиа-URL указывает на частный/внутренний адрес. Разрешены только публичные URL
Голосовые сообщения отображаются как текст
Если WeChat предоставляет расшифровку, адаптер использует текст. Это ожидаемое поведение
Сообщения появляются дублированными
Адаптер дедуплицирует по ID сообщения. Если вы видите дубликаты, проверьте, не запущено ли несколько экземпляров gateway
iLink POST ... HTTP 4xx/5xx
Ошибка API от сервиса iLink. Проверьте действительность токена и сетевое подключение
QR-код в терминале не отображается
Переустановите с дополнением messaging: pip install hermes-agent[messaging]. Альтернативно, откройте URL, напечатанный над QR-кодом