Skip to content

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.

ModusWas er tut
NotificationAlarm-Push an eine Feishu/Lark-Gruppe via Custom-Bot-Webhook.
IM bridgeZweiseitiger 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:

json
{
  "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:

text
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

  1. In der Feishu-Gruppe → 设置 → 群机器人 → 添加机器人 → 自定义机器人. Geben Sie ihm einen Namen und ein Avatar.
  2. 签名校验 aktivieren; das Secret kopieren.
  3. 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).
  4. 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_key für die Stream-Variante nicht ausfüllen müssen — das ist nur für Webhook.

Credential-Mapping

im_apps-SpalteFeishu-Bedeutung
provider"feishu"
mode"stream" (empfohlen) oder "webhook"
app_idFeishu app_id (cli_…).
app_secretFeishu app_secret.
verify_tokenOptional. Von Webhook-Mode-Signaturverifizierung verwendet.
encrypt_keyErforderlich im Webhook-Mode, im Stream-Mode ignoriert.
allow_fromOptional. 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

  1. 开发者后台 → 创建企业自建应用. app_id + app_secret holen.
  2. 应用功能 → 机器人 → aktivieren. Den Bot zu Ihrem Test-Chat hinzufügen.
  3. 权限管理 → 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_botSendText / EditText.
  4. 事件订阅 → 长连接模式 (Long-Connection) → aktivieren.
  5. In Ongrid: Settings → IM bridge → New → Provider = feishu → Mode = streamapp_id + app_secret einfügen. Save und Enable.
  6. 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:

text
sig = sha256(timestamp + nonce + encrypt_key + body), hex-codiert

Ja — 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 Sie allow_from mit ihren open_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 als ImThread.ImThreadID erfasst, sodass Antworten innerhalb eines Threads dieselbe Session fortsetzen — der Benutzer muss den Kontext nicht pro Frage zurücksetzen.