Think エージェントが Chat SDK のメッセンジャー webhook を直接受け取り、返信するときにメッセンジャーを使います。Think が webhook ルート、耐久性のある返信 fiber、会話のルーティング、プロバイダーへのストリーム配信を担います。
Think パッケージと、使うプロバイダーアダプターをインストールします。
npm install @cloudflare/think agents ai @chat-adapter/telegramプロバイダーアダプターはプロバイダー固有のサブパスからエクスポートされるため、使わないアダプターは Worker にバンドルされません。
import { Think } from "@cloudflare/think";
import {
defineMessengers,
ThinkMessengerStateAgent,
} from "@cloudflare/think/messengers";
import telegramMessenger from "@cloudflare/think/messengers/telegram";
export { ThinkMessengerStateAgent };
export class SupportAgent extends Think {
getMessengers() {
return defineMessengers({
telegram: telegramMessenger({
token: this.env.TELEGRAM_BOT_TOKEN,
userName: "support_bot",
secretToken: this.env.TELEGRAM_WEBHOOK_SECRET_TOKEN,
}),
});
}
}import { Think } from "@cloudflare/think";
import {
defineMessengers,
ThinkMessengerStateAgent,
} from "@cloudflare/think/messengers";
import telegramMessenger from "@cloudflare/think/messengers/telegram";
export { ThinkMessengerStateAgent };
export class SupportAgent extends Think<Env> {
getMessengers() {
return defineMessengers({
telegram: telegramMessenger({
token: this.env.TELEGRAM_BOT_TOKEN,
userName: "support_bot",
secretToken: this.env.TELEGRAM_WEBHOOK_SECRET_TOKEN,
}),
});
}
}デフォルトの telegram キーでは、Telegram webhook を次の URL に登録します。
https://<your-worker>/messengers/telegram/webhooktelegramMessenger() は webhook モードでは secretToken が必要です。ただし、独自の verifyWebhook 関数を渡すか、verifyWebhook: false で明示的に無効化した場合を除きます。
1 つの Think エージェントが複数の Telegram ボットを持つ場合は、各プロバイダーに異なる Chat SDK アダプター名を付けます。
defineMessengers({
support: telegramMessenger({
adapterName: "support-telegram",
token: this.env.SUPPORT_TELEGRAM_BOT_TOKEN,
userName: "support_bot",
secretToken: this.env.SUPPORT_TELEGRAM_WEBHOOK_SECRET_TOKEN,
}),
sales: telegramMessenger({
adapterName: "sales-telegram",
token: this.env.SALES_TELEGRAM_BOT_TOKEN,
userName: "sales_bot",
secretToken: this.env.SALES_TELEGRAM_WEBHOOK_SECRET_TOKEN,
}),
});defineMessengers({
support: telegramMessenger({
adapterName: "support-telegram",
token: this.env.SUPPORT_TELEGRAM_BOT_TOKEN,
userName: "support_bot",
secretToken: this.env.SUPPORT_TELEGRAM_WEBHOOK_SECRET_TOKEN,
}),
sales: telegramMessenger({
adapterName: "sales-telegram",
token: this.env.SALES_TELEGRAM_BOT_TOKEN,
userName: "sales_bot",
secretToken: this.env.SALES_TELEGRAM_WEBHOOK_SECRET_TOKEN,
}),
});重複したアダプター名は起動時に失敗します。共有 Chat SDK ランタイム上で、プロバイダー同士が上書きしないようにするためです。
ルートの Think エージェントは、フレームワークのサブエージェントルーティングと Think 内部ルートのあと、ユーザー定義の onRequest フォールバックより前に、メッセンジャーの webhook ルートを処理します。メッセンジャールートはルート専用です。サブエージェントクラスで getMessengers() を定義しても、そのサブエージェント用の webhook ルートは作られません。
デフォルトでは、Think はダイレクトメッセージとメンションに返信します。新しいメンションはその Chat SDK スレッドを購読するため、同じスレッド内の後続メンションも観測されます。ただし、購読済みスレッドの通常メッセージとボタン操作は、オプトインしない限り無視されます。
telegramMessenger({
token: this.env.TELEGRAM_BOT_TOKEN,
userName: "support_bot",
secretToken: this.env.TELEGRAM_WEBHOOK_SECRET_TOKEN,
respondTo: ["direct-message", "mention", "subscribed-thread", "action"],
});telegramMessenger({
token: this.env.TELEGRAM_BOT_TOKEN,
userName: "support_bot",
secretToken: this.env.TELEGRAM_WEBHOOK_SECRET_TOKEN,
respondTo: ["direct-message", "mention", "subscribed-thread", "action"],
});アクションイベントは、アクション ID、値、元のメッセージ ID、開始ユーザーを含む Think のユーザーメッセージに変換されます。プロバイダー固有のアクション詳細が必要なときは、フックやツール内で getMessengerContext()?.action を使います。アクションはオプトインです。インタラクティブカードが誤ってモデルのターンを起動しないようにするためです。
デフォルトの会話モードは、Chat SDK スレッドごとに 1 つの Think サブエージェントです。グループチャット、ダイレクトメッセージ、チャンネルが意図せずメモリを共有しないようにします。
すべてのメッセンジャートラフィックが 1 つの Think セッションを共有すべきときは、ルートエージェントを会話として使います。
telegramMessenger({
token: this.env.TELEGRAM_BOT_TOKEN,
userName: "support_bot",
secretToken: this.env.TELEGRAM_WEBHOOK_SECRET_TOKEN,
conversation: "self",
});telegramMessenger({
token: this.env.TELEGRAM_BOT_TOKEN,
userName: "support_bot",
secretToken: this.env.TELEGRAM_WEBHOOK_SECRET_TOKEN,
conversation: "self",
});テナント、チャンネル、スレッド、ユーザーに応じてルーティングするときは、resolver を使います。
telegramMessenger({
token: this.env.TELEGRAM_BOT_TOKEN,
userName: "support_bot",
secretToken: this.env.TELEGRAM_WEBHOOK_SECRET_TOKEN,
conversation(event) {
return {
target: "subagent",
name: `tenant:${event.thread.channelId ?? event.thread.id}`,
};
},
});telegramMessenger({
token: this.env.TELEGRAM_BOT_TOKEN,
userName: "support_bot",
secretToken: this.env.TELEGRAM_WEBHOOK_SECRET_TOKEN,
conversation(event) {
return {
target: "subagent",
name: `tenant:${event.thread.channelId ?? event.thread.id}`,
};
},
});メッセンジャーの状態は agents/chat-sdk がバックエンドです。サブエージェントルーティングが解決できるよう、Worker モジュールから ThinkMessengerStateAgent をエクスポートします。本番アプリケーションでは、この facet 専用の状態クラスに、別の Durable Object バインディングやマイグレーションは不要です。テストハーネスでは、明示的なバインディングがまだ必要な場合があります。
Think はストリーム付きの chat() パスで返信します。ルートエージェントはべき等な managed fiber を開始し、会話ターゲットを解決し、target.chat(message, callback) を呼び、プロバイダーの配信ポリシーが可視メッセージの投稿や編集を行います。
復旧スナップショットは、シリアライズ可能なイベントと Chat SDK スレッドデータだけを保存します。ストリーミング開始前に再起動した場合、Think は回答を再実行できます。ストリーミング開始後に再起動した場合は、部分的な回答の重複を避けるため、設定した中断メッセージを投稿します。
配信エラーは、デフォルトで一般的なユーザー向けメッセージを使います。内部の例外詳細を外部チャットに投稿しないためです。安全なカスタムメッセージにしたいときは、delivery.errorResponseText を上書きします。
メッセンジャーのターン中、getMessengerContext() は開始イベントのプロバイダー、スレッド、作者、メッセージ、機能、添付メタデータを返します。チャンネル固有の振る舞いが必要なプロンプト、ツール、フックから使います。
const messenger = this.getMessengerContext();
if (messenger?.thread.isDirectMessage === false) {
// Adjust behavior for group chats.
}const messenger = this.getMessengerContext();
if (messenger?.thread.isDirectMessage === false) {
// Adjust behavior for group chats.
}Think ヘルパーがまだないプロバイダーには chatSdkMessenger() を使います。
chatSdkMessenger({
adapter,
provider: "custom",
userName: "custom_bot",
verifyWebhook(request) {
return request.headers.get("x-custom-signature") === expectedSignature;
},
});chatSdkMessenger({
adapter,
provider: "custom",
userName: "custom_bot",
verifyWebhook(request) {
return request.headers.get("x-custom-signature") === expectedSignature;
},
});すべてのカスタムメッセンジャーは verifyWebhook を提供するか、明示的に verifyWebhook: false を使う必要があります。
examples/think-chat-sdk の例は、Think ネイティブの getMessengers() パスを示します。小さな Vite ダッシュボードで、Agent WebSocket 経由にルート Think 会話を確認できます。
examples/chat-sdk-messenger の例は、管理ダッシュボード、メニュー処理、アプリケーション所有の返信 fiber を備えた、より大きな手動イングレスエージェントを示します。シンプルな Think ネイティブパスには getMessengers() を使います。Chat SDK ランタイムとコントロールプレーン UI を自分で持ちたいときは、この例を使います。基盤の状態アダプターは Chat SDK の状態 を参照してください。