Wecom
On this page Подключите Hermes к WeCom (企业微信), корпоративной мессенджер-платформе от Tencent. Адаптер использует WebSocket-шлюз AI-бота WeCom для двунаправленной связи в реальном времени — не требуется публичный endpoint или webhook.
Требования¶
- Учётная запись организации в WeCom
- AI-бот, созданный в консоли администратора WeCom
- ID бота и секретный ключ со страницы учётных данных бота
- Пакеты Python:
aiohttpиhttpx
Настройка¶
Шаг 1: Создание AI-бота¶
Рекомендуемый способ: создание по QR-коду (одна команда)¶
[code] hermes gateway setup
[/code] Выберите WeCom и отсканируйте QR-код с помощью мобильного приложения WeCom. Hermes автоматически создаст приложение-бота с правильными разрешениями и сохранит учётные данные. Мастер настройки выполнит: 1. Отобразит QR-код в вашем терминале 2. Дождётся, пока вы отсканируете его в мобильном приложении WeCom 3. Автоматически получит ID бота и секретный ключ 4. Проведёт вас через настройку контроля доступа
Альтернатива: ручная настройка¶
Если создание по QR-коду недоступно, мастер переключится на ручной ввод:
1. Войдите в консоль администратора WeCom
2. Перейдите в Приложения → Создать приложение → AI-бот
3. Настройте имя и описание бота
4. Скопируйте ID бота и секретный ключ со страницы учётных данных
5. Запустите hermes gateway setup, выберите WeCom и введите учётные данные по запросу
warning Храните секретный ключ бота в тайне. Любой, кто им завладеет, сможет выдавать себя за вашего бота.
Шаг 2: Настройка Hermes¶
Вариант A: Интерактивная настройка (рекомендуется)¶
[code] hermes gateway setup
[/code] Выберите WeCom и следуйте подсказкам. Мастер проведёт вас через: * Учётные данные бота (через QR-код или ручной ввод) * Настройки контроля доступа (белый список, режим сопряжения или открытый доступ) * Домашний канал для уведомлений
Вариант B: Ручная конфигурация¶
Добавьте следующее в ~/.hermes/.env:
[code]
WECOM_BOT_ID=your-bot-id
WECOM_SECRET=your-secret
# Опционально: ограничение доступа
WECOM_ALLOWED_USERS=user_id_1,user_id_2
# Опционально: домашний канал для cron/уведомлений
WECOM_HOME_CHANNEL=chat_id
[/code]
Шаг 3: Запуск шлюза¶
[code] hermes gateway
[/code]
Возможности¶
- WebSocket-транспорт — постоянное соединение, не требуется публичный endpoint
- Личные и групповые сообщения — настраиваемые политики доступа
- Белые списки отправителей для каждой группы — тонкий контроль того, кто может взаимодействовать в каждой группе
- Поддержка медиа — загрузка и скачивание изображений, файлов, голоса, видео
- AES-зашифрованные медиа — автоматическая расшифровка входящих вложений
- Контекст цитирования — сохранение threading ответов
- Отрисовка Markdown — форматированные текстовые ответы
- Потоковая передача в режиме ответа — привязка ответов к контексту входящего сообщения
- Автопереподключение — экспоненциальная задержка при обрывах соединения
Параметры конфигурации¶
Установите в config.yaml в разделе platforms.wecom.extra:
Ключ| По умолчанию| Описание
---|---|---
bot_id| —| ID AI-бота WeCom (обязательно)
secret| —| Секретный ключ AI-бота WeCom (обязательно)
websocket_url| wss://openws.work.weixin.qq.com| URL WebSocket-шлюза
dm_policy| open| Доступ в ЛС: open, allowlist, disabled, pairing
group_policy| open| Доступ в группах: open, allowlist, disabled
allow_from| []| ID пользователей, разрешённых для ЛС (если dm_policy=allowlist)
group_allow_from| []| ID групп, разрешённых (если group_policy=allowlist)
groups| {}| Конфигурация для каждой группы (см. ниже)
Политики доступа¶
Политика для личных сообщений (DM)¶
Определяет, кто может отправлять боту личные сообщения:
Значение| Поведение
---|---
open| Любой может писать боту в ЛС (по умолчанию)
allowlist| Только пользователи из allow_from могут писать в ЛС
disabled| Все ЛС игнорируются
pairing| Режим сопряжения (для начальной настройки)
[code]
WECOM_DM_POLICY=allowlist
[/code]
Политика для групп¶
Определяет, в каких группах бот отвечает:
Значение| Поведение
---|---
open| Бот отвечает во всех группах (по умолчанию)
allowlist| Бот отвечает только в группах, ID которых указаны в group_allow_from
disabled| Все групповые сообщения игнорируются
[code]
WECOM_GROUP_POLICY=allowlist
[/code]
Белые списки отправителей для каждой группы¶
Для точного контроля можно ограничить, какие пользователи могут взаимодействовать с ботом в определённых группах. Настраивается в config.yaml:
[code]
platforms:
wecom:
enabled: true
extra:
bot_id: "your-bot-id"
secret: "your-secret"
group_policy: "allowlist"
group_allow_from:
- "group_id_1"
- "group_id_2"
groups:
group_id_1:
allow_from:
- "user_alice"
- "user_bob"
group_id_2:
allow_from:
- "user_charlie"
"*":
allow_from:
- "user_admin"
[/code]
Как это работает:
1. group_policy и group_allow_from определяют, разрешена ли группа в принципе.
2. Если группа проходит проверку верхнего уровня, список groups.<group_id>.allow_from (если задан) дополнительно ограничивает, какие отправители внутри этой группы могут взаимодействовать с ботом.
3. Запись с wildcard "*" служит значением по умолчанию для групп, не указанных явно.
4. Записи в белом списке поддерживают wildcard * для разрешения всех пользователей; регистр не учитывается.
5. Записи могут опционально использовать префикс wecom:user: или wecom:group: — префикс автоматически отбрасывается.
Если для группы не настроен allow_from, всем пользователям этой группы разрешено взаимодействие (при условии, что сама группа проходит проверку политики верхнего уровня).
Поддержка медиа¶
Входящие (получение)¶
Адаптер получает медиавложения от пользователей и кеширует их локально для обработки агентом:
Тип| Как обрабатывается
---|---
Изображения| Скачиваются и кешируются локально. Поддерживаются как URL, так и изображения в base64.
Файлы| Скачиваются и кешируются. Имя файла сохраняется из исходного сообщения.
Голос| Извлекается текстовая расшифровка голосового сообщения, если доступна.
Смешанные сообщения| Смешанные сообщения WeCom (текст + изображения) разбираются, извлекаются все компоненты.
Цитируемые сообщения: Медиа из цитируемых (на которые дан ответ) сообщений также извлекается, чтобы агент понимал контекст ответа пользователя.
Расшифровка AES-зашифрованных медиа¶
WeCom шифрует некоторые входящие медиавложения с помощью AES-256-CBC. Адаптер обрабатывает это автоматически:
* Если входящий медиафайл содержит поле aeskey, адаптер скачивает зашифрованные байты и расшифровывает их с помощью AES-256-CBC с выравниванием PKCS#7.
* AES-ключ — это значение поля aeskey, декодированное из base64 (должно быть ровно 32 байта).
* IV получается из первых 16 байт ключа.
* Для этого требуется пакет Python cryptography (pip install cryptography).
Настройка не требуется — расшифровка происходит прозрачно при получении зашифрованных медиа.
Исходящие (отправка)¶
| Метод | Что отправляет | Ограничение размера |
|---|---|---|
send |
Текстовые сообщения в Markdown | 4000 символов |
send_image / send_image_file |
Нативные изображения | 10 МБ |
send_document |
Вложения файлов | 20 МБ |
send_voice |
Голосовые сообщения (только AMR для нативного голоса) | 2 МБ |
send_video |
Видеосообщения | 10 МБ |
| Чанковая загрузка: Файлы загружаются по частям по 512 КБ через трёхшаговый протокол (init → chunks → finish). Адаптер обрабатывает это автоматически. | ||
| Автоматическое понижение: Когда медиа превышает лимит размера нативного типа, но не превышает абсолютный лимит в 20 МБ, оно автоматически отправляется как обычное файловое вложение: | ||
| * Изображения > 10 МБ → отправляются как файл | ||
| * Видео > 10 МБ → отправляются как файл | ||
| * Голос > 2 МБ → отправляется как файл | ||
| * Аудио не в формате AMR → отправляется как файл (WeCom поддерживает только AMR для нативного голоса) |
Файлы, превышающие абсолютный лимит в 20 МБ, отклоняются с отправкой информационного сообщения в чат.
Потоковые ответы в режиме ответа¶
Когда бот получает сообщение через callback WeCom, адаптер запоминает ID входящего запроса. Если ответ отправляется, пока контекст запроса ещё активен, адаптер использует режим ответа WeCom (aibot_respond_msg) с потоковой передачей, чтобы привязать ответ непосредственно к входящему сообщению. Это обеспечивает более естественный диалог в клиенте WeCom.
Если контекст входящего запроса истёк или недоступен, адаптер переключается на упреждающую отправку сообщений через aibot_send_msg.
Режим ответа также работает для медиа: загруженные медиафайлы могут быть отправлены как ответ на исходное сообщение.
Подключение и переподключение¶
Адаптер поддерживает постоянное WebSocket-соединение со шлюзом WeCom по адресу wss://openws.work.weixin.qq.com.
Жизненный цикл соединения¶
- Подключение: Открывает WebSocket-соединение и отправляет кадр аутентификации
aibot_subscribeс bot_id и secret. - Heartbeat: Отправляет ping-кадры прикладного уровня каждые 30 секунд для поддержания соединения.
- Прослушивание: Непрерывно читает входящие кадры и диспетчеризирует колбэки сообщений.
Поведение при переподключении¶
При потере соединения адаптер использует экспоненциальную задержку для переподключения:
Попытка| Задержка
---|---
1-я повторная| 2 секунды
2-я повторная| 5 секунд
3-я повторная| 10 секунд
4-я повторная| 30 секунд
5-я и далее| 60 секунд
После каждого успешного переподключения счётчик задержки сбрасывается. Все ожидающие ответа фьючерсы завершаются ошибкой при отключении, чтобы вызывающие стороны не зависали бесконечно.
Дедупликация¶
Входящие сообщения дедуплицируются по ID сообщений с окном в 5 минут и максимальным кешем на 1000 записей. Это предотвращает двойную обработку сообщений при переподключении или сетевых сбоях.
Все переменные окружения¶
Переменная| Обязательная| По умолчанию| Описание
---|---|---|---|---
WECOM_BOT_ID| ✅| —| ID AI-бота WeCom
WECOM_SECRET| ✅| —| Секретный ключ AI-бота WeCom
WECOM_ALLOWED_USERS| —| (пусто)| ID пользователей через запятую для белого списка уровня шлюза
WECOM_HOME_CHANNEL| —| —| ID чата для вывода cron/уведомлений
WECOM_WEBSOCKET_URL| —| wss://openws.work.weixin.qq.com| URL WebSocket-шлюза
WECOM_DM_POLICY| —| open| Политика доступа в ЛС
WECOM_GROUP_POLICY| —| open| Политика доступа в группах
Устранение неполадок¶
| Проблема | Решение |
|---|---|
WECOM_BOT_ID and WECOM_SECRET are required |
Установите обе переменные окружения или настройте через мастер установки |
WeCom startup failed: aiohttp not installed |
Установите aiohttp: pip install aiohttp |
WeCom startup failed: httpx not installed |
Установите httpx: pip install httpx |
invalid secret (errcode=40013) |
Проверьте, что секрет соответствует учётным данным вашего бота |
Timed out waiting for subscribe acknowledgement |
Проверьте сетевое подключение к openws.work.weixin.qq.com |
| Бот не отвечает в группах | Проверьте настройку group_policy и убедитесь, что ID группы есть в group_allow_from |
| Бот игнорирует некоторых пользователей в группе | Проверьте списки allow_from для конкретной группы в разделе конфигурации groups |
| Ошибка расшифровки медиа | Установите cryptography: pip install cryptography |
cryptography is required for WeCom media decryption |
Входящее медиа зашифровано AES. Установите: pip install cryptography |
| Голосовые сообщения отправляются как файлы | WeCom поддерживает только формат AMR для нативного голоса. Другие форматы автоматически понижаются до файла. |
Ошибка File too large |
У WeCom абсолютный лимит 20 МБ на все загрузки файлов. Сожмите или разделите файл. |
| Изображения отправляются как файлы | Изображения > 10 МБ превышают лимит нативных изображений и автоматически понижаются до вложений-файлов. |
Timeout sending message to WeCom |
Возможно, WebSocket отключился. Проверьте логи на наличие сообщений о переподключении. |
WeCom websocket closed during authentication |
Сетевая проблема или неверные учётные данные. Проверьте bot_id и secret. |
| * Требования | |
| * Настройка | |
| * Шаг 1: Создание AI-бота | |
| * Шаг 2: Настройка Hermes | |
| * Шаг 3: Запуск шлюза | |
| * Возможности | |
| * Параметры конфигурации | |
| * Политики доступа | |
| * Политика для личных сообщений (DM) | |
| * Политика для групп | |
| * Белые списки отправителей для каждой группы | |
| * Поддержка медиа | |
| * Входящие (получение) | |
| * Расшифровка AES-зашифрованных медиа | |
| * Исходящие (отправка) | |
| * Потоковые ответы в режиме ответа | |
| * Подключение и переподключение | |
| * Жизненный цикл соединения | |
| * Поведение при переподключении | |
| * Дедупликация | |
| * Все переменные окружения | |
| * Устранение неполадок |