Skip to content

Larksuite(飞书)

飞书(国内版)和 Lark Suite(海外版)共享同一套 OpenAPI。Ongrid 的 provider 把它们当作同一种集成;按你的租户选 base URL 即可。

模式行为
Notification通过自定义机器人 webhook 推告警到飞书/Lark 群。
IM bridge通过 WebSocket 长连接做双向 Agent 对话。

Notification 模式(自定义机器人)

飞书 sender 把飞书 / Lark 自定义机器人载荷 POST 到 bot 管理员给的 webhook URL。载荷形态:

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>"
}

签名 —— sign 字段

在飞书自定义机器人上开启 签名校验 时,飞书会给你一个共享 secret。sender 这样算 sign:

text
stringToSign = timestamp + "\n" + secret
sign         = base64(HMAC-SHA256(key=stringToSign, message=<empty>))

是的 —— secret 同时承担 HMAC 的 key 和参与 string-to-sign 两个角色。这是飞书文档定义的算法,signFeishu 是其实现。

Secret 留空的话,Ongrid 不带 sign / timestamp 直接 POST —— 只有当你的 bot 关闭了签名校验(或改用 IP 白名单)时才能跑通。

配置

  1. 在飞书群 → 设置 → 群机器人 → 添加机器人 → 自定义机器人。给它一个名字和头像。
  2. 签名校验,复制 secret。
  3. 复制 webhook URL —— 长得像 https://open.feishu.cn/open-apis/bot/v2/hook/<uuid>(Lark Suite 是 …/open.larksuite.com/…)。
  4. 在 Ongrid:Settings → Channels → New → Provider = feishu → Endpoint = webhook URL → Secret = 签名 secret。

自定义机器人 ≠ App

通知模式用 自定义机器人(仅群作用域、仅 webhook)。IM bridge 模式用飞书 App(租户作用域、OAuth + 事件)。两个是不同概念,凭据互不通用。

IM bridge 模式(长连接 stream)

双向 bridge 用 飞书长连接,承载方是官方 github.com/larksuite/oapi-sdk-go/v3/ws 客户端。manager 主动连到飞书事件端点,飞书通过 WebSocket 推事件 —— 不需要任何公网 webhook URL。

为什么选 stream 而非 webhook

为了向后兼容,schema 里保留 webhook 模式(mode=webhook),但长连接 stream 才是推荐路径:

  • manager 不需要任何公网入口。
  • 复用 supervisor 的 reconnect-with-backoff(SDK 自己也有重连;supervisor 给终止类失败加一层外层循环)。
  • SDK 内部处理签名校验 + AES 解密,所以 stream 模式不用填 encrypt_key —— encrypt_key 仅 webhook 模式需要。

字段映射

im_apps飞书含义
provider"feishu"
mode"stream"(推荐)或 "webhook"
app_id飞书 app_idcli_…)。
app_secret飞书 app_secret
verify_token可选。webhook 模式签名校验用。
encrypt_keywebhook 模式必填,stream 模式忽略。
allow_from可选。飞书天然受租户门控,白名单不强制。

default_locale

运维写中文的飞书租户填 zh;英文 Lark 团队填 en。空(默认)让 LLM 跟随用户。

配置步骤

  1. 开发者后台 → 创建企业自建应用。拿到 app_id + app_secret
  2. 应用功能 → 机器人 → 启用。把 bot 加进测试群。
  3. 权限管理 → 授予:
    • im:message —— 读发给 bot 的消息。
    • im:message.group_at_msg —— 群 @ 事件。
    • im:message.p2p_msg —— DM 事件。
    • im:message:send_as_bot —— SendText / EditText
  4. 事件订阅 → 长连接模式 (long-connection) → 启用。
  5. 在 Ongrid:Settings → IM bridge → New → Provider = feishu → Mode = stream → 粘 app_id + app_secret。保存并 Enable
  6. 在群里 @ bot。Agent 接管。

tenant_access_token 缓存

出站调用(SendTextEditText)用 tenant_access_token 鉴权,过期前 200s 内主动续期。token 按 Client 实例缓存,由 sync.Mutex 保护;换凭据就要重建 client。见 tenantAccessToken

编辑也必须带 msg_type

飞书的 PUT /open-apis/im/v1/messages/<id> 要求 body 里带 msg_type —— 不带就返 code: 99992402(字段校验失败),尽管"编辑消息"那篇文档没把这点写明显。provider 一律带 msg_type: text

Webhook 模式(遗留,保留兼容)

UI 里 webhook 模式仍可选;supervisor 自己做签名校验和载荷解密。

签名校验

HTTP handler 读 X-Lark-Signature 然后跑 VerifyEventSignature

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

是的 —— SHA-256 而非 HMAC。encrypt_key 在哈希输入里扮演共享 secret 的角色。校验器永远不会因坏输入 panic;不匹配返回 ErrBadSignature

载荷解密

设置了 encrypt_key 时,飞书把事件 JSON 包成 AES-256-CBC。解密用:

  • Key:SHA-256(encrypt_key)
  • IV:base64 解码后的前 16 字节。
  • Padding:PKCS#7。

DecryptEvent

能用 stream 就用 stream

Webhook 模式需要公网 HTTPS 端点 + 上面那套 encrypt_key 装配。长连接 stream 两个都不需要。仅在确实需要时(比如要把飞书事件接到已有的公网 webhook 路由)才用 webhook 模式。

小坑

  • 飞书 stream 客户端今天不强制 allow_from —— 飞书平台本身就有租户门控,只有企业成员能找到 bot。如果租户里有访客 / 外部合作者,把他们的 open_id 填进 allow_from,可以进一步收紧对话。
  • 贴纸、文件、卡片、富文本会被丢(只有 msg_type == "text" 触发 Agent)。和 Telegram / Slack 同一份 S1 契约。
  • RootId 字段被捕获为 ImThread.ImThreadID,所以 thread 内回复延续同一会话 —— 用户不用每问一句都重置上下文。