WeCom (Корпоративный WeChat)
Подключите VibeOS к WeCom (企业微信) — корпоративной мессенджер-платформе от Tencent. Адаптер использует WebSocket-шлюз AI-бота WeCom для двунаправленной связи в реальном времени — без необходимости в публичном эндпоинте или вебхуке.
См. также: WeCom Callback для настройки входящих вебхуков.
Предварительные требования
- Учётная запись организации в WeCom
- AI-бот, созданный в консоли администратора WeCom
- ID бота и секретный ключ со страницы учётных данных бота
- Пакеты Python:
aiohttpиhttpx
Настройка
Шаг 1: Создание AI-бота
Рекомендуемый способ: создание по QR-коду (одна команда)
vibeos gateway setup
Выберите WeCom и отсканируйте QR-код с помощью мобильного приложения WeCom. VibeOS автоматически создаст приложение-бота с правильными разрешениями и сохранит учётные данные.
Мастер настройки выполнит следующие действия:
- Отобразит QR-код в вашем терминале
- Дождётся сканирования с помощью мобильного приложения WeCom
- Автоматически получит ID бота и секретный ключ
- Проведёт вас через настройку контроля доступа
Альтернативный способ: ручная настройка
Если создание по QR-коду недоступно, мастер переключится на ручной ввод:
- Войдите в консоль администратора WeCom
- Перейдите в Приложения → Создать приложение → AI-бот
- Настройте имя и описание бота
- Скопируйте ID бота и секретный ключ со страницы учётных данных
- Запустите
vibeos gateway setup, выберите WeCom и введите учётные данные по запросу
Храните секретный ключ бота в тайне. Любой, кто им завладеет, сможет выдать себя за вашего бота.
Шаг 2: Настройка VibeOS
Вариант A: интерактивная настройка (рекомендуется)
vibeos gateway setup
Выберите WeCom и следуйте инструкциям. Мастер проведёт вас через:
- Учётные данные бота (через QR-код или ручной ввод)
- Настройки контроля доступа (белый список, режим сопряжения или открытый доступ)
- Домашний канал для уведомлений
Вариант B: ручная настройка
Добавьте следующее в ~/.vibeos/.env:
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
Шаг 3: Запуск шлюза
vibeos gateway
Возможности
- Транспорт WebSocket — постоянное соединение, не требуется публичный эндпоинт
- Личные и групповые сообщения — настраиваемые политики доступа
- Белые списки отправителей для каждой группы — тонкий контроль над тем, кто может взаимодействовать в каждой группе
- Поддержка медиа — загрузка и скачивание изображений, файлов, голосовых сообщений и видео
- AES-шифрование медиа — автоматическая расшифровка входящих вложений
- Контекст цитирования — сохранение цепочек ответов
- Рендеринг Markdown — форматированные текстовые ответы
- Привязка ответов — ответы привязываются к контексту входящего сообщения
- Автопереподключение — экспоненциальная задержка при обрывах соединения
Адаптер WeCom доставляет каждый ответ как одно полное сообщение — он не передаёт ответы по токенам и не показывает индикатор набора текста. «Привязка ответов» (ниже) только связывает ответ с входящим запросом; это не потоковая передача в реальном времени.
Параметры конфигурации
Установите их в 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 | {} | Конфигурация для каждой группы (см. ниже) |
Политики доступа
Политика для личных сообщений
Определяет, кто может отправлять боту личные сообщения:
| Значение | Поведение |
|---|---|
open | Любой может писать боту в ЛС (по умолчанию) |
allowlist | Только пользователи из allow_from могут писать в ЛС |
disabled | Все ЛС игнорируются |
pairing | Режим сопряжения (для начальной настройки) |
WECOM_DM_POLICY=allowlist
Политика для групп
Определяет, в каких группах бот отвечает:
| Значение | Поведение |
|---|---|
open | Бот отвечает во всех группах (по умолчанию) |
allowlist | Бот отвечает только в группах из group_allow_from |
disabled | Все групповые сообщения игнорируются |
WECOM_GROUP_POLICY=allowlist
Белые списки отправителей для каждой группы
Для тонкого контроля вы можете ограничить, какие пользователи могут взаимодействовать с ботом в определённых группах. Настраивается в config.yaml:
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"
Как это работает:
group_policyиgroup_allow_fromопределяют, разрешена ли группа в принципе.- Если группа проходит проверку верхнего уровня, список
groups.<group_id>.allow_from(если задан) дополнительно ограничивает отправителей внутри этой группы, которые могут взаимодействовать с ботом. - Запись с подстановочным знаком
"*"служит значением по умолчанию для групп, не указанных явно. - Записи в белом списке поддерживают подстановочный знак
*для разрешения всех пользователей, и записи нечувствительны к регистру. - Записи могут опционально использовать префикс
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 КБ через трёхэтапный протокол (инициализация → фрагменты → завершение). Адаптер обрабатывает это автоматически.
Автоматическое понижение: Когда медиа превышает лимит размера нативного типа, но находится в пределах абсолютного лимита в 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с ID бота и секретным ключом. - 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 и секретный ключ. |