跳转到内容

飞书对话机器人

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

  • 自定义机器人 Webhook 只用于向固定群投递,不能接收群成员消息。
  • 双向对话需要创建带机器人能力的企业自建应用,订阅 im.message.receive_v1
  • 群聊中机器人通常围绕 @机器人 消息工作;私聊事件与群聊事件可见范围受应用权限、版本和发布范围控制。
  • 长连接适合不想提供公网回调地址的企业自建应用;HTTP 回调适合已有统一入口、队列和验签体系的生产环境。
  1. 有权限在飞书开放平台创建企业自建应用,并能为应用发布版本。
  2. 有一个测试用户和测试群,应用可用范围覆盖这些成员。
  3. 准备 App ID、App Secret;HTTP 模式还要保存 Verification Token 和 Encrypt Key。
  4. 服务端使用官方 SDK 或完整实现官方回调验签/解密协议。
  1. 开发者后台创建企业自建应用。
  2. 添加应用能力 中启用机器人,设置名称与基本信息。
  3. 权限管理 申请“获取与发送单聊、群组消息”等接收和回复所需权限;以控制台实际列出的权限点为准。
  4. 事件与回调 选择接收方式:长连接,或将请求地址指向你的 HTTPS 事件入口。
  5. 添加事件 im.message.receive_v1(接收消息)。
  6. 创建并发布应用版本,把可用范围限制在测试成员;需要管理员审批的权限完成审批。
  7. 把 Bot 加入测试群,使用 @机器人 /ping;私聊场景直接发送 /ping

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

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

message.content 是按消息类型编码的 JSON 字符串,文本消息需先 JSON 解析再读取 text。不要把整段事件直接作为提示词。

{
"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};需要更细粒度时,按根消息或发送者隔离。

先取得 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\"}"}'

收到文本事件后先移除平台生成的 mention 标记,再解析 /ping/status 等命令。用原 message_id 调用“回复消息”可以保留对话关系;主动发送到其他会话则使用“发送消息”接口并明确 receive_id_type

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

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 缓存时按应用和租户隔离。
  • 对用户输入实施提示词注入防护,工具调用在服务端按用户和群权限重新鉴权。

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

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

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

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