Larksuite (Feishu)
Feishu (国内版) und Lark Suite (海外版) teilen dieselbe OpenAPI-Oberfläche. Der Ongrid-Provider behandelt sie als eine Integration; wählen Sie die Base-URL, die zu Ihrem Tenant passt.
| Modus | Was er tut |
|---|---|
| Notification | Alarm-Push an eine Feishu/Lark-Gruppe via Custom-Bot-Webhook. |
| IM bridge | Zweiseitiger Agenten-Chat mit der WebSocket-Long-Connection. |
Notification-Modus (Custom Bot)
Der Feishu-Sender postet ein Feishu- / Lark-Custom-Bot-Payload an die Webhook-URL, die Ihr Bot-Administrator bereitstellt. Payload-Form:
{
"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>"
}Signatur — sign-Feld
Wenn Sie 签名校验 (Signaturverifizierung) auf dem Feishu-Custom-Bot einschalten, händigt Feishu Ihnen ein geteiltes Secret aus. Der Sender berechnet das Sign-Feld als:
stringToSign = timestamp + "\n" + secret
sign = base64(HMAC-SHA256(key=stringToSign, message=<empty>))Ja — das Secret übernimmt die Rolle sowohl von Key-Material für HMAC als auch als Teil des String-to-Sign. Das ist der Algorithmus, den Feishu dokumentiert, und das ist, was signFeishu implementiert.
Wenn Sie das Secret-Feld leer lassen, postet Ongrid ohne sign / timestamp — nur nutzbar, wenn Ihr Bot Signaturverifizierung ausgeschaltet hat (oder stattdessen IP-Allowlisting hat).
Setup
- In der Feishu-Gruppe → 设置 → 群机器人 → 添加机器人 → 自定义机器人. Geben Sie ihm einen Namen und ein Avatar.
- 签名校验 aktivieren; das Secret kopieren.
- Die Webhook-URL kopieren — sieht aus wie
https://open.feishu.cn/open-apis/bot/v2/hook/<uuid>(oder…/open.larksuite.com/…für Lark Suite). - In Ongrid: Settings → Channels → New → Provider =
feishu→ Endpoint = die Webhook-URL → Secret = das Signatur-Secret.
Custom Bot ≠ App
Der Notification-Modus verwendet einen Custom Bot (Group-Scoped, nur Webhook). Der IM-Bridge-Modus verwendet eine Feishu App (Tenant-Scoped, OAuth + Events). Es sind verschiedene Konzepte; die Credentials überlappen nicht.
IM-Bridge-Modus (Long-Connection-Stream)
Der zweiseitige Bridge verwendet die Feishu-Long-Connection, ausgeliefert vom offiziellen github.com/larksuite/oapi-sdk-go/v3/ws-Client. Der Manager wählt Feishus Event-Endpunkt, und Feishu pusht Events über die WebSocket — keine öffentliche Webhook-URL erforderlich.
Warum Stream und nicht Webhook
Der Webhook-Modus (mode=webhook) wird im Schema für Rückwärtskompatibilität unterstützt, aber der Long-Connection-Stream ist der empfohlene Pfad:
- Kein öffentliches Ingress auf dem Manager nötig.
- Wiederverwendet das Reconnect-with-Backoff des Supervisors (das SDK hat sein eigenes Reconnect; der Supervisor fügt eine äußere Loop für terminale Fehler hinzu).
- Das SDK handhabt Signaturverifizierung + AES-Entschlüsselung intern, sodass Sie
encrypt_keyfür die Stream-Variante nicht ausfüllen müssen — das ist nur für Webhook.
Credential-Mapping
im_apps-Spalte | Feishu-Bedeutung |
|---|---|
provider | "feishu" |
mode | "stream" (empfohlen) oder "webhook" |
app_id | Feishu app_id (cli_…). |
app_secret | Feishu app_secret. |
verify_token | Optional. Von Webhook-Mode-Signaturverifizierung verwendet. |
encrypt_key | Erforderlich im Webhook-Mode, im Stream-Mode ignoriert. |
allow_from | Optional. Feishu ist tenant-gated, sodass die Allowlist nicht-verpflichtend ist. |
default_locale
Auf zh für einen Feishu-Tenant setzen, dessen Operatoren Chinesisch schreiben, auf en für ein englisches Lark-Team. Leer (Default) bedeutet, das LLM spiegelt den Benutzer.
Setup
- 开发者后台 → 创建企业自建应用.
app_id+app_secretholen. - 应用功能 → 机器人 → aktivieren. Den Bot zu Ihrem Test-Chat hinzufügen.
- 权限管理 → gewähren:
im:message— an den Bot adressierte Nachrichten lesen.im:message.group_at_msg— Group-Mention-Events.im:message.p2p_msg— DM-Events.im:message:send_as_bot—SendText/EditText.
- 事件订阅 → 长连接模式 (Long-Connection) → aktivieren.
- In Ongrid: Settings → IM bridge → New → Provider =
feishu→ Mode =stream→app_id+app_secreteinfügen. Save und Enable. - Den Bot im Chat mit
@adressieren. Der Agent nimmt es auf.
tenant_access_token-Caching
Ausgehende Aufrufe (SendText, EditText) authentifizieren sich mit einem tenant_access_token, proaktiv refresht, wenn innerhalb 200s vor Ablauf. Das Token wird per-Client-Instanz gecacht, durch einen sync.Mutex geschützt; Credentials rotieren bedeutet, den Client neu zu bauen. Siehe tenantAccessToken.
msg_type ist auch bei Edits erforderlich
Feishus PUT /open-apis/im/v1/messages/<id> erfordert msg_type im Body — es wegzulassen gibt code: 99992402 (field validation failed) zurück, auch wenn die Docs-Seite für „edit message" das nicht offensichtlich macht. Der Provider sendet immer msg_type: text.
Webhook-Mode (Legacy, für Kompatibilität behalten)
Webhook-Mode ist weiterhin in der UI auswählbar; der Supervisor verifiziert Signaturen und entschlüsselt Payloads selbst.
Signaturverifizierung
Der HTTP-Handler liest X-Lark-Signature und führt VerifyEventSignature aus:
sig = sha256(timestamp + nonce + encrypt_key + body), hex-codiertJa — SHA-256, nicht HMAC. Der encrypt_key spielt die Shared-Secret-Rolle innerhalb des Hash-Inputs. Der Verifier panic't nie bei schlechtem Input; Mismatch gibt ErrBadSignature zurück.
Payload-Entschlüsselung
Wenn encrypt_key gesetzt ist, wickelt Feishu das Event-JSON in AES-256-CBC. Die Entschlüsselung verwendet:
- Key:
SHA-256(encrypt_key). - IV: die ersten 16 Bytes der base64-decodierten Chiffretexts.
- Padding: PKCS#7.
Siehe DecryptEvent.
Wählen Sie Stream-Mode, wenn Sie können
Webhook-Mode erfordert einen öffentlichen HTTPS-Endpunkt und die encrypt_key-Verklemmung oben. Long-Connection-Stream vermeidet beides. Greifen Sie nur dann zum Webhook-Mode, wenn Sie es spezifisch brauchen (z. B. Feishu-Events mit einem bestehenden öffentlichen Webhook-Router integrieren).
Eigenheiten
- Der Feishu-Stream-Client erzwingt heute kein
allow_from— die Feishu-Plattform selbst ist tenant-gated, sodass nur Enterprise-Mitglieder den Bot erreichen. Wenn Ihr Tenant Gäste / externe Mitarbeiter hat, füllen Sieallow_frommit ihrenopen_id-Werten, um die Konversation weiter zu sperren. - Sticker, Dateien, Karten und Rich Messages werden gedroppt (nur
msg_type == "text"triggert den Agenten). Gleicher S1-Vertrag wie Telegram / Slack. - Das
RootId-Feld wird alsImThread.ImThreadIDerfasst, sodass Antworten innerhalb eines Threads dieselbe Session fortsetzen — der Benutzer muss den Kontext nicht pro Frage zurücksetzen.