1つのエージェント、あらゆるチャネル
Webウィジェット、Telegram、WhatsAppが同じメモリを持つ同じエージェントに到達する仕組み — アイデンティティの解決、共通の制御フロー、そしてチャネル固有のまま残るもの。
顧客があなたのウェブサイトで何かを尋ね、2週間後にWhatsAppから追加で質問してくる。それが1つの関係なのか、それとも2人の見知らぬ人なのかは、チャットUIではなく、アイデンティティがどう解決されるかで決まります。
全体像
チャネルは入り口であって、サイロではありません。それぞれが、下層にある同じ3つのものへと解決されます。
エージェントはチャネルごとに複製されません。検索・メモリ・追加のフォローアップはすべてスペースにぶら下がっているので、別のアプリから来てもトランスポートが変わるだけで、それ以外は何も変わりません。
アイデンティティの解決
各チャネルは外部の識別子を提供します — ウィジェットトークンのエンドユーザーID、TelegramのユーザーID、WhatsAppの番号などです。解決は (tenant, external_user_id) によって行われます。ルックアップと、初回に見たときのプロビジョニングです。
知っておく価値のある2つの点があります。
- 初回コンタクトには競合があり、それは処理済みです。 同時に到着した2つのメッセージは、どちらもユーザーが見つからず、どちらも作成しようとします。一意制約が勝者を決め、負けた側は失敗せずに読み直します。だから同時に届いた初回メッセージの一斉発生は、エラーではなく1人のユーザーを生みます。
- スペースは解決される、または作成される。 すべてのユーザーにはデフォルトのスペースがあります。明示的に要求されたスペースはそのユーザーに属していなければならず、そうでなければリクエストは拒否されます。このチェックが、細工されたリクエストが他人の会話を読むのを止めています。
1人の人物を複数チャネルにわたって結び付けるのはテナントの判断であり、推測ではありません。 プラットフォームは、似ているからといってウェブサイトの訪問者とWhatsAppの番号を統合したりしません。その推論こそ、システムがある顧客の履歴を別の顧客に漏らす仕組みです。同一人物だと識別できる場合(サインイン済みのユーザー、エンドユーザーID付きのリンク)は、同じ識別子を渡せば履歴がその人物についてまわります。識別できない場合は、別々のまま保たれます。
アダプターが共有するもの、しないもの
TelegramとWhatsAppは見た目は違いますが、同じ仕事をします。アダプター層は、乖離すべきでないものすべてを保持します。
| アダプターで共有 | 各チャネルに委ねる |
|---|---|
| アイデンティティ解決とスペースのルックアップ | メッセージのレンダリングと送信呼び出し |
| 現在セッションの読み書き | Telegramのインラインキーボードとフォームのプロンプト |
| コマンド — new, list, switch, history, rename, delete, location, help | WhatsAppのリスト応答とインタラクティブ応答 |
| 履歴の再生と整形 | プラットフォーム固有の添付ファイル処理 |
| 応答が遅い旨のヒント | |
| ターンの実行 |
ルールは、会話のセマンティクスは1か所に置くということです。セッション切り替えがWhatsAppとTelegramでわずかに違う動きをしたら、その違いは顧客がぶつかるまで目に見えません。
実務上の帰結として、これらはプライベートチャットの統合です。TelegramのプライベートチャットではチャットIDと送信者IDが同じなので、送信先とアイデンティティのキーが1つの値に潰れます。だからこそアダプターは「これは誰か」と「どこへ返信するか」を単一の概念として扱えるのです。
長時間かかる回答
ターンの中では生成できない返答もあります。エージェントは作業をスケジュールし、後から答えを届けることができ、リクエストが来たチャネルへプッシュされます — Webウィジェットの吹き出し、TelegramやWhatsAppのメッセージです。スケジュールされたフォローアップをご覧ください。
これが実務上意味すること
- どこからメッセージを送ってきても、1人の顧客につき1つの履歴。
- チャネルを追加しても、会話ロジックが分岐しません。
- 検索とメモリはどこでも同一に振る舞います。チャネルではなくスペースに紐づいているからです。
チャネルのセットアップはTelegram & WhatsAppとウィジェットの埋め込みで扱っています。