全渠道消息
将 WhatsApp、Facebook Messenger 和 Instagram 连接到 Sonzai 智能体,查看实时线程,并在需要时交给人工接管。
全渠道消息让 Sonzai 智能体通过 Meta 渠道对话,同时保留你在网页或移动聊天中使用的同一套人格、记忆和对话历史。你只需要连接一次渠道,把它映射到某个智能体人格,然后用 Conversations API 检查线程、订阅事件,或接管一段实时对话。
连接 Meta 渠道
有两种设置路径:
- 自带应用(Bring Your Own App) — 主要路径。你创建并拥有 Meta app、业务资产、Webhook verify token 和 access token。Sonzai 保存你提供的渠道凭据,并通过该应用投递消息。
- Embedded Signup — Sonzai 控制台中的一键式简化流程。该功能正在逐步推出;如果它已经对你的租户可见,并且你不需要自己管理 Meta app,可以使用它。
自带应用
此流程适用于 WhatsApp、Facebook Messenger 或 Instagram。
- 在 Meta for Developers 中创建或打开要用于该渠道的 app。
- 添加对应渠道的产品:WhatsApp、Messenger 或 Instagram。
- 连接所需的业务资产:
- WhatsApp:WhatsApp Business Account 和电话号码。
- Messenger:接收消息的 Facebook Page。
- Instagram:连接到 Facebook Page 的 Instagram professional account。
- 在该 Meta 产品的 Webhook 设置中,将 callback URL 设为
https://api.sonz.ai/webhooks/channels/meta。 - 创建一个 verify token。使用由租户拥有的随机字符串并安全保存。把同一个值粘贴到 Meta 和 Sonzai 控制台。
- 为所选产品订阅消息投递相关字段。
- 生成一个有权访问所选资产的 access token。在 Meta 支持的地方,优先使用长期有效的 system user 或 page token。
- 在 Sonzai 控制台打开 Channels,选择 Add channel,然后选择 Meta 渠道和 Bring Your Own App。
- 粘贴控制台要求的值:
- App ID
- App Secret
- WhatsApp 的 Phone Number ID、Messenger 的 Page ID,或 Instagram 的 Instagram Account ID
- Access Token
- Verify Token
- 选择智能体路由目标,保存渠道,然后从已连接账号发送一条测试消息。
凭据处理
App Secret、Access Token 和 Verify Token 都应按凭据处理。不要把它们提交到源码仓库,也不要发送到浏览器客户端。如果凭据泄露,请在 Meta 中轮换 token,并更新 Sonzai 渠道配置。
渠道路由
每个渠道都会映射到一个智能体人格。你可以把某个渠道的所有消息都路由到同一个默认智能体;如果控制台启用了 tier,也可以按 tier 拆分流量。例如,WhatsApp 支持渠道可以把免费 tier 用户路由到分诊人格,把付费 tier 用户路由到礼宾式支持人格。
如果消息没有匹配到已配置的渠道或 tier,Sonzai 会使用该渠道的默认智能体。如果没有配置默认智能体,对话会保持未路由状态,并发出 conversation.unrouted Webhook 事件,便于你的后端分配路由或提醒人工处理。
对话与可观测性
使用 Conversations API 可以跨 WhatsApp、Messenger、Instagram 以及租户连接的其他渠道列出、搜索、检查和流式接收线程。
列出和搜索线程
REST:
curl -H "Authorization: Bearer $SONZAI_API_KEY" \
"https://api.sonz.ai/conversations?channel=whatsapp&status=open&q=refund&limit=25"SDK:
const conversations = await client.conversations.list({
channel: "whatsapp",
status: "open",
query: "refund",
agentId: "agent-id",
limit: 25,
});
for (const thread of conversations.items) {
console.log(thread.id, thread.channel, thread.agentId, thread.lastMessageAt);
}查看线程
REST:
curl -H "Authorization: Bearer $SONZAI_API_KEY" \
"https://api.sonz.ai/conversations/conversation-id"
curl -H "Authorization: Bearer $SONZAI_API_KEY" \
"https://api.sonz.ai/conversations/conversation-id/messages?limit=50"SDK:
const thread = await client.conversations.get("conversation-id");
const messages = await client.conversations.messages("conversation-id", {
limit: 50,
});
console.log(thread.participant, messages.items.at(-1)?.text);流式接收实时对话
当你的控制台、CRM 或支持台需要实时更新且不想轮询时,使用 stream。
for await (const event of client.conversations.stream("conversation-id")) {
console.log(event.type, event.message?.text);
}Webhook 事件
当你的后端需要持久可观测性或工作流自动化时,订阅 conversation 事件。处理事件前请验证 Sonzai Webhook 签名;签名模型与 Webhook 页面相同。
| 事件 | 触发时机 |
|---|---|
conversation.started | 新的渠道对话被创建并路由到智能体 |
conversation.message | 用户、智能体或人工操作员向线程添加消息 |
conversation.takeover.started | 人工操作员接管对话 |
conversation.takeover.released | 操作员把对话释放回智能体 |
conversation.message.failed | 消息无法投递到外部渠道 |
conversation.unrouted | Sonzai 收到的消息未匹配到已配置渠道、tier 或默认智能体 |
事件负载包含 conversation ID、channel、已路由时的 agent ID、参与者标识,以及与事件相关的消息或失败详情。不要把 Webhook 投递当作唯一事实来源;收到事件后应使用 Conversations API 重新读取线程。
人工接管
人工接管会暂停实时对话中的自主智能体回复,让操作员通过同一个智能体人格回复。终端用户看到的仍是该渠道身份发出的消息,智能体也会把这段 transcript 保存在记忆中。接管释放后,智能体会记得用户和操作员在接管窗口内说过的话。
REST 流程
# 1. 接管实时对话
curl -X POST "https://api.sonz.ai/conversations/conversation-id/takeover" \
-H "Authorization: Bearer $SONZAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"operator_id":"op-123","reason":"billing escalation"}'
# 2. 以智能体人格发送回复
curl -X POST "https://api.sonz.ai/conversations/conversation-id/messages" \
-H "Authorization: Bearer $SONZAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"operator_id":"op-123","text":"I can help check that invoice now."}'
# 3. 释放回自主智能体处理
curl -X DELETE "https://api.sonz.ai/conversations/conversation-id/takeover" \
-H "Authorization: Bearer $SONZAI_API_KEY"SDK 流程
await client.conversations.takeOver("conversation-id", {
operatorId: "op-123",
reason: "billing escalation",
});
await client.conversations.sendAsAgent("conversation-id", {
operatorId: "op-123",
text: "I can help check that invoice now.",
});
await client.conversations.release("conversation-id", {
operatorId: "op-123",
});操作员语气
操作员回复会以智能体人格发送,而不是作为单独的人类身份发送。请让支持台话术与智能体语气保持一致,因为 transcript 会成为智能体未来上下文的一部分。