Skip to content

钉钉机器人接入

License 提示

钉钉渠道暂未单独 gate_PLATFORM_TO_FEATURE 里还没有 channel.dingtalk,默认 fail-open 放行)。若选 DMZ 中转部署,额外需要 deploy.dmz_bridge (ENTERPRISE)。

把一个 Sira 编排器接入钉钉企业内部机器人。员工在钉钉里单聊机器人、或群聊 @ 机器人,问答自动走 Sira 编排。通过 sira-channel-dingtalk 插件(基于 dingtalk-stream SDK)装载。

适用场景与限制

支持情况
钉钉企业内部应用机器人
第三方应用 / 自定义群机器人(Webhook-only)❌(需"企业内部应用 + 机器人" + Stream 模式)
标准版钉钉(公有云)
专属钉(私有化)✅(仅接入域名不同)
单聊
群聊(@ 机器人触发)
流式响应⚠️ 缓冲后单次推送(缓冲到 finish 一次性发 markdown,不做增量编辑,对齐飞书)
文本 / 富文本入站
图片入站✅(下载到 MinIO 后注入消息给 LLM)
文件入站(pdf / Office / zip 等)✅(content.downloadCode → 下载 → MinIO → 文件消息)
音频 / 视频入站◐ 走同一通用文件下载路径;file 结构已真机验证,音 / 视频投递结构未单独验证
图片 / 文件出站(MEDIA 标签)
主动推送(定时任务结果等)✅(优先 session_webhook,否则机器人批量 OTO,需「主动发消息」权限)
原生互动卡片 HITL◐ 需在钉钉「卡片平台」预注册模板(配 hitl_card_template_id);未配则自动降级为文本 HITL

连接模式

钉钉只有 Stream 长连接(WebSocket)一种接入:Backend 主动外连钉钉,无需公网回调地址(同企业微信 AI Bot)。创建 Application 时 connection_mode 自动锁定为 stream

第一步:在钉钉开放平台创建企业内部应用

  1. 打开 钉钉开放平台,用企业管理员账号登录
  2. 创建 企业内部应用
  3. 在应用里启用 机器人 能力,并把消息接收模式设为 Stream 模式(而非 HTTP 回调)
  4. 按需开通权限:
    • 机器人「接收消息」
    • 机器人「主动发消息」(主动推送 / 定时任务结果需要)
    • 「通讯录读权限」(需要按 userid 直解用户姓名 / 部门 / 扫码登录时)
  5. 凭证与基础信息 页拿到:
    • AppKey(也叫 Client ID)
    • AppSecret(也叫 Client Secret) 6.(可选,仅原生卡片 HITL)在 卡片平台 预注册一张含 approve/reject 回调按钮的卡片模板,记下模板 ID

第二步:在 Sira 创建 Application

进入 /agent-system/applications,点 新建应用,平台选 钉钉机器人。字段:

字段必填说明
部署形态(deploy_type)标准版钉钉(公有云) / 专属钉(私有化)
AppKey(app_id)钉钉开放平台 → 应用 → 凭证与基础信息 中的 AppKey
AppSecret(app_secret)应用的 AppSecret(编辑已有应用时留空 = 保留旧值)
专属钉接入域名仅专属钉选「专属钉」后填 API 域名等 override(透传给 SDK)
连接模式(connection_mode)自动固定 stream,无需手填

绑定一个目标编排器,保存。不需要在钉钉侧填回调地址——Stream 模式由 Backend 主动发起长连接。

第三步:测试

  1. 在钉钉企业内把应用 / 机器人可见范围授予测试用户
  2. 单聊机器人发一句话 → 路由到绑定的编排器并返回
  3. 群聊里 @ 机器人提问 → 同样有效

入站消息处理

  • SDK 在后端进程的独立 daemon 线程 + 独立事件循环里跑长连接(client.start() 自带重连)。
  • 收到消息后用 run_coroutine_threadsafe 调度回主事件循环,再分发给编排器。
  • 文本 / 富文本extract_text_from_incoming_message 解析(富文本按换行多段拼接)。
  • 图片get_image_list → 下载 → 传 MinIO → 以 presigned URL 注入消息给 LLM(message_type="image")。
  • 文件:消息 content.downloadCodemessageFiles/download 下载 → 传 MinIO → 以 message_type="file" 注入(multimodal_content 带文件 URL + 文件名)。该下载接口对任意 downloadCode 通用,音频 / 视频若以相同结构投递也会走此路径(按文件处理);目前仅对 file 结构做过真机验证。
  • 单聊 vs 群聊conversation_type 1=单聊、2=群聊(群聊 chat_id = openConversationId)。
  • 入站 user_idsender_staff_id(企业内 userid),与钉钉 OAuth / 通讯录身份对齐,让"对话 / 绑定 / 登录"落到同一个 Sira 用户。

出站消息

钉钉出站有两条传输通道,按场景自动选择:

场景通道格式
普通回复(用户刚发消息,带 session_webhook消息自带的 session_webhook(有效期约几小时)msgtype=markdown,无需企业 token / robotCode
主动推送 / webhook 不可用(定时任务结果、群推送等)机器人 API + 企业 accessTokenmsgKey=sampleMarkdown + robotCode=AppKey;群聊 robot/groupMessages/send、单聊 robot/oToMessages/batchSend
文件 / 图片(MEDIA 标签机器人 API(先上传拿 mediaIdsampleImageMsg / sampleFile
  • 流式:编排器的 chunk 累积到内存 buffer,直到 finish=True 才一次性发出,不做增量编辑(对齐飞书,避免触发钉钉编辑限制)。
  • webhook 失效自动回落:流式回复优先用 session_webhook;若 webhook 缺失 / 过期(任务跑了几小时、HITL 隔很久才恢复等),会自动回落到机器人主动推送(与 send_message 一致),不再丢消息。
  • ⚠️ 文件 / 图片出站走机器人 API,需要机器人「主动发消息 / 群消息主动发送」权限。若未授权导致发送失败,会回落一条文本提示告知用户「文件已生成但发送失败(可能缺权限)」,不再静默。

人工审批(HITL)

钉钉原生回调按钮卡必须在开放平台「卡片平台」预注册模板。在 Application 配 hitl_card_template_id 即启用原生卡片审批;未配置时 supports_approval_interaction() 返回 False,dispatcher 自动降级为文本 HITL(发一段文字让用户回复确认)。详见 人工审批 (HITL)

PlatformKey 与跨渠道关联

Key含义
dingtalk钉钉机器人(实际走的 key;别名 dingding

员工的钉钉 userid(sender_staff_id)通过 users.external_ids.dingtalk 关联到 Sira 用户,与企微 / 飞书 / 微信客服 / Web 等渠道身份打通——一处装的沙箱 / 建的定时任务,其它渠道也能用。

标准版钉钉 vs 专属钉

协议完全一致,差异仅在接入域名。专属钉在创建 Application 时选「专属钉(私有化)」,并填入 API / Stream 接入域名 override(透传给 SDK)。

部署多副本注意

Stream 是出站长连接(不需要公网入口)。统一渠道管线用资源锁保证多副本下只有一个进程持连(内嵌 runner 或独立 Channel Gateway 节点),不会重复连、消息不会乱发。跨网隔离场景可选 deployment="gateway"DMZ 中转(需 deploy.dmz_bridge License)。

已知不支持

  • 音频 / 视频入站:未单独验证。它们若以 content.downloadCode 结构投递会被当作文件处理,但钉钉对语音 / 视频的实际投递结构尚未在真机验证(文件、图片已验证 ✅)。
  • 原生互动卡片:未在「卡片平台」注册模板时不能用回调按钮卡(自动降级文本 HITL)。
  • stop() 为 best-effort:SDK 无公开 stop,靠关闭 loop + ws 退出线程。

相关文档

Apache-2.0 Licensed