Channels 渠道
添加于: @mastra/core@1.22.0
Channels 将 agents 连接到 Slack、Microsoft Teams、Discord、Telegram、WhatsApp、GitHub 和 Linear 等消息与协作平台。当用户在平台上发送消息或评论时,agent 会收到该消息并通过正常的 agent 管道处理,同时将响应流式传回对话。Mastra 使用 Chat SDK 实现这一渠道层。
从你所用平台的页面开始:
其他适配器列出了更多平台。Mastra channels 可与此处所列平台之外的兼容 Chat SDK 适配器配合使用,并且相同的 Mastra 配置模式适用于所有适配器。
何时使用 channels何时使用 channels的直接链接
当 agent 需要执行以下操作时,使用 channels:
- 在用户已经聊天或工作的地方与其互动。
- 在 Slack、Microsoft Teams、Discord、Telegram 和 WhatsApp 等聊天平台中响应。
- 支持多人 agents,让多人在共享渠道或 thread 中与同一 agent 交互。
- 与 GitHub issues、pull request threads 和 Linear 评论等协作工作流集成。
使用 Mastra Connect 更快配置 channels使用 Mastra Connect 更快配置 channels的直接链接
如果你不想为每个渠道配置 bot 或应用并自行维护凭据,可以使用 Mastra Connect。它为你管理凭据,简化渠道的设置和维护。
配置 agent配置 agent的直接链接
Channels 使用 Chat SDK 适配器,并遵循相同的 Mastra 侧模式:创建渠道适配器并将其添加到 agent。
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(),
},
},
})
渠道适配器需要特定于提供商的凭据和请求验证环境变量,例如 bot tokens、signing secrets、app IDs 和 webhook verification tokens。请查看你所使用平台的指南或 Chat SDK 适配器目录以获取确切的变量名。
我们建议为 channels 配置存储。存储可在重启后保留渠道和记忆状态,包括 thread 订阅和工具审批:
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 路由的直接链接
平台通过 webhooks 将渠道活动发送给 Mastra。Webhook 是一个 HTTP 端点,当发生某些事情(例如新消息、提及,或用户在交互式工具审批卡片上选择 "Approve")时,平台会调用它。Webhook 将消息投递给你的 agent 进行处理,agent 在同一渠道中响应。
Mastra 会为每个已配置的适配器注册一个 webhook 路由,并为你处理请求:
/api/agents/<AGENT_ID>/channels/<PLATFORM>/webhook
例如,一个 ID 为 your-agent 的 agent 上的 Slack 适配器使用:
/api/agents/your-agent/channels/slack/webhook
将平台的 webhook、event 或 interactions URL 指向此路径。请遵循你所使用平台的指南或 Chat SDK 文档。Webhook 会在 agent 完成响应之前确认请求。关于验证或处理器失败时会发生什么,请参阅错误处理与投递。
在本地开发期间,平台 webhooks 需要一个公共 URL 才能访问你的本地服务器。使用 cloudflared 或 ngrok 等隧道暴露你的服务器,默认是 localhost:4111:
- npm
- pnpm
- Yarn
- Bun
npx cloudflared tunnel --url http://localhost:4111
pnpm dlx cloudflared tunnel --url http://localhost:4111
yarn dlx cloudflared tunnel --url http://localhost:4111
bun x cloudflared tunnel --url http://localhost:4111
将生成的公共 URL 用作 webhook 路径的基础 URL,例如 https://abc123.trycloudflare.com/api/agents/your-agent/channels/slack/webhook。
隧道 URL 仅用于本地开发。部署 Mastra 服务器后,请将平台的 webhook、event 或 interactions URL 更新为生产 URL。
Thread 上下文Thread 上下文的直接链接
当用户在渠道 thread 中于对话中途提及 agent 时,agent 可能没有先前的上下文。在首次提及时,Mastra 会从平台获取较早的消息,并在提及运行之前将它们保存到 agent 的 memory thread 中。
- 在 thread 中的首次提及时,agent 会获取该 thread 的第一条消息以及提及之前最近的消息。
maxMessages(默认10)设置窗口:第一条消息加上最多maxMessages - 1条最近消息。当两条消息之间还有消息时,会在它们的位置保存一个[… N earlier Slack messages omitted]标记(平台名称与渠道匹配)。 - 每条获取的消息都会作为独立的用户消息保存到 memory,标注其作者和平台消息 id,并携带其附件,带有
source: 'thread-history'属性。随后,提及本身会作为普通消息分发。 - 响应后,agent 会订阅该 thread,并通过 Mastra memory 获得完整历史。
- 该 thread 中的后续消息不会再次从平台获取。
设置 threadContext: { maxMessages: 0 } 可禁用此行为。这仅适用于非直接消息 threads。
没有 memory 的 agents 无法保存这些行,因此它们会在提及中作为上下文文本接收相同的历史。写入 memory 失败时也适用相同的回退方式。
Memory 的 lastMessages 选项限制到达提示的消息数量。其默认值 10 会在 maxMessages 为 10 时裁剪第一条消息和省略标记,因此请将 lastMessages 至少设置为 maxMessages + 1。
Mastra 还会添加一条简短的系统消息,告知 agent 请求来自哪个渠道和平台,例如消息来自直接消息还是公共渠道。设置 threadContext: { addSystemMessage: false } 可跳过它。
工具审批工具审批的直接链接
带有 requireApproval: true 的工具会渲染为带 Approve 和 Deny 按钮的交互式卡片:
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 调用此工具时,用户会看到一张卡片,显示工具名称、参数以及 Approve 和 Deny 操作。工具仅在审批后执行。
在适配器上设置 toolDisplay: 'text' 可将工具调用渲染为纯文本而不是交互式卡片。在 'hidden' 模式下,当同一 thread 上稍后收到用户消息时,autoResumeSuspendedTools 可以恢复携带数据的 suspend() 流程。这需要 memory。隐藏模式只会隐藏审批按钮。它不会将消息变成同意。需要审批的工具会保持挂起,直到通过 UI 或 API 操作提交明确的批准或拒绝。
自定义操作处理自定义操作处理的直接链接
使用 handlers.onAction 处理你自己发布的卡片中的按钮点击和选择变更。处理器会接收 Chat SDK action 事件、默认处理器,以及其他渠道处理器收到的相同 ctx。你在委派前于 ctx.requestContext 上设置的值会传递到恢复的工具调用。默认处理器处理内置的 Approve 和 Deny 按钮,并忽略其他所有 action ID,因此对于你不处理的事件请调用它,以保持工具审批正常工作:
channels: {
adapters: {
slack: createSlackAdapter(),
},
handlers: {
onAction: async (event, defaultHandler, ctx) => {
if (event.actionId === 'retry') {
await event.thread?.post('Retrying...')
return
}
await defaultHandler()
},
},
},
设置 onAction: false 会完全禁用操作处理,包括内置的工具审批按钮。要在 channels 启动后注册更多 Chat SDK 处理器,请使用 agent.channels.sdk。
回复格式化回复格式化的直接链接
Agent 回复默认以 markdown 发布。具有原生 markdown 渲染的平台(例如 Slack)会直接渲染粗体文本、链接和表格。其他平台会将 markdown 转换为其自身格式。Agents 编写标准 markdown,即可在所有地方正确渲染,与同一回复在 Studio 中的渲染效果一致。
在适配器上设置 textFormat: 'plain',可将回复改为作为字面纯文本发布:
channels: {
adapters: {
slack: {
adapter: createSlackAdapter(),
textFormat: 'plain',
},
},
},
如果你的 agent 被提示输出平台特定的方言(例如 Slack mrkdwn)而不是标准 markdown,请使用此逃生口。如果你曾为了绕过字面 markdown 渲染而添加此类提示指令,请改为移除它们。默认现在会原生渲染标准 markdown。textFormat 仅影响最终回复文本。工具卡片、错误消息和原生流式文本不受影响。
多用户感知多用户感知的直接链接
在群组对话中,Mastra 会在每条消息前加上发送者的名称和平台 ID,以便 agent 区分不同的说话者:
[Alice (@U123ABC)]: Can you help me with this?
[Bob (@U456DEF)]: I have a question too.
每条消息的 Signal 元数据每条消息的 Signal 元数据的直接链接
在自定义 Channel 处理器中使用 signalMetadata,将结构化上下文附加到一条入站消息。当消息启动空闲运行或加入活动运行时,该元数据会随消息一起传递。
以下示例在调用默认处理器之前附加已注册的文件 ID:
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(),
},
handlers: {
onDirectMessage: async (thread, message, defaultHandler, ctx) => {
ctx.signalMetadata.attachmentIds = ['file-1']
await defaultHandler(thread, message)
},
},
},
})
只添加可 JSON 序列化的非敏感值。Signal 元数据可能存储在 memory 中,或通过共享的发布-订阅传输发送。它不会被添加到模型提示中。
使用 requestContext 表示运行作用域的配置,例如启动运行的消息所用凭据。使用 signalMetadata 表示必须附加到一条消息的上下文,包括投递到活动运行的消息。
错误处理与投递错误处理与投递的直接链接
渠道 webhook 会在 agent 完成之前向平台确认,因此 200 响应表示"已收到",而不是"已回答"。在确认之前,适配器会同步拒绝错误请求(验证失败返回 401,无法解析的请求体返回 400,瞬时状态失败返回 503),平台会根据其自身策略对非 2xx 响应重新投递。在 200 之后,平台不再重试,错误由 Mastra 负责。默认处理器会捕获 agent 运行失败,并向 thread 发布错误消息(可使用 formatError 自定义,默认是 ❌ Error: {message})。自定义处理器若因单条消息抛出异常,Chat SDK 只会记录日志,因此不会发布任何内容,也不会重试(多发送者批次请参阅批量消息)。请在自定义处理器中自行捕获失败:
channels: {
adapters: {
slack: createSlackAdapter(),
},
handlers: {
onDirectMessage: async (thread, message, defaultHandler, ctx) => {
try {
ctx.signalMetadata.ticketId = await lookupTicket(message)
} catch (error) {
ctx.mastra?.getLogger().error('Ticket lookup failed', { error })
await thread.post('Something went wrong looking up your ticket. Try again in a moment.')
return
}
await defaultHandler(thread, message)
},
},
},
平台重试有时会重复投递事件。适配器使用渠道状态进行去重,存储可以在重启后保留该状态。由于此保护是尽力而为的,自定义处理器的副作用应当幂等,以免重复投递重复执行诸如创建工单之类的工作。
批量消息批量消息的直接链接
当 chatOptions.concurrency 策略(burst、debounce 或 queue)将多条消息批量合并为一次分发时,Mastra 会将批次拆分为每个发送者一轮:来自同一发送者的连续消息构成一轮,按从旧到新排序。你的处理器每轮运行一次,拥有自己的 ctx.requestContext、ctx.signalMetadata 和 ctx.skipped(该轮较早的消息),因此授权和上下文会应用于每个发送者。请在处理器内 await defaultHandler,否则各发送者的轮次可能重叠。某一轮抛出异常的处理器会被记录,其余轮次仍会运行,随后重新抛出第一个错误。在因某条消息提及 bot 而路由到 onMention 的批次中,其他发送者的非提及消息也会到达 onMention,且 message.isMention 为 false。
多模态内容多模态内容的直接链接
Gemini 等模型可以原生处理图像、视频和音频。结合 inlineMedia 和 inlineLinks,让用户跨平台与你的 agent 分享富内容:
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 响应期间保持函数存活的方法,以及供实例协调的共享 pub/sub。
使用 waitUntil 保持函数存活keep-the-function-alive-with-waituntil的直接链接
渠道 webhook 会立即返回 200 响应,然后 agent 在后台运行以发布其回复。在大多数无服务器平台上,函数一旦响应就会被冻结,这会在 agent 回答之前停止运行。传入 waitUntil 函数,以便平台保持实例存活直到运行完成。
在 Vercel 上,从 @vercel/functions 传入 waitUntil:
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 需要 waitUntil,因为它们在响应发送后立即冻结函数。Cloudflare Workers 和 Netlify Functions 会从 request context 自动检测,因此不需要它。对于 waitUntil 位于 request context 上但未被自动检测的 runtime,请使用 resolveWaitUntil。详情请参阅 Channels 参考。
使用共享 pub/sub 协调实例使用共享 pub/sub 协调实例的直接链接
Channels 通过 agent 的 signal 管道路由消息,并且每次运行都会在其 thread 上获取租约,以便同一时间只有一个运行拥有该对话。
默认的内存 pub/sub 无法跨越实例边界,因此在无服务器环境中,后续消息可能被路由到与运行 agent 不同的实例。
没有共享 pub/sub 时,该实例无法触达活动运行并会启动自己的运行,导致原始运行不受影响且该 thread 被处理两次。
在 Mastra 实例上配置由 Redis Streams 支持的共享 pub/sub,以便租约和 signals 跨实例协调:
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 参考。
其他适配器其他适配器的直接链接
Mastra channels 使用 Chat SDK 适配器,因此平台指南并不是支持平台的完整列表。可以使用任何导出了与 channels.adapters 兼容的适配器工厂的 Chat SDK 平台适配器。
适配器目录适配器目录的直接链接
Chat SDK 适配器目录是可用适配器的权威来源。下面的列表是一个快照,可能不总是最新。
在撰写本文时,Chat SDK 列出了以下适配器:
- AgentPhone
- Baileys WhatsApp
- Discord
- GitHub
- Google Chat
- iMessage
- Kapso
- Lark / Feishu
- Linear
- Linq
- Liveblocks
- Matrix
- Mattermost
- Messenger
- Novu
- Resend
- Sendblue
- Telegram
- Twilio
- Velt
- Web
- Webex
- WhatsApp Business Cloud
- X
- Zalo
- Zernio
请查看适配器的文档以了解其包名、凭据变量、webhook 要求以及平台特定行为。
使用相同的 Mastra 接线使用相同的 Mastra 接线的直接链接
每个 Chat SDK 适配器的 Mastra 侧都遵循相同的设置。安装适配器包并将其工厂添加到 channels.adapters。然后配置平台凭据,并将其 webhook 指向生成的 Mastra 路由。
使用以下平台指南之一作为 Mastra 接线的参考:
检查适配器文档检查适配器文档的直接链接
在将新适配器接入 Mastra 之前,请检查适配器文档中关于以下内容的信息:
- 附件、卡片和富消息支持。
- 凭据环境变量。
- 所需的平台权限或作用域。
- 普通消息是否需要长时间运行的监听器或轮询。
- 平台是否需要用于设置、事件或交互的单独路由。
- Webhook 验证行为。