一个智能体,通吃所有渠道
网页挂件、Telegram 和 WhatsApp 如何接到同一个智能体、共用同一份记忆——身份解析、共享的控制流,以及哪些部分保持渠道特有。
客户先在你网站上问了点什么,两周后从 WhatsApp 追问过来。这到底算一段关系,还是两个陌生人,取决于身份是怎么解析的——而不是取决于聊天界面。
整体形状
渠道是入口,不是烟囱。每一个渠道最终都归到底下同样的三样东西:
智能体并不会按渠道复制一份。检索、记忆和跟进全都挂在空间上,所以换一个 App 进来,变的只是传输方式,别的什么都没变。
身份解析
每个渠道都提供一个外部标识:挂件令牌里的终端用户 id、Telegram 用户 id、WhatsApp 号码。解析依据是 (tenant, external_user_id)——查一次,首次见到就建一个。
有两个细节值得知道:
- 首次接触会有竞态,而且已经处理了。 两条消息同时到达,都会查不到用户,都会去创建。唯一约束会裁决,落败的一方改为重新读取而不是报错——所以一串同时到达的首条消息,产出的是一个用户,而不是一个错误。
- 空间要么解析出来,要么创建出来。 每个用户都有一个默认空间;如果请求里显式指定了空间,它必须属于该用户,否则请求被拒。正是这道校验,挡住了构造出来的请求去读别人的对话。
把同一个人在不同渠道之间关联起来,是租户的决定,而不是系统的猜测。 平台不会因为「看着像」就把一位网站访客和一个 WhatsApp 号码合并——这类推断正是系统把一位客户的历史泄给另一位的根源。凡是你能确认是同一个人的场景(已登录用户,或链接里带了终端用户 id),传同一个标识,历史就跟着走;确认不了的,就各自独立。
适配层共享什么,不共享什么
Telegram 和 WhatsApp 长得不一样,干的活是一样的。适配层握着所有不该出现分叉的东西:
| 适配层共享 | 各渠道自理 |
|---|---|
| 身份解析与空间查找 | 消息渲染与发送调用 |
| 当前会话的读写 | Telegram 内联键盘与表单提示 |
| 命令——新建、列表、切换、历史、重命名、删除、位置、帮助 | WhatsApp 列表与交互式回复 |
| 历史回放与格式化 | 平台特有的附件处理 |
| 慢响应提示 | |
| 执行一轮对话 |
原则是对话语义只存在于一个地方。如果 WhatsApp 上的会话切换和 Telegram 上略有出入,这点差异要等到客户撞上去了才会被发现。
一个实际推论:这些都是私聊集成。在 Telegram 私聊里,chat id 和发送者 id 是同一个值,于是发送目标和身份键合成了一个概念——这也是适配层可以把「这是谁」和「回哪儿去」当成一件事的原因。
需要长时间才能给出的回答
有些回复没法在一轮之内产出。智能体可以把这项工作排上日程,让答案稍后送达,并推回请求发起的那个渠道——网页挂件里的一个气泡,或者 Telegram、WhatsApp 里的一条消息。参见定时跟进。
这在实际使用中意味着什么
- 一位客户,一份历史,不管他从哪儿发消息过来。
- 新增一个渠道,不会让对话逻辑分叉。
- 检索和记忆在哪儿都表现一致,因为它们挂在空间上,而不是挂在渠道上。
渠道怎么配置,见 Telegram 与 WhatsApp 和嵌入挂件。