Activepieces AskHandle 集成 Piece 深度解析:构建、鉴权、动作与 Webhook 触发器
【免费下载链接】activepiecesAI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepieces
AskHandle 是一款面向客户支持与销售场景的聊天与线索管理服务,本仓库中的@activepieces/piece-ask-handle是 Activepieces 官方社区维护的 AskHandle 集成 Piece,用于在自动化工作流中收发聊天室消息、管理销售线索,并对新消息、新线索、新聊天室等事件做出实时响应。读完本文,你将掌握该 Piece 的构建命令、API Key 鉴权机制、4 个动作与 3 个触发器的完整参数语义,以及其基于 Webhook 的实时触发实现原理,可以直接在 Activepieces 中搭建"线索捕获 → 即时跟进"的自动化流程。
Piece 概览:一个模块化封装的 AskHandle 客户端
该 Piece 的入口文件 src/index.ts 通过createPiece组装了完整的集成能力:
- 展示名称:
AskHandle - 鉴权方式:
askHandleAuth(API Key 密文输入) - 最低支持版本:
minimumSupportedRelease: '0.36.1',即需要 Activepieces 0.36.1 及以上版本才能安装使用 - 维护作者:
onyedikachi-david - 动作(actions):创建消息
createMessage、创建线索createLead、列出聊天室listRooms、列出线索listLeads - 触发器(triggers):新消息
newMessageTrigger、新线索newLeadTrigger、新聊天室newRoomTrigger
从 package.json 可以看到,包名为@activepieces/piece-ask-handle(版本0.1.8,commonjs格式),其运行依赖@activepieces/pieces-common、@activepieces/pieces-framework、@activepieces/core-piece-types与@activepieces/core-utils,这些 workspace 依赖提供了 HTTP 客户端、Piece 属性框架等基础能力。
构建该 Piece:README 中的标准命令
该 Piece 的 README.md 给出了标准的构建方式:在仓库根目录执行以下命令,即可单独构建 AskHandle 集成库:
turbo run build --filter=@activepieces/piece-ask-handle该命令通过 Turborepo 的任务过滤机制,只构建@activepieces/piece-ask-handle及其上游 workspace 依赖,无需构建整个仓库。构建脚本定义在 package.json 的scripts.build中,核心是:
tsc -p tsconfig.lib.json && cp package.json dist/即先用 TypeScript 编译器按库模式配置(tsconfig.lib.json)把src/编译为dist/,再把package.json复制到产物目录,保证发布后的包元数据完整。除此之外,该包还提供了bundle(调用 CLI 打包 Piece)与lint(ESLint 检查src/**/*.ts)两个脚本。
鉴权设计:API Key 校验与连接验证
AskHandle 使用 API Key 作为连接凭证,实现在 src/lib/common/auth.ts。它基于PieceAuth.SecretText定义了一个必填的密文输入项,用户需要在 AskHandle 控制台完成以下步骤获取密钥:
- 访问 AskHandle 控制台(
https://dashboard.askhandle.com)并登录账号; - 进入 API 设置页面;
- 创建或复制 API Token;
- 将 Token 粘贴到 Activepieces 的连接配置中。
值得注意的是,该鉴权定义了一个validate回调:当用户在 Activepieces 中保存连接时,Piece 会立即向GET https://dashboard.askhandle.com/api/v1/rooms/发起一次真实请求来验证密钥有效性。请求头使用Authorization: Token <apiKey>的认证格式(注意是Token前缀而非Bearer)。只有当服务端返回 HTTP 200 时校验才通过,否则会给出"Invalid API key"之类的错误提示。这意味着密钥在保存连接阶段就会被预检,能有效避免配置了无效凭证的流程在运行期才报错。
统一 API 客户端与错误语义映射
所有动作的数据交互都收敛在 src/lib/common/client.ts 的askHandleApiCall函数中。该函数统一以https://dashboard.askhandle.com/api/v1为基址,拼接传入的path发起请求,头部固定携带Authorization: Token <apiKey>与Content-Type: application/json。成功(2xx)时直接返回响应体;失败时会将 HTTP 状态码映射为语义明确的中文可读错误信息:
| 状态码 | 错误语义 |
|---|---|
| 400 | 请求参数无效,需检查提交的数据 |
| 401 | 认证失败,API Key 无效,需核对凭证 |
| 403 | 访问被拒绝,当前凭证无权访问该资源 |
| 404 | 资源不存在 |
| 500 / 502 / 503 / 504 | 服务端异常,建议稍后重试 |
| 其他 | 携带具体状态码的通用错误信息 |
此外,当请求未返回任何状态码(如网络层失败)时,会抛出包含底层错误信息的 "Unexpected error"。这种集中式的错误处理让 4 个动作无需各自重复编写异常逻辑,也保证了用户在工作流运行日志中能看到统一、可排查的错误文案。
四个动作详解:从读取到写入的完整能力
发送消息到聊天室(Create Message)
定义于 src/lib/actions/create-message.ts,分类为WRITE,通过POST /messages/向指定聊天室追加一条消息。参数如下:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
room | Dropdown | 是 | 目标聊天室,从动态加载的聊天室列表中选取(值为 room 的 UUID) |
body | LongText | 是 | 消息正文内容 |
nickname | ShortText | 否 | 发送者昵称 |
email | ShortText | 否 | 发送者邮箱 |
phone_number | ShortText | 否 | 发送者电话号码 |
从源码实现看,请求体固定包含body与room: { uuid }结构,仅当昵称、邮箱、电话被填写时才追加对应字段(避免发送空串)。该动作非幂等,每次调用都会新增一条消息,适合作为自动回复或人工客服通知的输出节点。
创建线索(Create Lead)
定义于 src/lib/actions/create-lead.ts,分类为WRITE,通过POST /leads/创建一条新线索记录,参数如下:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
nickname | ShortText | 否 | 线索昵称 |
email | ShortText | 否 | 线索邮箱 |
phone_number | ShortText | 否 | 线索电话 |
device | ShortText | 否 | 设备信息 |
from_page_title | ShortText | 否 | 线索来源页面标题 |
referrer | ShortText | 否 | 来源页 URL |
实现上仅将已填写的字段纳入请求体。该动作同样非幂等,每次调用都会创建独立线索,不会按邮箱或电话去重,适合表单提交、落地页捕获等"新增潜客"场景。
列出聊天室(List Rooms)
定义于 src/lib/actions/list-rooms.ts,分类为SEARCH,无任何输入参数,直接GET /rooms/返回账号下所有聊天室。可用于在流程中枚举会话、按需查找 room UUID。
按时间窗口查询线索(List Leads)
定义于 src/lib/actions/list-leads.ts,分类为SEARCH,通过GET /leads/查询线索,支持三个可选过滤参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
start_date | DateTime | 否 | 线索起始时间过滤(源码会将其转换为YYYY-MM-DD日期串) |
end_date | DateTime | 否 | 线索截止时间过滤 |
limit | Number | 否 | 返回线索的最大条数 |
源码中会将日期参数先经new Date(...).toISOString()规范化为 ISO 格式再截取日期部分拼入查询串(如/leads/?start_date=2026-09-01&end_date=2026-09-12&limit=50),未填任何过滤条件时则请求裸路径/leads/。这是一个只读、幂等的查询动作,适合作为周期性的线索同步节点。
动态下拉属性:聊天室与线索的实时选择
src/lib/common/props.ts 定义了两个共享的动态下拉属性,供动作与触发器界面复用:
roomDropdown:调用GET /rooms/拉取聊天室列表,以room.name || room.label || Room <uuid>作为显示标签、room.uuid作为提交值;leadDropdown:调用GET /leads/拉取线索列表,以lead.nickname || lead.email || Lead <uuid>作为标签、lead.uuid作为值。
两个下拉在未连接账号时都会进入disabled状态并提示"Please connect your account first",请求失败时则提示 "Error loading rooms/leads"。它们兼容分页结构(response.results)与直接数组两种响应形态,从源码结构看这体现了对 AskHandle API 两种返回格式的适配。
三个 Webhook 触发器:实时事件响应
三个触发器分别对应新消息、新线索、新聊天室事件,均采用TriggerStrategy.WEBHOOK策略,实现在 src/lib/triggers/new-message.ts、src/lib/triggers/new-lead.ts 与 src/lib/triggers/new-room.ts,三者的生命周期实现完全对称。
事件订阅与生命周期管理
每个触发器都实现了onEnable/onDisable/run三段式生命周期:
onEnable(启用时注册订阅):向POST /webhooks/注册一个 webhook,请求体为{ event: '<事件名>', target: context.webhookUrl },其中target是 Activepieces 为该触发器动态生成的接收地址。注册成功后(HTTP 200 或 201),把返回的 webhookuuid存入context.store(键名分别为_askhandle_webhook_message、_askhandle_webhook_lead、_askhandle_webhook_room)。onDisable(停用时注销订阅):先从 store 读取之前保存的 webhook uuid,再调用DELETE /webhooks/{uuid}/注销订阅并清理 store,防止停用后仍收到回调。run(事件分发):收到回调后从请求体取data字段(取不到则回退整个 payload)作为事件负载返回给工作流。
三个触发器的订阅事件名分别为:新消息message.added、新线索lead.added、新聊天室chat.added。
示例负载(sampleData)
源码为每个触发器内置了示例数据,便于在编辑器中预览数据结构:
- 新消息:
{ uuid, nickname: 'Mary', email: 'mary@example.com', body: 'Hello!', is_support_sender: false, sent_at }——其中is_support_sender可用来判断消息是否来自支持人员; - 新线索:
{ uuid, nickname, email, phone_number, device, from_page_title, referrer, created_at }——携带完整的联系人与来源上下文; - 新聊天室:
{ uuid, label, name, rating, is_bot_use, created_at, messages }——包含聊天室评级、是否机器人使用等元信息。
典型应用场景:线索驱动的实时跟进
综合以上能力,可以在 Activepieces 中构建如下闭环:
- 用New Lead触发器监听"新线索产生"事件(
lead.added); - 在流程中解析负载里的
nickname、email、from_page_title等字段,路由到 CRM、表格或通知节点; - 用Create Message动作向对应聊天室
POST /messages/发送即时欢迎或跟进消息,结合List Leads / List Rooms动作在流程内动态查询和补全上下文。
由于触发器采用 Webhook 推送而非轮询,事件在 AskHandle 侧产生后即可实时到达工作流;而 store 机制保证了订阅注册与注销的成对管理,重复启用/停用触发器不会在 AskHandle 侧累积失效的 webhook 订阅。
源码结构一览
packages/pieces/community/ask-handle/ ├── README.md # 构建说明 ├── package.json # 包元数据与构建/打包脚本 └── src/ ├── index.ts # createPiece 入口,组装动作与触发器 ├── i18n/ # 多语言文案(de/es/fr/ja/nl/pt/zh 等) └── lib/ ├── common/ │ ├── auth.ts # API Key 鉴权与连接校验 │ ├── client.ts # 统一 API 客户端与错误映射 │ └── props.ts # room/lead 动态下拉属性 ├── actions/ │ ├── create-message.ts │ ├── create-lead.ts │ ├── list-rooms.ts │ └── list-leads.ts └── triggers/ ├── new-message.ts ├── new-lead.ts └── new-room.ts从源码结构看,该 Piece 遵循 Activepieces 社区 Piece 的标准分层:common收敛鉴权、客户端与共享属性,actions与triggers各自独立成文件,入口文件仅做声明式组装,整体结构清晰、易于扩展(例如新增动作时只需在lib/actions下添加文件并在index.ts注册)。如果你需要在本地二次开发,直接基于上述目录修改,再执行开头的turbo run build --filter=@activepieces/piece-ask-handle即可验证构建。
【免费下载链接】activepiecesAI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepieces
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考