Larksuite (Feishu)
Feishu (国内版) и Lark Suite (海外版) разделяют ту же поверхность OpenAPI. Provider Ongrid трактует их как одну интеграцию; выберите базовый URL, который соответствует вашему тенанту.
| Режим | Что он делает |
|---|---|
| Notification | Пуш алертов в Feishu/Lark-группу через webhook кастомного бота. |
| IM bridge | Двусторонний чат с агентом через WebSocket long-connection. |
Notification-режим (кастомный бот)
Sender Feishu постит payload Feishu / Lark кастомного бота на webhook URL, который предоставляет администратор вашего бота. Форма payload:
{
"msg_type": "text",
"content": {"text": "[CRITICAL] swap_high node-01\nswap_in_pages > 1000 for 5m\nsource: alert\ndedupe: alert:swap_high:device=7"},
"timestamp": "1717012345",
"sign": "<base64-hmac>"
}Подпись — поле sign
Когда вы включаете 签名校验 (signature verification) на кастомном боте Feishu, Feishu выдаёт вам shared secret. Sender вычисляет поле sign как:
stringToSign = timestamp + "\n" + secret
sign = base64(HMAC-SHA256(key=stringToSign, message=<empty>))Да — secret выполняет роль и key material для HMAC, и части string-to-sign. Это алгоритм, который документирует Feishu, и это то, что реализует signFeishu.
Если вы оставляете поле Secret пустым, Ongrid постит без sign / timestamp — пригодно только когда у вашего бота signature verification выключена (или есть IP allowlist вместо).
Настройка
- В Feishu-группе → 设置 → 群机器人 → 添加机器人 → 自定义机器人. Дайте имя и аватар.
- Отметьте 签名校验; скопируйте secret.
- Скопируйте webhook URL — выглядит как
https://open.feishu.cn/open-apis/bot/v2/hook/<uuid>(или…/open.larksuite.com/…для Lark Suite). - В Ongrid: Settings → Channels → New → Provider =
feishu→ Endpoint = webhook URL → Secret = signing secret.
Кастомный бот ≠ App
Notification-режим использует кастомного бота (group-scoped, только webhook). IM bridge-режим использует Feishu app (tenant-scoped, OAuth
- events). Это разные концепции; credentials не перекрываются.
IM bridge-режим (long-connection stream)
Двусторонний bridge использует Feishu long-connection, доставленный официальным github.com/larksuite/oapi-sdk-go/v3/ws клиентом. Manager дозванивается на event-эндпоинт Feishu, и Feishu пушит события через WebSocket — публичный webhook URL не требуется.
Почему stream, а не webhook
Webhook-режим (mode=webhook) поддерживается в схеме для back-compat, но long-connection stream — рекомендуемый путь:
- Не нужен публичный ingress на manager.
- Переиспользует reconnect-with-backoff supervisor (у SDK есть собственный reconnect; supervisor добавляет внешнюю петлю для терминальных отказов).
- SDK обрабатывает signature verification + AES-расшифровку внутри, так что вам не нужно заполнять
encrypt_keyдля stream-варианта — это только для webhook.
Маппинг credentials
Столбец im_apps | Значение в Feishu |
|---|---|
provider | "feishu" |
mode | "stream" (рекомендуется) или "webhook" |
app_id | Feishu app_id (cli_…). |
app_secret | Feishu app_secret. |
verify_token | Опционально. Используется signature verification в webhook-режиме. |
encrypt_key | Обязательно в webhook-режиме, игнорируется в stream-режиме. |
allow_from | Опционально. Feishu tenant-gated, так что allowlist не обязателен. |
default_locale
Поставьте zh для Feishu-тенанта, чьи операторы пишут на китайском, en для англоязычной Lark-команды. Пустое (по умолчанию) означает, что LLM зеркалит пользователя.
Настройка
- 开发者后台 → 创建企业自建应用. Получите
app_id+app_secret. - 应用功能 → 机器人 → включить. Добавьте бота в ваш тестовый чат.
- 权限管理 → grant:
im:message— читать сообщения, адресованные боту.im:message.group_at_msg— события group-mention.im:message.p2p_msg— события DM.im:message:send_as_bot—SendText/EditText.
- 事件订阅 → 长连接模式 (long-connection) → включить.
- В Ongrid: Settings → IM bridge → New → Provider =
feishu→ Mode =stream→ вставитьapp_id+app_secret. Сохранить и Enable. @бота в чате. Агент его подхватит.
Кэширование tenant_access_token
Исходящие вызовы (SendText, EditText) аутентифицируются через tenant_access_token, обновляемый проактивно, когда в пределах 200с до expiry. Токен кэшируется per-Client экземпляр, защищён sync.Mutex; ротация credentials означает пересборку клиента. См. tenantAccessToken.
msg_type обязательно и на edits
PUT /open-apis/im/v1/messages/<id> Feishu требует msg_type в теле — пропуск возвращает code: 99992402 (field validation failed), даже если страница документации для «edit message» этого не делает очевидным. Provider всегда отправляет msg_type: text.
Webhook-режим (legacy, оставлен для совместимости)
Webhook-режим всё ещё выбираем в UI; supervisor сам проверяет подписи и расшифровывает payload.
Signature verification
HTTP-handler читает X-Lark-Signature и запускает VerifyEventSignature:
sig = sha256(timestamp + nonce + encrypt_key + body), hex-encodedДа — SHA-256, не HMAC. encrypt_key играет роль shared-secret внутри hash input. Verifier никогда не паникует на плохом вводе; mismatch возвращает ErrBadSignature.
Расшифровка payload
Когда encrypt_key установлен, Feishu оборачивает event JSON в AES-256-CBC. Расшифровка использует:
- Key:
SHA-256(encrypt_key). - IV: первые 16 байт base64-декодированного ciphertext.
- Padding: PKCS#7.
См. DecryptEvent.
Выбирайте stream-режим, если можете
Webhook-режим требует публичного HTTPS-эндпоинта и encrypt_key- обвязки выше. Long-connection stream избегает обоих. Тянитесь к webhook- режиму, только когда вам это нужно (например, интегрировать события Feishu с существующим публичным webhook-роутером).
Особенности
- Feishu stream client сегодня не форсит
allow_from— сама платформа Feishu tenant-gated, так что только enterprise-члены достают до бота. Если у вашего тенанта есть гости / внешние коллабораторы, заполнитеallow_fromих значениямиopen_id, чтобы заблокировать разговор сильнее. - Стикеры, файлы, карты и rich-сообщения отбрасываются (только
msg_type == "text"триггерит агента). Тот же S1-контракт, что у Telegram / Slack. - Поле
RootIdзахватывается какImThread.ImThreadID, так что ответы внутри треда продолжают ту же сессию — нет необходимости пользователю ресетить контекст на каждый вопрос.