跳转到内容

飞书对话机器人

官方资料整理 核验日期 2026-09-14 中国大陆 官方资料

飞书企业自建应用可以订阅“接收消息”事件,并通过消息 API 回复。本文以长连接作为快速接入路径,同时说明 HTTP 回调的生产要求;核验日期为 2026-09-14,未在真实企业租户发布应用。

  • 自定义机器人 Webhook 只用于向固定群投递,不能接收群成员消息。
  • 双向对话需要创建带机器人能力的企业自建应用,订阅 im.message.receive_v1。
  • 群聊中机器人通常围绕 @机器人 消息工作;私聊事件与群聊事件可见范围受应用权限、版本和发布范围控制。
  • 长连接适合不想提供公网回调地址的企业自建应用;HTTP 回调适合已有统一入口、队列和验签体系的生产环境。
  • 两种接收方式都只负责把平台事件交给应用。普通命令和 AI 回复最终仍调用相同的消息 API。
  • 同一应用不应让长连接和 HTTP 回调同时处理同一事件,否则即使平台只投递一次,也可能产生双重回复。
  1. 有权限在飞书开放平台创建企业自建应用、启用机器人能力、申请权限并发布版本。
  2. 有一个测试用户和测试群,应用可用范围覆盖这些成员,机器人已经加入测试群。
  3. 准备 App ID、App Secret;HTTP 模式还要按控制台配置保存 Verification Token 和 Encrypt Key。
  4. 长连接模式准备官方服务端 SDK;HTTP 模式准备公网 HTTPS 地址、原始请求体读取能力和事件队列。
  5. 已定义群聊触发规则、事件去重存储和稳定会话键,模型服务不可用时有非 AI 降级响应。
条件长连接HTTP 回调
公网入口不需要,由服务主动连接飞书需要稳定公网 HTTPS 地址
推荐实现使用官方 SDK 处理鉴权、心跳和重连使用官方 SDK 处理 challenge、验签和解密
扩缩容控制连接实例和事件消费归属API 网关后可横向扩展,靠事件 ID 去重
适用阶段本地开发、内网部署、快速联调已有网关、WAF、队列和统一回调平台

不要自行实现长连接协议。HTTP 回调如果不能安全保存原始请求体,也不应跳过验签后直接解析 JSON。

  1. 在开发者后台创建企业自建应用。
  2. 在添加应用能力中启用机器人,设置名称与基本信息。
  3. 在权限管理申请接收与发送单聊、群组消息所需权限;按调用身份选择最小权限。
  4. 把可用范围先限制在测试成员,并由管理员完成必要审批。
  1. 进入事件与回调,选择长连接或 HTTP 回调。
  2. 长连接模式按官方 SDK 初始化 App ID 和 App Secret,在代码中注册 im.message.receive_v1 处理器。
  3. HTTP 模式填写 HTTPS 请求地址,处理平台的 URL challenge,并按当前配置校验 Verification Token 或解密加密事件。
  4. 添加事件 im.message.receive_v1(接收消息)。

URL challenge 只用于验证回调地址,不能进入正常业务队列。事件回调先验签或解密,再以 header.event_id 落去重记录并快速返回成功响应。

  1. 创建并发布应用版本,确认机器人能力、权限、事件和可用范围都已经生效。
  2. 把 Bot 加入测试群,确认群设置允许机器人发言。
  3. 在群内发送 @机器人 /ping;私聊场景直接发送 /ping。
  4. 先返回固定 pong,再接业务 API,最后接入模型服务。

修改权限、事件或可用范围后通常需要重新发布版本才会对用户生效。不要只在开发者后台保存配置就开始排查代码。

事件 v2 的稳定去重标识位于事件头 header.event_id,事件类型为 im.message.receive_v1。正文中的 message.message_id 用于回复原消息,message.chat_id 标识会话,sender.sender_id 标识发送者。

message.content 是按消息类型编码的 JSON 字符串,文本消息需先 JSON 解析再读取 text。message.mentions 给出提及标记和用户标识,应按 mentions[].key 移除机器人 mention,而不是用正则删除所有 @ 文本。不要把整段事件直接作为提示词。

{
"header": { "event_id": "evt_xxx", "event_type": "im.message.receive_v1" },
"event": {
"sender": { "sender_id": { "open_id": "ou_xxx" } },
"message": {
"message_id": "om_xxx",
"chat_id": "oc_xxx",
"chat_type": "group",
"message_type": "text",
"content": "{\"text\":\"@_user_1 /ping\"}"
}
}
}

使用 header.event_id 做事件去重。会话键推荐 feishu:{tenant}:{chat_id};话题内对话可加入 thread_id 或根消息 ID,私聊需要按租户和用户隔离。显示名不能作为身份或会话主键。

先取得 tenant access token,再调用回复消息接口。下面假设已经把 Token 放入环境变量,仅验证平台回复路径:

Terminal window
curl -X POST 'https://open.feishu.cn/open-apis/im/v1/messages/MESSAGE_ID/reply' \
-H 'Authorization: Bearer TENANT_ACCESS_TOKEN' \
-H 'Content-Type: application/json; charset=utf-8' \
-d '{"msg_type":"text","content":"{\"text\":\"pong\"}"}'

收到文本事件后先依据 mentions 移除平台生成的机器人标记,再解析 /ping、/status 等命令。用原 message_id 调用“回复消息”可以保留对话关系;需要以话题形式回复时设置 reply_in_thread=true。主动发送到其他会话则使用“发送消息”接口并明确 receive_id_type。

长连接和 HTTP 回调都可能发生重复投递。业务处理前为 event_id 建唯一记录,处理成功后保存回复消息 ID。HTTP 入口应尽快确认,不在回调线程中等待慢业务;长连接处理器也应快速入队并按 SDK 要求确认。

回复与主动发送接口对同一用户限频为 5 QPS,同一群的机器人共享 5 QPS。使用可选 uuid 可以让同一发送或回复请求在一小时内至多成功一次,适合超时重试。

const conversationKey = `feishu:${tenantKey}:${message.chat_id}`;
const answer = await generateReply({
messages: await history.withUserMessage(conversationKey, normalizedText),
signal: AbortSignal.timeout(20_000),
});
await replyMessage(message.message_id, answer);
  • 群聊默认仅处理明确 @机器人 的内容;私聊可直接进入对话。
  • 富文本、图片和文件需先按类型解析、下载和安全扫描,不能假设 content.text 永远存在。
  • 模型超时后返回简短错误或转人工;不要让平台回调等待整轮模型生成。
  • AI 不需要额外“平台 AI 权限”,但模型服务、知识库和工具各自仍需鉴权与合规评估。
  • 长回复按飞书消息大小限制切分;代码块和卡片结构不能在任意字节位置截断。
  • HTTP 模式使用官方 SDK 验证请求、处理 URL challenge 和加密事件;先保留原始请求体。
  • 长连接使用官方 SDK,维护连接生命周期,不把 App Secret 输出到日志。
  • 使用 event_id 做事件去重,对同一会话串行处理,避免 AI 回复乱序。
  • App ID 与 App Secret 只在服务端;租户 Token 缓存时按应用和租户隔离。
  • 对用户输入实施提示词注入防护,工具调用在服务端按用户和群权限重新鉴权。
  • 忽略机器人自身发送的事件,限制文本、附件、单用户并发和每日模型预算。
  • 保存平台请求 ID、事件 ID 和回复消息 ID 的关联,但不记录完整消息正文和凭据。

收不到事件:检查机器人能力、事件订阅、权限、应用版本是否已发布,以及用户/群是否在可用范围内。

群内不响应普通文字:推荐让用户 @机器人;不要假设 Bot 可以读取群内所有消息。

回复接口无权限:核对消息权限、Token 所属应用与应用是否仍在会话中。

同一消息回复多次:以 header.event_id 做持久化去重,不要只在单进程内存中记录。

URL challenge 通过后仍收不到事件:检查事件是否已添加、应用版本是否重新发布、用户是否在可用范围,以及 HTTP 入口是否在验签前修改了原始请求体。

机器人回复打断群内话题:使用原消息 ID 调用回复接口;需要话题回复时设置 reply_in_thread=true,不要改成向整个 chat_id 主动发送。

高峰期出现限流:按用户或群维度排队,合并重复请求,并对平台限流响应做退避,不并发重试。