Webhook 与事件
让外部系统通过 Webhook 通知 Z Tag,并把回调整理成可以订阅的事件。
Webhook 是 Z Tag 对外提供的接收地址。外部系统(例如 GitLab)向它推送回调,Z Tag 验签后按事件定义把回调整理成具名事件;ZAI 订阅这些事件后,事件到达时就会自动开始工作。订阅的用法见订阅事件。
谁可以做:组织 Owner、Admin 可以在 组织管理 视图中管理所有 Channel 和组织连接器的 Webhook。成员个人连接器的 Webhook 只有他本人能看到和管理,Owner、Admin 也看不到。成员可以在 我的资源 → Webhook 管理归属自己所在群的 Webhook 和自己个人连接器的 Webhook,见在控制台管理自己的资源。
把接收地址交给外部系统的维护人员时,请同时提供Webhook 接入指南(发送方),其中包含 GitLab 配置、HTTP 推送示例、事件格式约定、验签、重试和联调步骤。
归属与权限
Webhook 归属中的 Channel 可以是群,也可以是成员自己和 ZAI 的私聊,见你会看到的词。每个 Webhook 归属于一个 Channel 或一个连接器,每个归属最多保留 10 个未撤销的 Webhook:
| 归属 | 谁能订阅它的事件 | 谁能管理 |
|---|---|---|
| Channel | 只有这个 Channel | 组织 Owner、Admin,以及这个 Channel 的成员 |
| 连接器 | 连接器生效的每个 Channel | 组织连接器:组织 Owner、Admin;个人连接器:只有它的所有者本人 |
成员能看到哪些 Channel 的 Webhook,取决于 Z Tag 记录的成员名单:成员加入后即可看到,退出后随即看不到。名单暂时无法确认时,这个 Channel 的 Webhook 会暂时从成员的列表中消失,确认恢复后自动出现。创建、修改或删除时会当场再确认一次,确认不了时操作报错,稍后重试即可。组织 Owner 和 Admin 不受影响。
如果 ZAI 已被移出这个群或群已解散,群成员名单不再同步:Owner、Admin 以外的成员随即看不到这个群的 Webhook,停留在旧页面上的修改会提示 ZAI 已被移出群,无法核对成员 或 群已解散,无法核对成员,重试不会成功。组织 Owner 和 Admin 仍能看到这些 Webhook,列表、详情和 订阅 标签页在群名旁标注 ZAI 已被移出群 或 群已解散,可以撤销后删除 Webhook、移除订阅。把 ZAI 重新拉进群并完成成员同步后恢复原状。
群设置只允许群主和群管理员(或指定成员)发言时,ZAI 仍在群里但发不出回答,群名旁标注 ZAI 无发言权限,这个群仍可选作归属;恢复发言权限后标注随之消失,见ZAI 不能发言时。
这些情况下订阅和事件会怎样,见ZAI 被移出时。
在 Channel 里,ZAI 也可以直接创建和管理归属这个 Channel 的 Webhook;连接器的 Webhook 在控制台创建和维护,ZAI 只能在连接器生效的 Channel 里订阅它的事件。
ZAI 在 Channel 里自己定义的事件(见让 ZAI 自己发出事件)列在 Webhook 页底部的 Channel 事件与内置事件 里,只有定义它的 Channel 能订阅,权限与归属 Channel 的 Webhook 相同。这里只能删除事件、暂停、恢复或移除它的订阅,创建和改名都在 Channel 里让 ZAI 完成。群自带的成员进出与新消息事件(见群里的成员进出与新消息)也列在这里,不能删除,只能管理它们的订阅。
创建
在控制台 Webhook 页面点击 新建,选择 归属(Channel 或 连接器)、名称、发送方 和 验签方式;归属为 Channel 时按 Workspace 浏览并选择 Channel,ZAI 已经不在其中的 Channel 不会出现在候选中。连接器详情的 事件入口 分区也可以直接为该连接器创建。
创建成功后凭证只显示一次:对话框只有在点击 我已保存 后才会关闭,请先把接收地址和 Token 或签名密钥交给发送方。之后需要凭证时,只能在详情页 更多 菜单中 轮换凭证 生成新的,旧凭证立即失效。把鼠标移到详情页的名称上会出现铅笔按钮,点击可修改名称。
如果验签方式是 URL Token,或发送方是飞书自定义机器人,凭证就在完整地址里:完整地址只在创建或轮换时的对话框中显示。详情页顶部的 接收地址 不含凭证,不能直接交给发送方;轮换后完整地址也会变,发送方要替换整段地址。
发送方与验签
| 发送方 | 验签方式 | 发送方需要做的 |
|---|---|---|
| GitLab | 请求头 Token | 在项目 Webhooks 设置里填入接收地址,把 Token 填到 Secret token(X-Gitlab-Token) |
| 通用 | HMAC-SHA256 签名(默认) | 用签名密钥对请求体计算 HMAC-SHA256,放入 X-Ztag-Signature: sha256=<hex> |
| 通用 | 请求头 Token | 把 Token 放入 X-Ztag-Webhook-Token 请求头 |
| GitLab、通用 | URL Token | 直接向带 Token 的地址 POST;仅供无法设置请求头的系统,凭证暴露在地址里 |
| 飞书自定义机器人 | 地址验证;原自定义机器人启用了签名验证时为 飞书签名验证 | 把原调用方配置里的飞书 Webhook 地址换成完整接收地址,消息格式和签名算法不变;见飞书自定义机器人 |
签名模式可附带 X-Ztag-Timestamp,与 Z Tag 收到请求的时间相差超过五分钟时会被拒绝;签名算法见接入指南。正文建议不超过 256 KiB,超出的部分会被截断保存,可能导致验签失败或无法解析 JSON;请求体远大于这个值时会被直接拒绝,不留入站记录,见大小限制。
飞书自定义机器人
发送方选择 飞书自定义机器人,创建后把完整接收地址替换到原调用方的 Webhook 配置中。支持文本、富文本、图片、群名片和飞书卡片;原来的消息格式保持不变。
原自定义机器人启用了签名验证时,打开 原自定义机器人启用了签名验证 并填写 原签名密钥。Z Tag 验证请求体中的 timestamp 和 sign,调用方不需要增加专用请求头。
开启 保留原群聊通知 并填写 原飞书 Webhook 地址 后,Z Tag 同步调用原自定义机器人,向原群发送原消息,并向调用方返回飞书的发送结果。ZAI 按事件订阅另行处理;没有匹配的事件、订阅已暂停或 ZAI 处理失败,都不影响原群聊转发。关闭该选项后,成功只表示 Z Tag 已接收。原地址须是以 https://open.feishu.cn/open-apis/bot/v2/hook/ 开头的完整地址,签名密钥不超过 256 个字符且不含换行;不符合时表单会在对应字段下提示。
原自定义机器人设置了 IP 白名单时,请 Z Tag 管理员提供平台出口 IP,并在飞书里放行;关键词检查仍由原自定义机器人执行。详情页 配置 标签可更换密钥、原地址或关闭转发;已保存的密钥和原地址不会再显示,留空即保持不变。完整消息格式、签名与重试规则见发送方接入指南。
入站记录分别显示事件分类与 原群聊通知 状态。结果待确认 表示发送期间发生网络错误或超时,飞书可能已经收到;Z Tag 不会自动补发。调用方按原策略重试时,仍可能产生重复通知。
定义事件
一条回调会与 Webhook 的每个已启用事件定义比对,命中即产生一个事件。事件 key 是订阅时使用的稳定名称,例如 gitlab.merge_request.open。
| 匹配方式 | 说明 |
|---|---|
| 按发送方事件名 | GitLab 比较 X-Gitlab-Event 或 object_kind(Merge Request Hook 与 merge_request 等价),可再限定 object_attributes.action 中的动作,如 open;通用发送方比较 X-Ztag-Event 请求头(没有时取正文的 event 或 type)与正文的 action;飞书自定义机器人比较正文的 msg_type 与 action |
| JavaScript 分类器 | Z Tag 运行你写的一段 JavaScript 函数来判定,还可以提取摘要与数据,适合复杂条件 |
| 任意入站 | 每条通过验签的回调都算这个事件 |
分类器不能访问网络、文件和当前时间,必须在 200 ms 内返回 { match: true | false },代码不超过 32 KiB。按发送方事件名 与 任意入站 的定义在对话框中编辑;JavaScript 分类器 在独立页面编辑,页面中的 用样例测试 区域可用样例事件名与样例请求体运行分类器并显示 命中 或 未命中,也可以从某条入站记录打开 用此记录测试分类器。飞书自定义机器人的事件名取自请求体的 msg_type,用样例测试 和 发送测试事件 因此只填请求体。
每个 Webhook 最多 30 个事件定义。匹配方式 添加后不能修改,需要换方式时只能删除后重建。行内菜单可以单独暂停或恢复某个定义,只有已启用的定义参与比对。删除事件定义会同时移除它的全部订阅,确认时会显示受影响的订阅数。每个 Channel 能持有的订阅数也有上限,见订阅事件。
检查链路
- 发送测试事件 用于验证样例分类和投递,并显示命中的事件定义;它会跳过外部请求的验签,但仍产生真实的事件与投递。样例请求体与分类器测试样例一样不能超过 256 KiB(按 UTF-8 字节计,中文约 8.7 万字)。Webhook 已暂停时不能发送测试事件。发送方的网络与签名需要按接入指南实际推送验证。飞书自定义机器人的测试事件只验证 Z Tag 内的分类和投递,不向原自定义机器人转发;真实发送需要从调用方请求完整接收地址。
- 入站记录 列出通过验签的回调、分类结果与命中数,点击 查看 打开请求头子集与请求体。分类失败时,失败 列逐条写明哪个事件定义的分类器出了什么问题,例如“部署完成:超时”;分类器求值服务暂时不可用时,记录保持 待分类 并注明稍后重试。
- 订阅 列出各 Channel 的订阅。投递到 列显示 当前话题(投递到创建订阅时所在的话题)、每次新话题(每个事件在 Channel 里开启一个新话题)、不开话题(ZAI 处理事件时不开话题,自己决定是否在 Channel 里直接发消息)或 所在消息的话题(回在触发事件的那条新消息的话题里)。行内菜单可以暂停、恢复或移除订阅,并打开 投递记录 查看每次投递的状态与 失败原因,打开期间会自动刷新。状态 正在开启新话题 表示 ZAI 正在为这个事件发出新话题的第一条消息,发出后才开始处理。 展示 / 触发 列显示订阅是否先发通知(默认、消息 或 卡片)以及之后是否处理(触发 ZAI 或 不触发 ZAI),见先发通知;订阅有自定义的通知样式时,可在投递记录里查看它的代码。发过通知的投递多出 通知 列,显示通知时间;订阅带按钮或有投递被点过按钮时,再多出 按钮点击 列,列出点了哪个按钮、什么时候点的,以及是触发了 ZAI 还是只做了记录,按钮本身的设置可在投递记录里查看;只发通知的投递在通知发出后显示为 已通知。通知没能照样式画出、改用事件名称和摘要,或卡片改发了消息时,这一列写明原因。
- 事件记录 列出已产生的事件与摘要,可按事件定义筛选并展开数据。Z Tag 根据回调内容生成的摘要按发送方事件种类显示,例如 GitLab 合并请求显示编号、动作与标题,旁边注明项目和触发人;分类器返回的摘要和飞书消息的正文原样显示。
入站记录默认保留 14 天。事件与它的投递记录默认保留 90 天(从事件产生时算起),之后从 事件记录 和投递记录中消失;届时仍有投递未结束的事件,在投递全部结束后删除。订阅本身和它的累计投递次数不受影响。
订阅的 最近失败 和投递记录的 失败原因 显示下表中的说明;有原始诊断信息时(例如平台返回的报错),它显示在说明下方,便于排查。最近失败 一栏放不下时截断显示,完整内容见投递记录。较早的记录没有分类,显示为 未分类失败 并附原始信息。
| 说明 | 含义 | 之后会怎样 |
|---|---|---|
| 该 Channel 已无法使用这个 Webhook | 投递时这个连接器已对该 Channel 不生效,这次事件被跳过,不会补投 | 订阅不变;连接器重新对该 Channel 生效后,之后的投递照常进行 |
| 事件、Webhook 或所在消息已不存在 | 投递时事件、它所属的 Webhook,或要回复的那条消息已不存在 | 这次投递结束,不会补投 |
| 应用不可用(已停用或已卸载) | ZAI 所在的 IM 应用在投递时不可用,例如应用被停用 | 这次事件不处理;应用恢复后,之后到达的事件照常投递 |
| Workspace 已由其他应用接手 | 投递期间 Workspace 换成了另一个 IM 应用,这次事件没能开始处理 | 订阅自动转到新的应用,之后到达的事件照常投递 |
| ZAI 已不在该 Channel 中 | ZAI 已被移出这个群 | 到达的和已排队的事件被丢弃,不计入投递次数,订阅保持启用;把 ZAI 拉回群后,之后到达的事件照常投递 |
| Channel 已解散 | 群已解散 | 订阅随之结束 |
| Channel 有组织外的成员或访客,已跳过 | 这个 Channel 里有本组织以外的人 | 事件被丢弃,订阅保持启用;Channel 里恢复为只有本组织成员后,之后到达的事件照常投递 |
| Channel 的设置不允许 ZAI 发言 | Channel 的设置不允许 ZAI 发言,消息没有发出 | 订阅保持启用,见ZAI 不能发言时 |
| 排队过多,已丢弃较早的投递 | 同一订阅排队的事件超过上限,最早的被丢弃;上限见订阅事件 | 订阅保持启用 |
| 订阅已移除、订阅已到期、订阅已达投递次数上限 | 订阅被移除、到期或达到次数上限时,还在排队的事件随之结束 | 不是故障,不会写入 最近失败 |
| 以“稍后重试”结尾的说明,例如 暂时无法确定 Channel 所在的范围,稍后重试 | 暂时无法投递 | Z Tag 会自动重试 |
| 其他说明,例如 沙箱意外中断、Agent 执行失败 | ZAI 处理这个事件时失败的原因 | 可以在对应的 Channel 里直接问 ZAI 这个订阅为什么没有结果 |
最近失败 显示最近一次投递遇到的问题,包括正在等待重试的情况;之后有一次投递正常结束或被停止,这一列就会清空。订阅达到次数或时间限制、被移除不算失败;因群解散而结束的订阅记为 Channel 已解散。
订阅达到次数或时间限制、被移除,或它的事件定义被删除后,不再排队新的投递,积压的投递随之结束;已经开始的任务继续执行。暂停订阅后,已排队的事件保留,恢复后继续处理;暂停期间新到的事件不会进入这个订阅,恢复后也不补发。
在详情页 更多 菜单中点击 暂停接收 可以暂时停用接收地址,点击 恢复接收 后重新启用。GitLab 与通用 Webhook 暂停期间的回调直接丢弃、不补收。飞书自定义机器人暂停期间返回失败,即使开启了 保留原群聊通知 也不转发;只想让 ZAI 暂时不处理、转发照常时,暂停对应的订阅即可。
点击 撤销 后接收地址返回 410,历史记录保留,撤销不可恢复。列表默认隐藏已撤销的 Webhook,关闭 隐藏已撤销 后可以打开它,并在 更多 菜单中 删除;删除会一并移除它的事件定义、订阅、入站记录、事件与投递记录。删除所属连接器时跳过撤销,直接删除 Webhook,调用方收到 404,见修改前检查影响。