钉钉企业机器人对话
钉钉企业内部应用机器人能在群聊被 @ 或单聊时接收消息。本文主路径使用官方推荐的 Stream 模式,HTTP 回调作为已有公网入口时的替代方案;核验日期为 2026-09-08,未在真实组织发布应用。
- 自定义机器人 Webhook 是固定群通知入口,不等于企业机器人接收消息能力。
- 企业机器人接收消息支持 Stream 和 HTTP 两种模式。Stream 由客户端主动建立连接,不要求公网回调地址。
- 群聊通常由
@机器人触发;单聊需应用机器人和组织侧配置允许。 - AI Card、流式卡片是可选的展示增强,不是完成普通文本 AI 对话的前置条件。
- 有权限在钉钉开放平台创建企业内部应用、添加机器人并发布版本。
- 已准备 AppKey(Client ID)、AppSecret(Client Secret)和测试组织。
- Stream 模式使用官方 Stream SDK;HTTP 模式准备公网 HTTPS 回调地址并完整实现验签要求。
- 明确 Bot 加群、单聊可见范围和组织管理员审批流程。
- 在钉钉开放平台创建企业内部应用。
- 在应用能力中添加机器人,设置机器人名称、图标和消息接收模式。
- 优先选择 Stream 模式;若选择 HTTP 模式,填写回调 URL 并完成平台校验。
- 按回复方式申请机器人发消息所需权限,创建并发布应用版本。
- 把机器人添加到测试群,或从工作台进入机器人单聊。
- 启动 Stream 客户端,用
@机器人 /ping验证入站事件。
回调中常见字段包括消息 ID、会话 ID、会话类型、发送者 ID、文本内容和临时 sessionWebhook。字段会随消息类型和 SDK 封装变化,应以官方模型为准,不要用显示昵称建立身份。
{ "msgId": "msg_xxx", "conversationId": "cid_xxx", "conversationType": "2", "senderStaffId": "user_xxx", "text": { "content": " /ping" }, "sessionWebhook": "https://oapi.dingtalk.com/robot/sendBySession?..."}以官方消息 ID 做事件去重。会话键建议 dingtalk:{corpId}:{conversationId};单聊可加入 senderStaffId。Stream SDK 收到消息后仍要按 SDK 协议确认,避免平台重投。
最小会话 Webhook 回复
Section titled “最小会话 Webhook 回复”sessionWebhook 来自入站消息,只能在其官方有效期与限制内用于当前会话。它不是长期凭据,也不要持久化到聊天历史。
curl -X POST 'SESSION_WEBHOOK' \ -H 'Content-Type: application/json' \ -d '{"msgtype":"text","text":{"content":"pong"}}'const response = await fetch(process.env.SESSION_WEBHOOK, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ msgtype: 'text', text: { content: 'pong' } }),});if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);import osimport requests
response = requests.post( os.environ["SESSION_WEBHOOK"], json={"msgtype": "text", "text": {"content": "pong"}}, timeout=15,)response.raise_for_status()普通 API 双向回复
Section titled “普通 API 双向回复”最小路径可使用消息携带的 sessionWebhook 回复当前会话。需要超出临时回复窗口、主动发起消息或精确控制接收人时,应按官方企业机器人 OpenAPI 获取访问令牌并调用相应群聊/单聊发送接口,不要长期缓存 sessionWebhook 代替正式身份凭据。
确定性命令处理建议优先:/ping 返回 pong,/status 查询业务 API。平台确认、业务执行和回复分开记录,失败重试前检查消息 ID 是否已经回复。
AI 对话扩展
Section titled “AI 对话扩展”const conversationKey = `dingtalk:${corpId}:${message.conversationId}`;const answer = await generateReply({ messages: await history.withUserMessage(conversationKey, message.text.content.trim()), signal: AbortSignal.timeout(20_000),});await replyWithSessionWebhook(message.sessionWebhook, answer);生成时间可能超过临时回复窗口时,改用正式发送 API,或使用钉钉当前支持的 AI Card/流式卡片方案。引入卡片前先完成普通文本一问一答,避免同时排查卡片模板、流式更新和模型问题。
安全与可靠性
Section titled “安全与可靠性”- AppSecret、访问令牌和
sessionWebhook都按敏感凭据处理,日志中只保留哈希或脱敏片段。 - Stream 模式使用官方 SDK管理鉴权、重连和确认;HTTP 模式按官方规范验签。
- 用消息 ID 做事件去重,对同一会话串行,忽略 Bot 自身消息。
- 只在
@机器人、单聊或明确命令时触发模型,设置输入长度、并发和预算上限。 - 模型工具调用需要按钉钉用户、组织和业务资源在服务端重新鉴权,防范提示词注入。
机器人可以发通知但收不到消息:确认使用的是企业内部应用机器人,而不是只有 Webhook 的自定义机器人。
Stream 已连接但群里不触发:检查机器人是否已入群、消息是否 @机器人、应用版本和可见范围是否已生效。
sessionWebhook 后来失效:它是临时回复地址。异步长任务应使用官方主动发送接口,不要把 URL 当长期 Token。
重复回复:消息处理前为消息 ID 建唯一键,并在 Stream/HTTP 重投时直接确认而不重复执行业务。