可选的钉钉聊天卡片
在管理后台的 IM 通道 → 编辑钉钉通道 中,填写“聊天 AI 卡片模板 ID”。留空会保持现有回复方式;已有 use_ai_card=false 的通道仍使用普通回复。订阅通知的 card_template_id 与聊天卡片配置独立。
模板需要发布到该钉钉应用。在“输出中”和“完成”状态下,正文组件应绑定同一字段,输出中组件须启用流式。卡片上的输入框用于文字;图片通过独立的“上传图片”组件提交,图片不是必填项。卡片文件上传暂未接入。
上线时先完整发布后端,确保所有实例已升级,再发布管理前端并配置聊天模板。也可以先只发布后端:未配置 chat_card 的通道继续使用原回复方式。启用前先在测试通道验证流式输出、回答结束和卡片追问。
配置
仅填写模板 ID 即使用以下默认映射;“高级:字段与追问设置”允许修改字段名或关闭追问。
| 配置 | 默认值 | 用途 |
|---|---|---|
template_id | 必填,仅启用自定义模板时 | 钉钉模板 ID |
content_key | content | AI 回答的 Markdown 正文字段 |
follow_up_enabled | true | 是否接受卡片追问 |
follow_up_action | follow_up | 发送按钮的回传动作 ID |
follow_up_text_key | followUpText | 回调携带的文本参数名 |
follow_up_images_key | followUpImages | 回调携带的图片 URL 数组参数名 |
follow_up_status_key | null(关闭) | 可选的发送状态字段,必须在模板中绑定 |
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 校验卡片轮次,拒绝迟到的旧轮次事件。
发送状态反馈(可选)
- 在模板中创建普通文本变量
followUpStatus,默认值idle。 - 在通道高级设置中,将“发送状态字段”填写为
followUpStatus。 - 将按钮文案和状态绑定到该变量:
sending显示“发送中”并禁用;sent显示“已发送”;failed显示“重试”;idle显示“发送”。只有sending时禁用,其他状态允许新的追问。 - 若模板支持加载动画,让动画的显示条件为该变量等于
sending,保存并发布模板后验证。
后端只增量更新这一字段,保留原答案和已输入的文本、图片。sent 表示本次处理函数已成功返回,不代表模型必定已经完成回答;它与 AI 卡片的 flowStatus 独立。字段留空时保持原模板行为。模板动画及按钮绑定需在钉钉编辑器中配置,后台配置本身不会自动修改布局。
状态更新参考:钉钉官方 Python SDK 的卡片更新接口。
图片追问
使用默认字段映射时,在钉钉卡片编辑器中设置:
- 创建本地变量
followUpImages,类型为“普通文本数组”,初始值为[]。 - 选中“上传图片”组件,进入“事件 → 更新本地变量”,选择
followUpImages。 - 选中“发送”按钮,在回传参数中保留
followUpText,新增followUpImages,参数类型选“变量”,参数值选本地变量followUpImages。 - 保存并发布模板,使用新卡片验证。自定义字段名时,同步修改通道的高级映射。
回调 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 表示附件已保存。客户端显示“上传成功”并不代表发送按钮已回传图片变量。
联调
- 保存一个测试通道的聊天模板配置,在钉钉 @机器人,确认正文在完成前持续增长。
- 从卡片追问,确认新卡片出现在原会话,Wegent 中仍为同一任务且保留历史。
- 切换当前对话后,从旧卡片追问,确认回复仍进入旧卡片对应的任务。
- 用另一个账号点击卡片、重复回调、在任务执行中追问,确认不会产生越权或重复执行。
- 清空聊天模板配置,确认恢复现有回复方式;订阅通知仍使用原通知模板。
- 分别验证纯文字、文字加图片、仅图片,确认 Wegent 本轮消息有附件;图片下载失败时应提示错误,不能继续生成缺图的回答。
本地单元测试使用模拟的钉钉 HTTP、任务服务和缓存验证协议与路由;实际客户端渲染及真实按钮回调仍需以上联调。
协议参考:钉钉 Stream 事件类型、卡片事件回调。