FEATURED · 精选文章

Zoom Team Chat 多步工作流实战:基于 Chatbot API 的卡片、状态存储与 Webhook 去重指南

发布时间 / 2026/9/14 6:04:56
来源 / 创域科博编辑部
栏目 / 资讯中心
Zoom Team Chat 多步工作流实战:基于 Chatbot API 的卡片、状态存储与 Webhook 去重指南 Zoom Team Chat 多步工作流实战基于 Chatbot API 的卡片、状态存储与 Webhook 去重指南【免费下载链接】knowledge-work-pluginsOpen source repository of plugins primarily intended for knowledge workers to use in Claude Cowork项目地址: https://gitcode.com/GitHub_Trending/kn/knowledge-work-plugins导读本文讲解在 knowledge-work-plugins 仓库的 Zoom 插件技能库中如何基于 Zoom Team Chat 的Chatbot API构建多步交互工作流Multi-Step Workflows——即发送带按钮的卡片 → 点击后更新状态并发送下一张卡片 → 重复直至完成的完整模式。读完本文你将掌握消息卡片的动作组件设计、interactive_message_actions等 Webhook 的响应处理、服务端状态存储方案以及 Webhook 重复投递与日志隐私这两个最容易踩坑的工程细节。什么是多步工作流为什么需要它在 Zoom Team Chat 中单条消息卡片只能承载一次交互用户看到按钮 → 点击 → 机器人收到一次回调。而真实业务场景往往是多阶段的——审批查看 → 批准/驳回、向导式填单步骤 1 → 步骤 2 → 步骤 3、工单流程创建 → 选择分类 → 提交。这就需要把多个单步交互串联成一条有状态的会话链路。仓库中 multi-step-workflows.md 给出的核心模式非常凝练发送带按钮的卡片第 1 步点击按钮后更新服务端存储的状态并回复第 2 步卡片重复上述过程直至流程完成。这个模式成立的前提是使用Chatbot APIbot 类型而非 Team Chat APIuser 类型。只有 Chatbot API 才支持带按钮、表单、下拉框的富文本消息卡片其端点族为/v2/im/chat/messages使用client_credentials授权Scope 为imchat:bot而 Team Chat API 只能以真实用户身份发送纯文本消息。两者不可混用详见 SKILL.md 中的 API 选择决策表。模式分解三步构建一条多步链路第 1 步发送带按钮的起始卡片多步工作流的第一张卡片决定了整个流程的入口。卡片通过POST https://api.zoom.us/v2/im/chat/messages发送请求体必须包含robot_jid、to_jid、account_id三个字段其中toJid与accountId通常直接取自触发 Webhook 的payload用户往哪个会话发消息就回复到哪个会话。卡片的完整结构是content.head标题区content.body组件数组参考 message-cards.md{ robot_jid: process.env.ZOOM_BOT_JID, to_jid: payload.toJid, // 取自 Webhook account_id: payload.accountId, // 取自 Webhook content: { head: { text: 费用报销审批, sub_head: { text: Step 1 of 3 } }, body: [ { type: fields, items: [ { key: 金额, value: $500.00 }, { key: 类别, value: 差旅 } ] }, { type: actions, items: [ { text: 批准, value: approve_500, style: Primary }, { text: 驳回, value: reject_500, style: Danger }, { text: 查看详情, value: details_500, style: Default } ] } ] } }动作按钮actions的每个item由text按钮文案、value回传标识、stylePrimary蓝色 /Danger红色 /Default灰色构成。button-actions.md 特别强调value是机器人区分不同动作的唯一依据必须使用稳定的动作 ID例如approve_request、reject_request、open_ticket:123——这样在 Webhook 回调中才能可靠路由也便于把资源 ID如:123编码进同一个 value。第 2 步处理点击回调更新状态用户点击按钮后Zoom 会向你的 Bot Endpoint URL 发送一个interactive_message_actions事件。回调的关键载荷字段详见 webhooks.md为payload.actionItem.value—— 你定义的按钮 value路由的核心依据payload.toJid—— 回复目标会话频道或私聊payload.accountId—— 账号标识发消息时原样回传payload.messageId、payload.userName—— 用于追踪与日志。Webhook 的通用请求体结构是{ event: ..., payload: { ... } }所有请求都会携带x-zm-signature、x-zm-request-timestamp等签名相关头部。处理interactive_message_actions的标准骨架如下case interactive_message_actions: { const { actionItem, toJid, accountId, userName } payload; // 1. 依据 actionItem.value 路由 switch (actionItem.value) { case approve_500: // 2. 更新服务端存储的状态数据库 / 内存会话 await updateWorkflowStatus(wf_500, approved, userName); // 3. 进入下一步发送第 2 张卡片 await sendStep2Card(toJid, accountId, { workflowId: wf_500 }); break; case reject_500: await updateWorkflowStatus(wf_500, rejected, userName); await sendTextMessage(toJid, accountId, ❌ 已驳回); break; default: console.log(Unknown action:, actionItem.value); } }这里最关键的一点是点击回调本身不携带完整的业务状态状态的记忆必须由你的服务端负责。这也是多步工作流与单步机器人最本质的区别——actionItem.value只是这一步选了哪个选项的信号而当前用户进行到哪一步、上一步填了什么需要靠状态存储来还原。第 3 步发送下一张卡片直至完成第 2 步中更新状态 → 发送第 2 张卡片的过程可以无限复用。每一步都是同样的闭环发送 N 步卡片 → 用户点击/提交 → 收到 Webhook → 校验签名 → 按 value 路由 → 读取/更新状态 → 若未完成则发送 N1 步卡片若完成则发送结果消息整个流程的架构图对应 webhooks.md 中的事件流用户操作点击按钮 / 斜杠命令 / 提交表单 ↓ Zoom 发送 Webhook POST 到 Bot Endpoint URL ↓ 校验 x-zm-signatureHMAC-SHA256 ↓ 按 event 路由interactive_message_actions / chat_message.submit / bot_notification ↓ 读取并更新状态 → 发送下一张卡片或完成消息需要注意的是除了按钮第 2 步及后续步骤同样可以由表单提交chat_message.submit见 form-submissions.md或下拉选择dropdown触发模式完全一致收到 Webhook → 更新状态 → 发送下一张卡片。状态存储多步工作流的心脏多步工作流是有状态会话状态存哪里是关键设计决策。仓库中的 database-integration.md 给出了面向生产环境的建表建议installationsaccount_id,bot_jid,created_at—— 记录机器人安装到了哪些账号userszoom_jid,internal_user_id—— 把 Zoom 用户 JID 映射到内部系统用户workflowsworkflow_id,status,payload_json—— 每一条进行中的工作流payload_json存放该流程的全部中间数据。对每一步 Webhook 回调处理逻辑就是读workflows表 → 按当前status决定下一步 → 更新status与payload_json→ 发送对应卡片。对于简单场景如演示、短期会话也可以先用内存 Map 或 Redis 做会话状态但只要涉及审批、跨用户协作、异常恢复就应该落到数据库否则服务重启即丢失流程。从仓库 chatbot-setup.md 的实现看机器人侧还封装了sendMessageWithButtons(toJid, accountId, { title, message, buttons })这类工具函数把标题 正文 一组按钮的卡片发送固化为一行调用多步流程中每一步只需传入不同的buttons与状态标记即可非常适合串联多步链路。完整可运行的示例三步审批流程结合上述模式与仓库中的工具代码chatbot-setup.md 中的utils/auth.js、utils/chatbot.js、routes/webhook.js一个发起申请 → 确认信息 → 提交完成的三步流程可以这样组织。发送第 1 张卡片由/start斜杠命令触发// 收到 bot_notificationcmd start await sendMessageWithButtons(toJid, accountId, { title: 发起新申请, message: 请选择申请类型, buttons: [ { text: 差旅报销, value: type_travel, style: Primary }, { text: 采购申请, value: type_procurement, style: Default } ] }); // 同时在服务端创建 workflow 记录{ workflow_id, status: awaiting_type }处理第 1 步点击发送第 2 张卡片// interactive_message_actionsactionItem.value type_travel await updateWorkflowStatus(workflowId, awaiting_confirm, { type: travel }); await sendMessageWithButtons(toJid, accountId, { title: 确认差旅报销信息, message: 金额、日期等信息确认无误吗, buttons: [ { text: 确认提交, value: confirm, style: Primary }, { text: 返回修改, value: back, style: Default } ] });处理第 2 步点击完成流程// actionItem.value confirm await updateWorkflowStatus(workflowId, completed, { ...state, confirmedBy: userName }); await sendTextMessage(toJid, accountId, ✅ 申请已提交工单号 #123); // 可选通知审批人给审批人的 toJid 单独发送一张带 approve/reject 按钮的卡片这正是仓库 SKILL.md 中描述的 Approval Workflow PatternRequest → Send card with buttons → User clicks → Update status → Notify的落地实现。两大陷阱与工程化规避原文档明确列出两个 Pitfalls它们是多步工作流上线前必须处理的工程问题。陷阱一Webhook 可能被重复投递——必须按事件 ID 去重Webhooks can be delivered more than once; de-dupe by event ID if available.Zoom 的 Webhook 采用尽力投递at-least-once语义网络抖动或对端超时都可能导致同一个事件被投递多次。若不做去重用户点一次确认提交可能收到两条已提交回复甚至把同一审批单提交两遍。去重的常规做法是以事件唯一标识为键写入已处理记录数据库唯一索引或 Redis SETNX从请求中提取事件 ID若可用在进入业务逻辑前先检查该 ID 是否已处理过已处理则直接返回 200未处理则原子地标记后再执行流程。配合仓库 webhooks.md 给出的先快速返回 200、再异步处理的推荐写法即便异步任务被重复触发去重层也能兜底。此外回调处理应尽量幂等如把状态更新为已完成重复执行无害双保险更稳妥。陷阱二日志中禁止出现 PIIAvoid storing PII in logs.多步工作流的回调载荷里天然包含userName、userJid、消息原文cmd等个人可识别信息PII。仓库的 security.md 明确要求记录请求 ID 与关联 ID但禁止记录 token 与 PII。推荐的日志策略console.log([Webhook] ${event}, { requestId: req.headers[x-zm-request-id], // 关联 ID accountId: payload.accountId, // 账号级信息非个人级 timestamp: new Date().toISOString() }); // ❌ 不要记录 userName、userJid、cmd 原文、accessToken如果确实需要排查某个用户的问题用内部用户 ID非 JID关联即可避免把姓名、邮箱、消息原文写进日志。这既是合规要求也防止日志泄露被用来伪造后续请求。配套的工程化实践签名校验是 Webhook 安全的第一道门所有 Webhook 处理器都应先做 HMAC-SHA256 签名校验详见 webhooks.md 与 chatbot-setup.md 中的utils/validation.jsconst message v0:${req.headers[x-zm-request-timestamp]}:${JSON.stringify(req.body)}; const hash crypto.createHmac(sha256, process.env.ZOOM_VERIFICATION_TOKEN) .update(message).digest(hex); if (req.headers[x-zm-signature] ! v0${hash}) { throw new Error(Invalid webhook signature); }签名不匹配时返回 401业务逻辑含状态更新一概不执行。配置 Bot Endpoint URL 时 Zoom 还会发送endpoint.url_validation校验请求需要回传plainToken与encryptedToken对plainToken用验证 Token 做 HMAC-SHA256详见 webhooks.md 的 URL 校验章节。3 秒内必须响应重活异步化Zoom 期望 Webhook 端点在 3 秒内返回 200。多步流程中的调数据库 调 LLM 发卡片很容易超时因此仓库推荐的标准写法是先校验签名、立即res.status(200).json({ success: true })再异步执行状态更新与消息发送。对多步工作流而言这意味着每次点击之后用户可以立刻继续操作而状态更新的最终一致性由异步任务保证。输入校验与内容限制把 Webhook 载荷一律视为不可信输入服务端校验类型日期、数字后再入库见 form-submissions.md消息文本限制 4,096 字符、按钮文案限制 40 字符、每条消息按钮不超过 5 个、字段键值各不超过 256 字符、下拉选项不超过 100 个见 message-cards.md——多步流程可以通过拆成更多步骤来绕过这些单卡片限制校验toJid格式userdomain或channeldomain见 jid-formats.md凭据一律放环境变量ZOOM_BOT_JID、ZOOM_VERIFICATION_TOKEN等见 environment-variables.md禁止硬编码。相关扩展阅读多步工作流是其他交互能力的组合基础进一步深入可参考仓库内以下文档button-actions.md——按钮 value 的稳定命名与路由实践form-submissions.md——用表单作为多步流程中的输入步骤dropdown-selects.md——用下拉选择作为流程分支database-integration.md——状态存储的表结构设计webhooks.md——Webhook 架构、签名校验与事件清单message-cards.md——卡片组件全目录与完整示例chatbot-setup.md——完整的可运行机器人骨架含sendMessageWithButtons等工具函数webhook-events.md——bot_notification、interactive_message_actions、chat_message.submit等事件速查security.md——Webhook 与日志的隐私安全规范入口与导航SKILL.md、RUNBOOK.md。总结基于 Zoom Team Chat Chatbot API 的多步工作流本质是一条发送卡片 → 回调 → 更新状态 → 发送下一张卡片的闭环链路。落地的关键有三点一是用稳定、带业务语义的actionItem.value驱动路由二是把会话状态持久化到服务端数据库或 Redis让每一步都能从上一状态继续三是处理好 Webhook 的重复投递按事件 ID 去重 幂等处理与日志隐私不落 PII并始终以签名校验作为所有回调的入口防线。掌握这套模式后审批流、多步填单、工单流程等常见企业场景都可以在 Zoom Team Chat 内直接交付。【免费下载链接】knowledge-work-pluginsOpen source repository of plugins primarily intended for knowledge workers to use in Claude Cowork项目地址: https://gitcode.com/GitHub_Trending/kn/knowledge-work-plugins创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻