channels()
Returns a live channels resolver over the connections attached to a Mastra platform project, ready to hand to new Mastra({ channels }). Enabled provider instances are constructed once, without credentials, so their webhook and OAuth routes can mount at Mastra construction. The resolver caches the project's connections and binds credentials to these instances as connections change, without redeploying the app.
import { Mastra } from '@mastra/core'
import { channels } from '@mastra/connect'
export const mastra = new Mastra({
agents: { assistant },
channels: await channels(),
})
Returns: Promise<ChannelsResolver>. See The resolver.
The documented channel setup covers Slack, Telegram, and Discord. Their implementations come from @mastra/slack, @mastra/telegram, and @mastra/discord, loaded on demand. Use those packages directly to configure a channel outside the platform connection flow.
The SDK also registers microsoft-teams, backed by @mastra/teams. SDK registration doesn't guarantee availability in the platform catalog. Constructing the Teams provider requires MASTRA_ENCRYPTION_KEY, a base64-encoded 32-byte value for protecting stored bot secrets. Without it, the resolver warns and skips Teams, including its routes.
ParametersDirect link to Parameters
options?:
projectId?:
providers?:
client?:
ttlMs?:
Use the array form to mount only the named channels. The record form leaves other registered channels enabled:
const onlyDiscord = await channels({ providers: ['discord'] })
const allExceptTelegram = await channels({ providers: { telegram: false } })
Per-provider optionsDirect link to Per-provider options
Each value in the providers record form is true, false, or a ChannelsProviderOptions. false excludes the channel entirely: no instance is constructed and no routes are mounted.
connectionId?:
providerOptions?:
The resolverDirect link to The resolver
The resolved ChannelsResolver satisfies @mastra/core's channels-resolver contract:
- Callable: returns the current
Record<string, ChannelProvider>of providers with an active connection. Mastra invokes it at runtime; the TTL cache makes repeat calls cheap. Only the first resolution waits on the platform. After the TTL expires, resolution returns the stale snapshot immediately and refreshes in the background, skipping the refresh during a short cooldown after a failed fetch, so a new connection can appear one resolution later than the TTL suggests. getRoutes(): the union of API routes for every enabled channel, available synchronously so Mastra can mount them at construction. Routes exist before (and after) their provider has an active connection.refresh(): fetches connections from the platform now and updates the cache. Rejects if the platform fetch fails.disconnect(): clears the cached snapshot so the next resolution fetches fresh. It doesn't tear down providers, sessions, or credentials.
Providers without an active connection don't appear in the resolved map. Their routes stay mounted and begin working once a connection is attached.
Failure handling matches tools(): configuration errors (missing project ID, bad ttlMs, an unknown or malformed provider ID, both spellings of the Slack key) reject at call time, while per-provider problems (provider construction failure, needs_reauth, credential sync failure) are downgraded to warn-and-skip. Several active connections for one provider aren't a skip: the resolver warns and uses the first, and providers.<id>.connectionId pins the choice. The initial resolution rejects if its platform fetch fails. A failed background refresh warns and preserves the cached snapshot, while an explicit refresh() rejects on fetch failure.
Discord permissionsDirect link to Discord permissions
The Discord bot-invite URL requests the bot and applications.commands scopes with these permissions:
- View Channels
- Send Messages
- Send Messages in Threads
- Embed Links
- Attach Files
- Read Message History
- Add Reactions
- Use Application Commands
These permissions support chat, threads, files, reactions, and slash commands without granting moderation or channel-management access. Override the permission bitfield through providers.discord.providerOptions.permissions. See the Discord permissions reference for bit values.
ErrorsDirect link to Errors
Throws MastraConnectError with a code property:
| Code | When |
|---|---|
missing_project_id | No project ID configured |
missing_access_token | No platform token configured |
invalid_options | Unknown or malformed provider ID, both slack and slack-channels in one config, a malformed provider entry, or invalid ttlMs |
no_active_connection | A channel needed its credential while its provider has no active connection |
unauthorized | The platform rejected the token (401/403) |
platform_error | Any other platform request failure |