Larksuite (Feishu)
Feishu (国内版) et Lark Suite (海外版) partagent la même surface OpenAPI. Le provider Ongrid les traite comme une seule intégration ; choisissez la base URL qui matche votre tenant.
| Mode | Ce que ça fait |
|---|---|
| Notification | Push d'alerte vers un groupe Feishu/Lark via webhook de bot personnalisé. |
| Pont IM | Chat agent bidirectionnel via la long-connection WebSocket. |
Mode notification (bot personnalisé)
Le sender Feishu poste un payload de bot personnalisé Feishu / Lark à l'URL de webhook que votre administrateur de bot fournit. Forme du 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>"
}Signature — champ sign
Quand vous activez 签名校验 (vérification de signature) sur le bot personnalisé Feishu, Feishu vous donne un secret partagé. Le sender calcule le champ sign comme :
stringToSign = timestamp + "\n" + secret
sign = base64(HMAC-SHA256(key=stringToSign, message=<empty>))Oui — le secret prend le rôle à la fois de matière de clé pour HMAC et de partie du string-to-sign. C'est l'algorithme que Feishu documente, et c'est ce que signFeishu implémente.
Si vous laissez le champ Secret vide, Ongrid poste sans sign / timestamp — utilisable seulement quand votre bot a la vérification de signature désactivée (ou a une allowlist IP à la place).
Setup
- Dans le groupe Feishu → 设置 → 群机器人 → 添加机器人 → 自定义机器人. Donnez-lui un nom et un avatar.
- Cochez 签名校验 ; copiez le secret.
- Copiez l'URL du webhook — ressemble à
https://open.feishu.cn/open-apis/bot/v2/hook/<uuid>(ou…/open.larksuite.com/…pour Lark Suite). - Dans Ongrid : Settings → Channels → New → Provider =
feishu→ Endpoint = l'URL de webhook → Secret = le secret de signature.
Bot personnalisé ≠ App
Le mode notification utilise un bot personnalisé (scope groupe, webhook uniquement). Le mode pont IM utilise une app Feishu (scope tenant, OAuth + events). Ce sont des concepts différents ; les credentials ne se chevauchent pas.
Mode pont IM (stream long-connection)
Le pont bidirectionnel utilise la long-connection Feishu livrée par le client officiel github.com/larksuite/oapi-sdk-go/v3/ws. Le manager se connecte à l'endpoint d'événement de Feishu et Feishu pousse les événements sur le WebSocket — aucune URL de webhook publique requise.
Pourquoi stream et pas webhook
Le mode webhook (mode=webhook) est supporté dans le schéma pour rétro-compat, mais le stream long-connection est le chemin recommandé :
- Pas d'ingress public nécessaire sur le manager.
- Réutilise le reconnect-with-backoff du superviseur (le SDK a son propre reconnect ; le superviseur ajoute une boucle externe pour les échecs terminaux).
- Le SDK gère la vérification de signature + le déchiffrement AES en interne, donc vous n'avez pas besoin de remplir
encrypt_keypour la variante stream — c'est webhook-only.
Mapping des credentials
Colonne im_apps | Signification Feishu |
|---|---|
provider | "feishu" |
mode | "stream" (recommandé) ou "webhook" |
app_id | Feishu app_id (cli_…). |
app_secret | Feishu app_secret. |
verify_token | Optionnel. Utilisé par la vérification de signature en mode webhook. |
encrypt_key | Requis en mode webhook, ignoré en mode stream. |
allow_from | Optionnel. Feishu est gaté par tenant donc l'allowlist est non-obligatoire. |
default_locale
Mettez zh pour un tenant Feishu dont les opérateurs écrivent en chinois, en pour une équipe Lark anglophone. Vide (défaut) signifie que le LLM mirror l'utilisateur.
Setup
- 开发者后台 → 创建企业自建应用. Obtenez
app_id+app_secret. - 应用功能 → 机器人 → activer. Ajoutez le bot à votre chat de test.
- 权限管理 → accorder :
im:message— lire les messages adressés au bot.im:message.group_at_msg— événements de mention de groupe.im:message.p2p_msg— événements de DM.im:message:send_as_bot—SendText/EditText.
- 事件订阅 → 长连接模式 (long-connection) → activer.
- Dans Ongrid : Settings → IM bridge → New → Provider =
feishu→ Mode =stream→ collerapp_id+app_secret. Save et Enable. @le bot dans le chat. L'agent le récupère.
Mise en cache tenant_access_token
Les appels sortants (SendText, EditText) s'authentifient avec un tenant_access_token, rafraîchi proactivement quand on est à moins de 200s de l'expiration. Le token est cached par instance de Client, protégé par un sync.Mutex ; rotater les credentials signifie reconstruire le client. Voir tenantAccessToken.
msg_type est requis aussi sur les edits
Le PUT /open-apis/im/v1/messages/<id> de Feishu requiert msg_type dans le corps — l'omettre renvoie code: 99992402 (échec de validation de champ) même si la page de doc pour « edit message » ne le rend pas évident. Le provider envoie toujours msg_type: text.
Mode webhook (legacy, conservé pour compatibilité)
Le mode webhook est encore sélectionnable dans l'UI ; le superviseur vérifie les signatures et déchiffre les payloads lui-même.
Vérification de signature
Le handler HTTP lit X-Lark-Signature et exécute VerifyEventSignature :
sig = sha256(timestamp + nonce + encrypt_key + body), hex-encodedOui — SHA-256, pas HMAC. L'encrypt_key joue le rôle de secret partagé dans l'input du hash. Le vérificateur ne panique jamais sur un input mauvais ; un mismatch renvoie ErrBadSignature.
Déchiffrement du payload
Quand encrypt_key est posé, Feishu enveloppe le JSON d'événement en AES-256-CBC. Le déchiffrement utilise :
- Clé :
SHA-256(encrypt_key). - IV : les 16 premiers octets du ciphertext base64-décodé.
- Padding : PKCS#7.
Voir DecryptEvent.
Choisissez le mode stream si possible
Le mode webhook nécessite un endpoint HTTPS public et la plomberie encrypt_key ci-dessus. Le stream long-connection évite les deux. Tendez la main vers le mode webhook seulement quand vous en avez spécifiquement besoin (par ex. intégrer les événements Feishu à un routeur de webhooks publics existant).
Particularités
- Le client stream Feishu n'impose pas
allow_fromaujourd'hui — la plateforme Feishu elle-même est gatée par tenant, donc seuls les membres de l'entreprise atteignent le bot. Si votre tenant a des invités / collaborateurs externes, remplissezallow_fromavec leurs valeursopen_idpour verrouiller la conversation plus loin. - Les stickers, fichiers, cartes et messages riches sont droppés (seul
msg_type == "text"déclenche l'agent). Même contrat S1 que Telegram / Slack. - Le champ
RootIdest capturé commeImThread.ImThreadIDpour que les réponses à l'intérieur d'un thread continuent la même session — pas besoin pour l'utilisateur de reset le contexte par question.