跳到主要内容

可选的钉钉聊天卡片

在管理后台的 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 卡片。

追问与历史

群内引用回复也可进入同一追问流程:投放时保存 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_persistedattachment_ids 表示附件已保存。客户端显示“上传成功”并不代表发送按钮已回传图片变量。

联调

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

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

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