跳到主要内容

可选的钉钉聊天卡片

在管理后台的 IM 通道 → 编辑钉钉通道 中,填写“聊天 AI 卡片模板 ID”。留空会保持现有回复方式;已有 use_ai_card=false 的通道仍使用普通回复。订阅通知的 card_template_id 与聊天卡片配置独立。

模板需要发布到该钉钉应用。在“输出中”和“完成”状态下,正文组件应绑定同一字段,输出中组件须启用流式。卡片上的输入框用于文字;图片通过独立的“上传图片”组件提交,图片不是必填项。卡片文件上传暂未接入。

上线时先完整发布后端,确保所有实例已升级,再发布管理前端并配置聊天模板。也可以先只发布后端:未配置 chat_card 的通道继续使用原回复方式。启用前先在测试通道验证流式输出、回答结束和卡片追问。

配置​

仅填写模板 ID 即使用以下默认映射;“高级:字段与追问设置”允许修改字段名或关闭追问。

配置默认值用途
template_id必填,仅启用自定义模板时钉钉模板 ID
content_keycontentAI 回答的 Markdown 正文字段
follow_up_enabledtrue是否接受卡片追问
follow_up_actionfollow_up发送按钮的回传动作 ID
follow_up_text_keyfollowUpText回调携带的文本参数名
follow_up_images_keyfollowUpImages回调携带的图片 URL 数组参数名
follow_up_status_keynull(关闭)可选的发送状态字段,必须在模板中绑定
initial_data{}可通过配置 API 设置的模板初始变量,值为字符串

配置存放于通道的 config.chat_card,例如:

{
"chat_card": {
"template_id": "your-template.schema",
"content_key": "answer",
"follow_up_action": "ask_again",
"follow_up_text_key": "question",
"follow_up_images_key": "photos",
"follow_up_enabled": true,
"initial_data": { "heading": "助手" }
}
}

通过 API 移除配置时发送 {"chat_card": null};省略该字段代表保持现有配置。后台清空模板 ID 会发送 null。

flowStatus 是钉钉 AI 卡片的协议字段,不能用作正文字段。配色、布局及其他展示组件由钉钉模板管理;字段映射并不将普通卡片自动转换成支持流式的 AI 卡片。

回复卡片默认携带 sys_full_json_obj(值为 {"config":{"autoLayout":true}}):声明了 config.autoLayout 的模板会自动按内容宽度展示,宽表格不再被挤成窄列,未声明该变量的模板则忽略它。该变量也是系统字段,不能用作 content_key 或 follow_up_status_key;如需自定义,在 initial_data 中设置同名变量即可覆盖默认值。

通知卡片(可选)​

同一个钉钉通道可以把应用内通知改用卡片推送:勾选“任务通知以卡片发送”后,@提及、被分配、开始执行、执行完成/失败/取消这类通知会以卡片形式发出。只有配置了通知卡片的通道才会收到 IM 推送,同一用户连接的其他渠道不会重复发送;未配置通知卡片时不发送 IM 通知,应用内通知和应用内记录不受影响。卡片本次发送失败时仍会退回原来的 Markdown 通知。

默认使用钉钉内置的 Markdown 消息卡片,无需自建模板。内置模板的变量约定是 title、markdown、tips,以及 sys_full_json_obj 中的 msgButtons。这与下方自定义模板的变量约定不同。通知使用普通消息卡片,不使用带流式状态和反馈区的 AI 卡片。

如需分区显示通知类型、事项、详情和操作入口,可使用Wegent 通知卡片导入示例:

  1. 在钉钉卡片平台为发送通知的机器人应用创建普通消息卡片,在编辑器中导入 JSON,检查预览后保存并发布。
  2. 复制本组织中新建模板的 ID,在钉钉通道勾选“任务通知以卡片发送”,填写该模板 ID。测试组织使用的模板 ID 不能直接用于其他组织。
  3. 确认生产环境的 FRONTEND_URL 是可访问的 HTTPS 地址。在实际钉钉客户端检查 @提及、被分配和各执行状态,以及两个操作入口。自定义卡片的 Wework 入口使用经校验的 wework:// 深链,由系统交给关联的 Wework 桌面应用打开;安装多个版本时,系统的默认关联决定打开哪个应用。

自定义模板使用以下 13 个普通变量;后端在投放卡片时填充它们:

变量内容
kindLabel“评论提及”“任务分配”或执行状态标签
tone状态色:blue、orange、green、red、gray
headline通知动作,如“你的任务已完成”
itemTitle任务标题
itemKey任务编号
metaLine看板、任务状态和负责人组成的摘要
detailLabel详情标题,如“评论内容”“失败原因”
detail评论、结果或原因;卡片最多展示 240 个字符
showDetail是否展示详情;在模板中定义为布尔变量
primaryLabel网页入口文案“查看任务”
primaryUrl任务网页地址
secondaryLabel桌面入口文案“在 Wework 中打开”
secondaryUrl经校验的 Wework wework:// 桌面深链

tone 由通知类型与状态决定:提及、分配和开始执行为 blue;等待审批或设备为 orange;完成为 green;失败为 red;取消为 gray。人工派发以及带项目来源的普通通知也使用同一组事项字段。卡片标题描述动作,任务标题与编号、上下文和可选详情分开显示。卡片的“查看任务”按钮直接使用任务网页地址;应用内通知地址、内置卡片及 Markdown 通知仍保留原来的 wework:// 链接。可引用回复的本地运行任务通知仍为文本消息,以便直接引用继续任务。

配置存放于通道的 config.notification_card;自定义模板例如:

{
"notification_card": {
"template_id": "your-published-template.schema"
}
}

仅勾选开关而不填写自定义模板 ID 时,使用上述内置模板。通过 API 关闭时发送 {"notification_card": null};省略该字段代表保持现有配置。

追问与历史​

群内引用回复也可进入同一追问流程:投放时保存 carrierId → outTrackId 关联,引用并 @机器人时,用回调的 originalProcessQueryKey 查询该关联。仅处理原群、同企业、引用本机器人的已关联卡片;普通消息、未匹配引用和斜杠命令沿用原流程。关联保留 7 天,新增代码前投放的卡片没有自动建立该索引。

每轮回答新建一张卡片,该轮正文持续更新同一张卡片。点击旧卡片追问时,后端根据 outTrackId 查找原任务,复用原任务的智能体和执行参数;新回答使用新卡片,历史回答保留,也不会改变当前私聊选中的任务。

卡片关联和模板映射快照保存在共享 Redis,默认保留 7 天。过期后需重新 @机器人。钉钉群内卡片默认开放协作:同企业、同原始群内的其他用户首次追问时,将原任务转为 Wegent 群聊任务并加入成员。后续补充保留实际发言人,复用同一任务和完整历史;成员可在 Wegent 群聊列表访问该任务。任务创建者保持不变,不创建钉钉群,也不改变其他通道的加入规则。已被移出的成员不能通过卡片重新加入。

多人协作要求通道使用员工 ID 或邮箱映射到独立 Wegent 账号;“指定用户”映射不支持其他人代入协作。私聊卡片和设备本地运行任务仍限原提问者追问。任务执行中或同一任务正处理其他卡片追问时,会拒绝追加。回调重试按事件 ID 去重。

卡片接口和 Stream 回调沿用该机器人的应用凭证。后端在现有 Stream 连接上注册 /v1.0/card/instances/callback,不需要额外启动一个 Stream 客户端。按钮回调参数提供文本和可选图片,不接受客户端指定目标任务。

接收回调时,后端先原子写入 Redis 待处理记录和去重标记,再确认接收。每个通道定期恢复待处理记录;已开始但因进程中断而结果不确定的追问不会自动重复触发 AI,而是提示检查会话记录。处理租约每 30 秒续期,进程退出后最多约 90 秒释放租约。未完成的记录保留到处理结束,终态去重记录保留 7 天。可靠恢复依赖 Redis 数据保留,不能将此实例当作可随时清空的缓存。

卡片更新遇到网络错误、429 或 5xx 时最多尝试 3 次,重复写入复用相同正文和 guid。结束失败会向上层报告失败并保留回调信息及共享正文至原 TTL,供后续重投重试,不会记录为发送成功。本地任务通过来源消息 ID 与通道 ID 校验卡片轮次,拒绝迟到的旧轮次事件。

发送状态反馈(可选)​

  1. 在模板中创建普通文本变量 followUpStatus,默认值 idle。
  2. 在通道高级设置中,将“发送状态字段”填写为 followUpStatus。
  3. 将按钮文案和状态绑定到该变量:sending 显示“发送中”并禁用;sent 显示“已发送”;failed 显示“重试”;idle 显示“发送”。只有 sending 时禁用,其他状态允许新的追问。
  4. 若模板支持加载动画,让动画的显示条件为该变量等于 sending,保存并发布模板后验证。

后端只增量更新这一字段,保留原答案和已输入的文本、图片。sent 表示本次处理函数已成功返回,不代表模型必定已经完成回答;它与 AI 卡片的 flowStatus 独立。字段留空时保持原模板行为。模板动画及按钮绑定需在钉钉编辑器中配置,后台配置本身不会自动修改布局。

状态更新参考:钉钉官方 Python SDK 的卡片更新接口。

图片追问​

使用默认字段映射时,在钉钉卡片编辑器中设置:

  1. 创建本地变量 followUpImages,类型为“普通文本数组”,初始值为 []。
  2. 选中“上传图片”组件,进入“事件 → 更新本地变量”,选择 followUpImages。
  3. 选中“发送”按钮,在回传参数中保留 followUpText,新增 followUpImages,参数类型选“变量”,参数值选本地变量 followUpImages。
  4. 保存并发布模板,使用新卡片验证。自定义字段名时,同步修改通道的高级映射。

回调 cardPrivateData.params 应包含以下结构;不上传图片时可省略图片字段或传 []:

{
"followUpText": "解释图片内容",
"followUpImages": ["https://static.dingtalk.com/media/example.png"]
}

支持纯文字、文字加图片和仅图片追问;仅图片时使用“请查看图片”作为本轮文字。普通 @机器人消息先用下载码取得图片地址,卡片上传组件直接提供图片 URL。两者下载后均使用现有附件服务:云端任务关联到本轮用户消息,本地任务通过 attachment_ids 传递。

地址校验允许 https://static.dingtalk.com/media/ 和 https://down.dingtalk.com/ddmedia/,下载不跟随重定向。电脑上传的 static 地址已通过下载验证;手机上传的 down 地址在当前无 Cookie 的服务端请求中返回 403 / cookie_empty,下载鉴权尚未接通,不能视为手机图片已支持。支持 PNG、JPEG、GIF、WebP,最多 9 张,单张最多 10 MB,总计最多 30 MB。下载或保存失败会提示错误,本轮不会在缺图的情况下触发模型。

日志 card_follow_up_accepted.image_count 表示回调收到的图片数;card_follow_up_images_persisted 的 attachment_ids 表示附件已保存。客户端显示“上传成功”并不代表发送按钮已回传图片变量。

联调​

  1. 保存一个测试通道的聊天模板配置,在钉钉 @机器人,确认正文在完成前持续增长。
  2. 从卡片追问,确认新卡片出现在原会话,Wegent 中仍为同一任务且保留历史。
  3. 切换当前对话后,从旧卡片追问,确认回复仍进入旧卡片对应的任务。
  4. 用另一个账号点击卡片、重复回调、在任务执行中追问,确认不会产生越权或重复执行。
  5. 清空聊天模板配置,确认恢复现有回复方式;订阅通知仍使用原通知模板。
  6. 分别验证纯文字、文字加图片、仅图片,确认 Wegent 本轮消息有附件;图片下载失败时应提示错误,不能继续生成缺图的回答。

本地单元测试使用模拟的钉钉 HTTP、任务服务和缓存验证协议与路由;实际客户端渲染及真实按钮回调仍需以上联调。

协议参考:钉钉 Stream 事件类型、卡片事件回调。