メインコンテンツへ移動

Channels の概要

追加バージョン: @mastra/core@1.22.0

Channels は Agent を Slack、Microsoft Teams、Discord、Telegram、WhatsApp、GitHub、Linear などのメッセージングおよびコラボレーションプラットフォームに接続します。ユーザーがプラットフォーム上でメッセージやコメントを送信すると、Agent はそれを受信し、通常の Agent パイプラインで処理して、応答を会話へストリーミングします。Mastra はこの channel レイヤーに Chat SDK を使用します。

使用するプラットフォームのページから始めてください。

その他には、追加のプラットフォームが掲載されています。Mastra channels は、ここに記載されていない互換性のある Chat SDK アダプターでも動作し、どのアダプターでも同じ Mastra の設定パターンを使用できます。

Channels を使用する場面
Channels を使用する場面への直接リンク

Agent に次の機能が必要な場合は Channels を使用します。

  • ユーザーが普段会話したり作業したりしている場所で対応する。
  • Slack、Microsoft Teams、Discord、Telegram、WhatsApp などのチャットプラットフォームで応答する。
  • 複数のユーザーが共有 channel やスレッド内で同じ Agent とやり取りする、マルチユーザー Agent をサポートする。
  • GitHub の Issue、プルリクエストのスレッド、Linear のコメントなどのコラボレーションワークフローと連携する。

Agent の設定
Agent の設定への直接リンク

Channels は Chat SDK アダプターを使用し、Mastra 側では共通のパターンに従います。channel アダプターを作成し、Agent に追加します。

src/mastra/agents/your-agent.ts
import { Agent } from '@mastra/core/agent'
import { createSlackAdapter } from '@chat-adapter/slack'

export const yourAgent = new Agent({
id: 'your-agent',
name: 'Your Agent',
instructions: 'You are a helpful assistant.',
model: 'openai/gpt-5.6-sol',
channels: {
adapters: {
slack: createSlackAdapter(),
},
},
})
注記

Channel アダプターでは、認証情報とリクエスト検証のために、Bot トークン、署名シークレット、アプリ ID、Webhook 検証トークンなど、Provider 固有の環境変数が必要です。正確な変数名は、使用するプラットフォームのガイドまたは Chat SDK アダプターカタログを確認してください。

Channels には storage の設定を推奨します。storage を使用すると、Mastra は channel の状態、スレッドの購読、Tool の承認、Memory を再起動後も保持できます。

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { LibSQLStore } from '@mastra/libsql'
import { yourAgent } from './agents/your-agent'

export const mastra = new Mastra({
agents: { yourAgent },
storage: new LibSQLStore({
id: 'mastra-storage',
url: process.env.DATABASE_URL,
}),
})

Webhook ルート
Webhook ルートへの直接リンク

プラットフォームは Webhook を通じて channel のアクティビティを Mastra に送信します。Webhook とは、新しいメッセージやメンション、ユーザーによる対話型 Tool 承認カードの「Approve」の選択など、何らかのイベントが発生したときにプラットフォームから呼び出される HTTP エンドポイントです。これにより、Agent は新しいメッセージを受信して処理を開始し、同じ channel に応答します。

Mastra は設定済みのアダプターごとに Webhook ルートを登録し、リクエストを処理します。

/api/agents/<AGENT_ID>/channels/<PLATFORM>/webhook

たとえば、ID が your-agent の Agent に設定された Slack アダプターは、次のルートを使用します。

/api/agents/your-agent/channels/slack/webhook

プラットフォームの Webhook、イベント、インタラクション URL にこのパスを指定します。使用するプラットフォームのガイドまたは Chat SDK ドキュメントに従ってください。

ローカル開発では、プラットフォームの Webhook がローカルサーバーにアクセスできるよう、公開 URL が必要です。cloudflaredngrok などのトンネルを使用して、デフォルトでは localhost:4111 で稼働するサーバーを公開します。

npx cloudflared tunnel --url http://localhost:4111

生成された公開 URL を Webhook パスのベース URL として使用します。例: https://abc123.trycloudflare.com/api/agents/your-agent/channels/slack/webhook

注記

トンネル URL はローカル開発用です。Mastra サーバーをデプロイしたら、プラットフォームの Webhook、イベント、インタラクション URL を本番環境の URL に更新してください。

スレッドコンテキスト
スレッドコンテキストへの直接リンク

ユーザーが channel のスレッドで会話の途中に Agent をメンションした場合、Agent にはそれまでのコンテキストがない可能性があります。デフォルトでは、最初のメンション時に Mastra がプラットフォームから直近 10 件のメッセージを取得します。

  1. スレッドで最初にメンションされると、Agent はプラットフォームから直近のメッセージを取得します。
  2. これらのメッセージは、会話のコンテキストとしてユーザーのメッセージの前に追加されます。
  3. 応答後、Agent はスレッドを購読し、Mastra Memory を通じて完全な履歴を保持します。
  4. そのスレッドの後続メッセージでは、プラットフォームから再取得しません。

この動作を無効にするには、threadContext: { maxMessages: 0 } を設定します。この設定はダイレクトメッセージ以外のスレッドにのみ適用されます。

Mastra は、リクエストがどの channel とプラットフォームから届いたか、たとえばダイレクトメッセージと公開 channel のどちらから届いたかを Agent に伝える短い system message も追加します。追加しない場合は、threadContext: { addSystemMessage: false } を設定します。

Tool の承認
Tool の承認への直接リンク

requireApproval: true が設定された Tool は、「Approve」と「Deny」ボタンを備えた対話型カードとして表示されます。

src/mastra/tools/delete-file.ts
import { promises as fs } from 'node:fs'
import { createTool } from '@mastra/core/tools'
import { z } from 'zod'

export const deleteFile = createTool({
id: 'delete-file',
description: 'Delete a file from the system',
inputSchema: z.object({
path: z.string().describe('Path to the file to delete'),
}),
requireApproval: true,
execute: async ({ path }) => {
await fs.unlink(path)
return { deleted: path }
},
})

Agent がこの Tool を呼び出すと、Tool 名、引数、「Approve」と「Deny」のアクションを含むカードがユーザーに表示されます。Tool は承認後にのみ実行されます。

対話型カードではなくプレーンテキストで Tool 呼び出しを表示するには、アダプターに toolDisplay: 'text' を設定します。'hidden' モードでは、同じスレッドに後続のユーザーメッセージが届いたとき、autoResumeSuspendedTools が一時停止中の Tool を再開できます。これには Memory が必要です。hidden モードで非表示になるのは承認ボタンだけです。

応答のフォーマット
応答のフォーマットへの直接リンク

Agent の応答は、デフォルトで markdown として投稿されます。Slack など markdown をネイティブにレンダリングするプラットフォームでは、太字、リンク、テーブルがそのまま表示されます。ほかのプラットフォームでは、markdown が各プラットフォームの形式に変換されます。Agent は標準の markdown を記述するだけで、Studio と同じように、どのプラットフォームでも正しく表示されます。

応答をリテラルなプレーンテキストとして投稿するには、アダプターに textFormat: 'plain' を設定します。

src/mastra/agents/your-agent.ts
channels: {
adapters: {
slack: {
adapter: createSlackAdapter(),
textFormat: 'plain',
},
},
},

Agent に標準 markdown ではなく Slack mrkdwn などプラットフォーム固有の記法を出力させる場合は、この回避策を使用してください。markdown がリテラル表示される問題を回避するために、そのようなプロンプト指示を追加していた場合は、代わりに削除してください。現在、標準 markdown はデフォルトでネイティブにレンダリングされます。textFormat が影響するのは最終的な応答テキストだけです。Tool カード、エラーメッセージ、ネイティブにストリーミングされるテキストには影響しません。

複数ユーザーの識別
複数ユーザーの識別への直接リンク

グループ会話では、Agent が発言者を区別できるよう、Mastra が各メッセージの先頭に送信者の名前とプラットフォーム ID を付加します。

[Alice (@U123ABC)]: Can you help me with this?
[Bob (@U456DEF)]: I have a question too.

マルチモーダルコンテンツ
マルチモーダルコンテンツへの直接リンク

Gemini などのモデルは、画像、動画、音声をネイティブに処理できます。inlineMediainlineLinks を組み合わせると、ユーザーは複数のプラットフォームから Agent とリッチコンテンツを共有できます。

src/mastra/agents/vision-agent.ts
import { Agent } from '@mastra/core/agent'
import { createDiscordAdapter } from '@chat-adapter/discord'

export const visionAgent = new Agent({
id: 'vision-agent',
name: 'Vision Agent',
instructions: 'You can see images, watch videos, and listen to audio.',
model: 'google/gemini-2.5-flash',
channels: {
adapters: {
discord: createDiscordAdapter(),
},
inlineMedia: ['image/*', 'video/*', 'audio/*'],
inlineLinks: [
{ match: 'youtube.com', mimeType: 'video/*' },
{ match: 'youtu.be', mimeType: 'video/*' },
'imgur.com',
],
},
})

この設定により、次の処理が可能になります。

  • ユーザーがスクリーンショットをアップロードすると、Agent がその内容を説明する。
  • ユーザーが .mp4 クリップをアップロードすると、Agent が動画を要約する。
  • ユーザーが YouTube のリンクを貼り付けると、Agent が動画を視聴して内容について応答する。
  • ユーザーが imgur のリンクを貼り付けると、Agent が画像を直接認識する。

デフォルトでは、画像だけがインライン送信されます(inlineMedia: ['image/*'])。サポートされていない形式はテキストの要約として記述されるため、該当形式を拒否するモデルでもエラーを起こさず、Agent がファイルの存在を認識できます。すべての inlineMedia パターンについては Channels リファレンスを、ドメインマッチング、HEAD 検出、MIME タイプの強制指定については inlineLinks リファレンスを参照してください。

サーバーレスへのデプロイ
サーバーレスへのデプロイへの直接リンク

Vercel などのサーバーレスプラットフォームでは、リクエストごとに独立した短命なインスタンスが実行されます。この環境で Channels を確実に動作させるには、Agent が応答する間 Function を稼働させる仕組みと、インスタンス間を連携させる共有 pub/sub の 2 つが必要です。

waitUntil で Function を稼働させる
keep-the-function-alive-with-waituntilへの直接リンク

Channel の Webhook はすぐに 200 レスポンスを返し、その後 Agent がバックグラウンドで実行されて応答を投稿します。ほとんどのサーバーレスプラットフォームでは、応答直後に Function が凍結されるため、Agent が回答する前に実行が停止します。実行が完了するまでプラットフォームがインスタンスを稼働させるよう、waitUntil 関数を渡します。

Vercel では、@vercel/functionswaitUntil を渡します。

src/mastra/agents/your-agent.ts
import { Agent } from '@mastra/core/agent'
import { createSlackAdapter } from '@chat-adapter/slack'
import { waitUntil } from '@vercel/functions'

export const yourAgent = new Agent({
id: 'your-agent',
name: 'Your Agent',
instructions: 'You are a helpful assistant.',
model: 'openai/gpt-5.6-sol',
channels: {
adapters: {
slack: createSlackAdapter(),
},
waitUntil,
},
})

Vercel と AWS Lambda は応答送信直後に Function を凍結するため、waitUntil が必要です。Cloudflare Workers と Netlify Functions はリクエストコンテキストから自動検出されるため、設定は不要です。waitUntil がリクエストコンテキストに存在しても自動検出されないランタイムでは、resolveWaitUntil を使用します。詳しくは Channels リファレンスを参照してください。

共有 pub/sub でインスタンスを連携させる
共有 pub/sub でインスタンスを連携させるへの直接リンク

Channels は Agent の signal パイプラインを通じてメッセージをルーティングし、各実行がスレッドのリースを取得することで、一度に 1 つの実行だけが会話を処理します。

デフォルトのインメモリ pub/sub はインスタンスの境界を越えられないため、サーバーレス環境では、後続メッセージが Agent を実行しているインスタンスとは別のインスタンスにルーティングされる場合があります。

共有 pub/sub がない場合、そのインスタンスは実行中の処理にアクセスできず、独自の処理を開始します。その結果、元の処理は変更されないまま、スレッドが二重に処理されます。

インスタンス間でリースと signal を連携させるには、Mastra インスタンスに Redis Streams を使用した共有 pub/sub を設定します。

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { RedisStreamsPubSub } from '@mastra/redis-streams'
import { yourAgent } from './agents/your-agent'

export const mastra = new Mastra({
agents: { yourAgent },
pubsub: new RedisStreamsPubSub({
url: process.env.REDIS_URL,
keyPrefix: 'mastra:my-app',
}),
})

Vercel のマネージド Redis 連携と Upstash Redis は、どちらも適しています。分散 pub/sub が必要になる状況について詳しくは、PubSub ガイドおよび RedisStreamsPubSub リファレンスを参照してください。