> Discover all available pages from the documentation index: https://mastra.zisheng.pro/ja/llms.txt # Channels **追加バージョン:** `@mastra/core@1.22.0` Channels は Agent をメッセージングプラットフォームへ接続します。`Agent` コンストラクターの `channels` プロパティで設定します。渡すオブジェクトは `ChannelConfig` です。概念とプラットフォームの設定手順は、[Channels の概要](https://mastra.zisheng.pro/ja/docs/capabilities/channels/overview)を参照してください。 ## 使用例 ```typescript import { Agent } from '@mastra/core/agent' import { createSlackAdapter } from '@chat-adapter/slack' import { createDiscordAdapter } from '@chat-adapter/discord' export const supportAgent = new Agent({ id: 'support-agent', name: 'Support Agent', instructions: 'You are a helpful support assistant.', model: 'openai/gpt-5.6-sol', channels: { adapters: { slack: createSlackAdapter(), discord: createDiscordAdapter(), }, }, }) ``` ## パラメータ `channels` プロパティは、次のフィールドを持つ `ChannelConfig` オブジェクトを受け取ります。 **adapters** (`Record`): 名前(例:slack、discord)をキーとするプラットフォーム Adapter。デフォルト設定には Adapter を直接渡し、Adapter ごとのオプションをカスタマイズするには ChannelAdapterConfig オブジェクトを渡します。 **handlers** (`ChannelHandlers`): DM、メンション、購読中の Thread に対するデフォルトのメッセージ Handler を上書きします。 **inlineMedia** (`string[] | ((mimeType: string) => boolean)`): モデルへファイルパートとして送る添付ファイルの種類を制御します。一致しない種類はテキスト要約として説明されます。MIME タイプの glob 配列または述語関数を受け取ります。デフォルトは主要な Vision モデルが対応する形式です。 (Default: `['image/png', 'image/jpeg', 'image/webp', 'application/pdf']`) **inlineLinks** (`InlineLinkEntry[]`): メッセージ本文内の URL をファイルパートへ昇格し、モデルがリンク先の内容を処理できるようにします。各エントリはドメインに一致します。デフォルトでは無効です。 **tools** (`boolean`): getTools() が Channel 固有の Tool(add\_reaction、remove\_reaction)を返すかどうか。Function calling に対応しないモデルでは false にします。Channel Tool が Agent に自動追加されることはないため、tools: { ...channels.getTools() } で明示的に渡してください。 (Default: `true`) **state** (`StateAdapter`): 購読と重複排除に使う State Adapter。デフォルトでは、Mastra インスタンスの Storage を利用する MastraStateAdapter です。Channels を使うには Storage の設定が必要です。 (Default: `MastraStateAdapter (from Mastra storage)`) **userName** (`string`): プラットフォームのメッセージに表示する Bot 名。デフォルトは Agent の name で、名前が未設定の場合は 'Mastra' です。 (Default: `` agent's `name` ``) **threadContext** (`{ maxMessages?: number; addSystemMessage?: boolean }`): Agent が現在の Thread のコンテキストを取得する方法。maxMessages は、最初のメンション時に取得するプラットフォーム上の直近メッセージ数を制御します(無効にするには 0。DM 以外の Thread にのみ適用)。addSystemMessage: false を指定すると、リクエスト元の Channel/プラットフォームを Agent に伝える組み込みシステムメッセージを省略します。 (Default: `{ maxMessages: 10, addSystemMessage: true }`) **chatOptions** (`Omit`): Chat SDK へ直接渡す追加オプション。dedupeTtlMs、fallbackStreamingPlaceholderText、lockScope、messageHistory などの高度な設定に使用します。 **resolveResourceId** (`(ctx: ResolveResourceIdContext) => string | Promise`): メッセージ送信者とは別に、Channel Thread のリソースレベル Memory を所有する resourceId を決定します。新しい Thread の作成時にのみ実行されます。再利用される Thread は保存済みの所有者を維持し、この Hook を呼び出しません。組み込みの動作を維持するには ctx.defaultResourceId(${platform}:${message.author.userId})を返します。 **resolveThreadId** (`(ctx: ResolveThreadIdContext) => string | Promise`): Channel Thread に使う Mastra 内部の Thread ID を決定します。解決済みの所有者をコンテキストに含め、resolveResourceId の後に実行されます。新しい Thread の作成時にのみ実行され、再利用される Thread は保存済み ID を維持して Hook を呼び出しません。返す ID は Memory Store 全体で一意である必要があります。衝突時は生成された ID が代わりに使われます。組み込みの動作を維持するには ctx.defaultThreadId(ランダムな UUID)を返します。 **waitUntil** (`(promise: Promise) => void`): プラットフォームの waitUntil 関数。Webhook が 200 を返した後もバックグラウンドの Agent Run を継続させるため、Vercel では必須です。Vercel では @vercel/functions の waitUntil を渡します。Cloudflare Workers と Netlify Functions はリクエストコンテキストから自動検出されます。AWS Lambda はイベントループが自然に空になるまで待つため、waitUntil は不要です。 **resolveWaitUntil** (`(c: Context) => ((promise: Promise) => void) | undefined`): waitUntil が Hono のリクエストコンテキストにあり、組み込み Helper では対応できない Runtime 用の Resolver。解決順序は、単独の waitUntil → resolveWaitUntil(c) → デフォルト(Cloudflare Workers、Netlify)です。 ## Adapter ごとのオプション Adapter ごとのオプションを設定するには、Adapter を `ChannelAdapterConfig` オブジェクトでラップします。 ```typescript import { Agent } from '@mastra/core/agent' import { createDiscordAdapter } from '@chat-adapter/discord' import { createSlackAdapter } from '@chat-adapter/slack' const agent = new Agent({ id: 'example', name: 'Example', instructions: '...', model: 'openai/gpt-5.6-sol', channels: { adapters: { discord: { adapter: createDiscordAdapter(), toolDisplay: 'text', cors: { origin: ['https://customer-saas.example'], credentials: true, }, gateway: false, }, slack: createSlackAdapter(), // Plain adapter uses defaults }, }, }) ``` **adapter** (`Adapter`): このプラットフォーム用の Chat SDK Adapter インスタンス。 **gateway** (`boolean`): DM、@メンション、リアクションを受信する常駐 Gateway WebSocket Listener を起動します。Webhook ベースの対話だけが必要なサーバーレス環境では false にします。 (Default: `true`) **cards** (`boolean`): \*\*非推奨\*\* — 代わりに toolDisplay を使用してください。toolDisplay が未設定の場合、cards: true は toolDisplay: "cards"、cards: false は toolDisplay: "text" に対応します。IDE ではこのフィールドに取り消し線が表示されますが、Runtime の動作は維持されます。 **cors** (`CorsOptions`): この Adapter の Webhook Route に対する CORS 設定。オリジン間 Credential が必要なブラウザベースの Channel Adapter で使用します。 **formatError** (`(error: Error) => PostableMessage`): チャットでのエラー表示方法を上書きします。生のエラーを公開せず、ユーザー向けのメッセージを返します。 (Default: `"❌ Error: "`) **formatToolCall** (`(args: { toolName: string; args: unknown; result: unknown; isError: boolean }) => PostableMessage | null`): \*\*非推奨\*\* — 代わりに関数形式の toolDisplay を使用してください。設定すると、result/error イベントでのみ発火する ToolDisplayFn として動作し、running と approval イベントは表示されません。型レベルでは toolDisplay と相互排他的です。 **streaming** (`boolean | { updateIntervalMs?: number }`): Agent のテキスト差分をバッファリングして Step ごとに一度投稿する代わりに、生成中に Channel へストリーミングします。基盤となる Adapter が投稿と編集によるストリーミングに対応している必要があります。Slack のデフォルトは true、その他の Adapter は false です。 (Default: `false (true for Slack)`) **textFormat** (`'markdown' | 'plain'`): Agent の最終返信テキストに使う方言。デフォルトの 'markdown' は返信を Markdown として投稿します。Markdown をネイティブ表示できる Adapter(Slack)は直接表示し、それ以外は各プラットフォーム形式へ変換します。'plain' は返信をリテラルなプレーンテキストとして投稿し、Slack mrkdwn などのプラットフォーム方言を出力するよう指示された Agent で、Markdown 対応前の動作を復元します。最終返信テキストにのみ適用され、Tool Card、エラーメッセージ、Tripwire 通知には影響しません。ネイティブストリーミングでは、この設定にかかわらず常に Markdown を使います。 (Default: `'markdown'`) **toolDisplay** (`'cards' | 'text' | 'timeline' | 'grouped' | 'hidden' | ToolDisplayFn`): Channel での Tool 呼び出しの表示方法。"cards" は Tool ごとの実行中/結果 Card をリッチな Block Kit として投稿します。"text" は同じライフサイクルをプレーンテキストで投稿します(Block Kit なし)。"timeline" と "grouped" は Tool の状態をインライン task\_update チャンクとしてストリーミングします(streaming: true が必要。現在は Slack のみで、他の Adapter はプレースホルダーを表示する場合があります)。"hidden" は Tool を表示せずに実行します。Tool イベントを独自表示するには関数を渡します。個別の投稿/編集には { kind: "post", message }、ストリーミング Widget への送信には { kind: "stream", chunk } を返し、そのイベントを表示しない場合は undefined を返します。チャンクをアクティブなストリーミングセッションにのみ適用する場合は、Stream 結果に openIfEmpty: false を追加します。承認/拒否プロンプトは、モードにかかわらず常に別の Card として表示されます。 (Default: `'cards' ('grouped' for Slack)`) **typingStatus** (`boolean | ((chunk: AgentChunkType, ctx: TypingStatusContext) => string | false | null | undefined | void)`): プラットフォームの入力中インジケーターを制御します。true は組み込みのデフォルトを使います(テキストでは is typing…、Tool 呼び出しでは is calling {tool}…、Tool 呼び出し承認では is waiting for approval…)。false は入力中表示を完全に抑制します。ライブストリーミング Widget(例:Slack の toolDisplay: "grouped")がすでに進捗を示す場合に便利です。チャンクごとにカスタムステータス文を設定するには関数を渡します。ステータスを設定するには文字列、変更しない場合は false/null/undefined を返します。処理しないチャンクをデフォルトへフォールバックするには、defaultTypingStatus(@mastra/core/channels から export)と組み合わせます。 (Default: `true`) ## Tool 表示モード `toolDisplay` は、チャットでの Tool 呼び出しの表示方法を制御します。デフォルトの `'cards'` は Tool ごとに「Running…」Card を投稿し、結果で更新します。これは以前のバージョンと同じ動作です。`'text'` は同じライフサイクルを使いますが、リッチな Block Kit は使いません。Card を適切に表示できないプラットフォームで便利です。 `'timeline'` と `'grouped'` は、Agent のテキストとともに Tool の状態をインライン `task_update` チャンクとしてストリーミングします。これらのモードには `streaming: true` が必要で、チャンクの表示は Chat Adapter に依存します。Slack は両方をネイティブにサポートします。他の Adapter は対応するまでプレースホルダーを表示する場合があります。`streaming` が無効な場合、Channel は警告を一度記録して `'cards'` へフォールバックします。 `'hidden'` は Tool を表示せずに実行します。処理中であることは入力中ステータスだけで示されます。 表示を完全にカスタマイズするには、`toolDisplay` に関数を渡します。関数は `ToolDisplayEvent`(`running`/`result`/`error`/`approval`)と `ToolDisplayContext`(`{ mode, platform }`)を受け取ります。個別の投稿/編集には `{ kind: 'post', message }` for a discrete post/edit, `{ kind: 'stream', chunk }` を返し、 アクティブなストリーミング Widget へ送信します。そのイベントを表示しない場合は `undefined` を返します。 デフォルトでは、アクティブなセッションがない場合、Stream 結果がストリーミングセッションを開始します。チャンクを既存セッションにのみ適用する場合は `openIfEmpty: false` を設定します。アクティブなセッションがなければ、Mastra はチャンクをスキップします。静的 Channel はこのオプションを無視し、既存のプレーンテキストへのフォールバック動作を維持します。 ```typescript toolDisplay: event => { if (event.kind !== 'running') return undefined return { kind: 'stream', chunk: { type: 'task_update', id: event.toolCallId, title: event.displayName, status: 'in_progress', }, openIfEmpty: false, } } ``` 承認/拒否プロンプト(`requireApproval`)は、モードにかかわらず常に別の Card として表示されます。インライン Task エントリには対話型ボタンを含められないためです。 ```typescript import { Agent } from '@mastra/core/agent' import { createSlackAdapter } from '@chat-adapter/slack' const agent = new Agent({ id: 'streaming-agent', name: 'Streaming Agent', instructions: '...', model: 'openai/gpt-5.6-sol', channels: { adapters: { slack: { adapter: createSlackAdapter(), streaming: true, // already the Slack default toolDisplay: 'timeline', }, }, }, }) ``` ## カスタム入力中ステータス ステータス文をカスタマイズするには、`typingStatus` に関数を渡します。関数は Stream チャンクごとに一度呼ばれます。ステータスを設定するには文字列を返し、現在のステータスを変更しない場合は `false`/`null`/`undefined` を返します。戻り値は重複排除されるため、プラットフォーム側で呼び出しが発生するのはステータスが変わったときだけです。 `defaultTypingStatus` は `@mastra/core/channels` から export されており、処理しないチャンクを組み込みのデフォルトへフォールバックできます。 ```typescript import { Agent } from '@mastra/core/agent' import { defaultTypingStatus } from '@mastra/core/channels' import { createDiscordAdapter } from '@chat-adapter/discord' const agent = new Agent({ id: 'custom-typing-agent', name: 'Custom Typing Agent', instructions: '...', model: 'openai/gpt-5.6-sol', channels: { adapters: { discord: { adapter: createDiscordAdapter(), typingStatus: (chunk, ctx) => { if (chunk.type === 'tool-call' && chunk.payload.toolName === 'searchDocs') { return 'is searching docs…' } return defaultTypingStatus(chunk, ctx) }, }, }, }, }) ``` ## Handler 組み込み Event Handler を上書きします。各 Handler には次を指定できます。 - **省略**:デフォルトの Mastra Handler を使います(メッセージを Agent へ送り、レスポンスを投稿) - **`false`**:Handler を完全に無効化します - **関数** `(thread, message, defaultHandler) => Promise`:デフォルト処理をラップまたは置換します ```typescript import { Agent } from '@mastra/core/agent' import { createSlackAdapter } from '@chat-adapter/slack' const agent = new Agent({ id: 'custom-handler-agent', name: 'Custom Handler Agent', instructions: '...', model: 'openai/gpt-5.6-sol', channels: { adapters: { slack: createSlackAdapter(), }, handlers: { onMention: async (thread, message, defaultHandler) => { console.log('Received mention:', message.text) await defaultHandler(thread, message) }, onDirectMessage: false, }, }, }) ``` **onDirectMessage** (`ChannelHandler | false`): Bot がダイレクトメッセージを受信したときに呼び出されます。 **onMention** (`ChannelHandler | false`): Channel または Thread で Bot が @メンションされたときに呼び出されます。 **onSubscribedMessage** (`ChannelHandler | false`): Agent が購読している Thread のメッセージに対して呼び出されます。 `ChannelHandler` 関数のシグネチャ: ```typescript type ChannelHandler = ( thread: Thread, message: Message, defaultHandler: (thread: Thread, message: Message) => Promise, ctx: ChannelHandlerContext, ) => Promise type ChannelHandlerContext = { mastra?: Mastra requestContext: RequestContext } ``` `ctx.mastra` は解決済みの `mastra` インスタンスです。そのため Handler は、外部 Accessor を渡されなくても Storage や他の登録済み Primitive へアクセスできます。 ```typescript onDirectMessage: async (thread, message, defaultHandler, ctx) => { const store = await ctx.mastra?.getStorage()?.getStore('memory') await defaultHandler(thread, message) } ``` `ctx.requestContext` は、このメッセージが開始する Run の [`RequestContext`](https://mastra.zisheng.pro/ja/docs/server/request-context) で、メッセージごとに新しく作成されます。`defaultHandler` を呼び出す前に値を書き込むと、後から Mastra が追加する Channel エントリとともに Run へ渡されます。 ```typescript onDirectMessage: async (thread, message, defaultHandler, ctx) => { ctx.requestContext.set('locale', 'en-GB') await defaultHandler(thread, message) } ``` この方法により、プラットフォームの送信者をどのユーザーへ対応付けるかなど、Run がリクエストコンテキストから読む値をメッセージごとに決定できます。 ## Resource ID の解決 デフォルトでは、Channel Thread の Memory `resourceId` は `${platform}:${message.author.userId}` です。送信者がプラットフォーム単位で Memory を所有します。シングルサインオン(SSO)のように共通 ID を使うアプリでは、これにより Memory が分割されます。同じユーザーでも、Feishu の DM では `feishu:user_123`、Web では `user_123` になります。 送信者とは別に Memory の所有者を決めるには、`resolveResourceId` を渡します。新しい Thread の作成時にのみ実行されます。再利用される Thread は保存済みの `resourceId` を維持して Hook を呼び出さないため、既存の会話は Resolver の可用性に依存しません。組み込みの動作へフォールバックするには `ctx.defaultResourceId` を返します。 ```typescript import { Agent } from '@mastra/core/agent' import { createSlackAdapter } from '@chat-adapter/slack' const agent = new Agent({ id: 'sso-agent', name: 'SSO Agent', instructions: '...', model: 'openai/gpt-5.6-sol', channels: { adapters: { slack: createSlackAdapter(), }, resolveResourceId: async ({ thread, message }) => { // DM: share resource-level memory with the web app by using the bare SSO id if (thread.isDM) { return await resolveSsoUserId(message) } // Group chat: the conversation owns the memory; the sender stays the actor return thread.channelId }, }, }) ``` 関数へ渡される `ResolveResourceIdContext`: **platform** (`string`): プラットフォーム名(例:slack、discord)。 **thread** (`Thread`): メッセージを受信した Channel Thread。DM とグループ/Channel Thread の判別には thread.isDM を使います。 **message** (`Message`): 受信メッセージ。message.author.userId は Actor/送信者であり、必ずしも Memory の所有者ではありません。 **defaultResourceId** (`string`): 組み込みのデフォルト(${platform}:${message.author.userId})。現在の動作を維持するには、この値を返します。 ## Thread ID の解決 デフォルトでは、新しい Channel Thread の Mastra 内部 Thread ID にランダムな UUID が使われます。ID を独自に決めるには `resolveThreadId` を渡します。たとえば、アプリ自身が作成する Thread の命名方法に合わせ、所属するセッションと同じ ID を Thread に設定できます。 この Hook は `resolveResourceId` の後に実行されるため、解決済みの所有者をコンテキストから利用できます。`resolveResourceId` と同様、新しい Thread の作成時にのみ実行されます。再利用される Thread は保存済み ID を維持し、Hook を呼び出しません。返す ID は Memory Store 全体で一意である必要があります。既存の Thread が同じ ID を使っている場合、Mastra は警告を記録し、既存 Thread を上書きしないよう生成した ID を代わりに使います。組み込みの動作を維持するには `ctx.defaultThreadId` を返します。 ```typescript import { Agent } from '@mastra/core/agent' import { createSlackAdapter } from '@chat-adapter/slack' const agent = new Agent({ id: 'session-agent', name: 'Session Agent', instructions: '...', model: 'openai/gpt-5.6-sol', channels: { adapters: { slack: createSlackAdapter(), }, // Owner: a session id resolved from the sender's linked account resolveResourceId: async ctx => resolveSessionId(ctx), // Thread id: align with the session id so app URLs that address // threads by session id resolve channel-created threads too resolveThreadId: ({ resourceId, defaultThreadId }) => { return isSessionId(resourceId) ? resourceId : defaultThreadId }, }, }) ``` 関数へ渡される `ResolveThreadIdContext`: **platform** (`string`): プラットフォーム名(例:slack、discord)。 **thread** (`Thread`): メッセージを受信した Channel Thread。DM とグループ/Channel Thread の判別には thread.isDM を使います。 **message** (`Message`): 受信メッセージ。 **resourceId** (`string`): 新しい Thread が属する、解決済みの Memory resourceId(resolveResourceId の実行後)。 **defaultThreadId** (`string`): 組み込みのデフォルト(ランダムな UUID)。現在の動作を維持するには、この値を返します。 ## インラインメディア モデルへファイルパートとして送る添付ファイルの種類(画像、動画、PDF など)を制御します。一致しない種類はテキスト要約として説明されるため、未対応の種類を拒否するモデルを停止させずに、Agent へファイルの存在を伝えられます。 デフォルト(`['image/png', 'image/jpeg', 'image/webp', 'application/pdf']`)は、主要な Vision モデルが対応する形式です。`inlineMedia` を上書きしてリストを拡張する(例:`['image/*', 'audio/*']`)か、述語関数で完全に置き換えます。 対応する glob パターン: | パターン | 一致対象 | | ----------------- | -------------------------------------- | | `image/*` | すべての画像タイプ(`image/png`、`image/jpeg` など) | | `video/*` | すべての動画タイプ | | `*` または `*/*` | すべてのタイプ | | `application/pdf` | 完全一致するタイプ | 非公開 CDN を使うプラットフォーム(例:Slack)では、Chat SDK から認証済み Credential を使って添付ファイルを取得します。公開 CDN を使うプラットフォーム(例:Discord)では、URL をモデルへ直接渡します。 ## インラインリンク メッセージ本文内の URL をファイルパートへ昇格し、モデルが生の URL テキストではなくリンク先の内容を処理できるようにします。各エントリには文字列(ドメインパターン)、または MIME タイプを強制するオブジェクトを指定できます。 **文字列エントリ**はドメインに一致し、HEAD リクエストで Content-Type を検出します。解決したタイプを `inlineMedia` と照合し、一致したタイプだけがファイルパートになります。 **オブジェクトエントリ**はドメインに一致し、特定の MIME タイプを強制します。HEAD リクエストと `inlineMedia` の検査は省略されます。HEAD リクエストでは `text/html` が返るものの、モデルが URL を動画コンテンツとして扱う YouTube のようなサイトで便利です。 ```typescript type InlineLinkEntry = | string // Domain pattern (HEAD determines mime type) | { match: string; mimeType: string } // Domain + forced mime type (skips HEAD) ``` ## 関連項目 - [Channels の概要](https://mastra.zisheng.pro/ja/docs/capabilities/channels/overview):概念、クイックスタート、プラットフォーム設定 - [Agent クラス](https://mastra.zisheng.pro/ja/reference/agents/agent):コンストラクターのパラメータとメソッド - [Chat SDK Adapter](https://chat-sdk.dev/adapters):Adapter の設定とプラットフォーム設定