飞书对话机器人
飞书企业自建应用可以订阅“接收消息”事件,并通过消息 API 回复。本文以官方推荐的长连接作为快速接入路径,同时说明 HTTP 回调;核验日期为 2026-09-08,未在真实企业租户发布应用。
- 自定义机器人 Webhook 只用于向固定群投递,不能接收群成员消息。
- 双向对话需要创建带机器人能力的企业自建应用,订阅
im.message.receive_v1。 - 群聊中机器人通常围绕
@机器人消息工作;私聊事件与群聊事件可见范围受应用权限、版本和发布范围控制。 - 长连接适合不想提供公网回调地址的企业自建应用;HTTP 回调适合已有统一入口、队列和验签体系的生产环境。
- 有权限在飞书开放平台创建企业自建应用,并能为应用发布版本。
- 有一个测试用户和测试群,应用可用范围覆盖这些成员。
- 准备 App ID、App Secret;HTTP 模式还要保存 Verification Token 和 Encrypt Key。
- 服务端使用官方 SDK 或完整实现官方回调验签/解密协议。
- 在开发者后台创建企业自建应用。
- 在 添加应用能力 中启用机器人,设置名称与基本信息。
- 在 权限管理 申请“获取与发送单聊、群组消息”等接收和回复所需权限;以控制台实际列出的权限点为准。
- 在 事件与回调 选择接收方式:长连接,或将请求地址指向你的 HTTPS 事件入口。
- 添加事件
im.message.receive_v1(接收消息)。 - 创建并发布应用版本,把可用范围限制在测试成员;需要管理员审批的权限完成审批。
- 把 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};需要更细粒度时,按根消息或发送者隔离。
最小回复验证
Section titled “最小回复验证”先取得 tenant access token,再调用回复消息接口。下面假设已经把 Token 放入环境变量,仅验证平台回复路径:
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\"}"}'const response = await fetch(`https://open.feishu.cn/open-apis/im/v1/messages/${process.env.MESSAGE_ID}/reply`, { method: 'POST', headers: { Authorization: `Bearer ${process.env.TENANT_ACCESS_TOKEN}`, 'Content-Type': 'application/json; charset=utf-8', }, body: JSON.stringify({ msg_type: 'text', content: JSON.stringify({ text: 'pong' }) }),});const result = await response.json();if (!response.ok || result.code !== 0) throw new Error(JSON.stringify(result));import osimport requests
response = requests.post( f"https://open.feishu.cn/open-apis/im/v1/messages/{os.environ['MESSAGE_ID']}/reply", headers={"Authorization": f"Bearer {os.environ['TENANT_ACCESS_TOKEN']}"}, json={"msg_type": "text", "content": '{"text":"pong"}'}, timeout=15,)response.raise_for_status()result = response.json()if result.get("code") != 0: raise RuntimeError(result)普通 API 双向回复
Section titled “普通 API 双向回复”收到文本事件后先移除平台生成的 mention 标记,再解析 /ping、/status 等命令。用原 message_id 调用“回复消息”可以保留对话关系;主动发送到其他会话则使用“发送消息”接口并明确 receive_id_type。
长连接和 HTTP 回调都可能发生重复投递。业务处理前为 event_id 建唯一记录,处理成功后保存回复消息 ID。HTTP 入口应尽快确认,不在回调线程中等待慢业务。
AI 对话扩展
Section titled “AI 对话扩展”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 权限”,但模型服务、知识库和工具各自仍需鉴权与合规评估。
安全与可靠性
Section titled “安全与可靠性”- HTTP 模式使用官方 SDK 验证请求、处理 URL challenge 和加密事件;先保留原始请求体。
- 长连接使用官方 SDK,维护连接生命周期,不把 App Secret 输出到日志。
- 使用
event_id做事件去重,对同一会话串行处理,避免 AI 回复乱序。 - App ID 与 App Secret 只在服务端;租户 Token 缓存时按应用和租户隔离。
- 对用户输入实施提示词注入防护,工具调用在服务端按用户和群权限重新鉴权。
收不到事件:检查机器人能力、事件订阅、权限、应用版本是否已发布,以及用户/群是否在可用范围内。
群内不响应普通文字:推荐让用户 @机器人;不要假设 Bot 可以读取群内所有消息。
回复接口无权限:核对消息权限、Token 所属应用与应用是否仍在会话中。
同一消息回复多次:以 header.event_id 做持久化去重,不要只在单进程内存中记录。