SlackProvider
SlackProvider is the managed path for connecting agents to Slack. Register it on Mastra.channels and it provisions Slack apps via the Manifest API, runs the OAuth install flow, rotates configuration tokens, and routes Slack events to your agents. Use it when you want Mastra to own app creation and installation. For the lower-level path where you create the Slack app and configure scopes and webhooks yourself, use createSlackAdapter on the agent's channels.adapters instead.
Usage exampleDirect link to Usage example
Register the provider on the Mastra constructor. The refresh token is single-use and rotates on startup; the resulting access tokens are persisted to Mastra.storage.
import { Mastra } from '@mastra/core/mastra'
import { SlackProvider } from '@mastra/slack'
export const mastra = new Mastra({
storage,
channels: {
slack: new SlackProvider({
refreshToken: process.env.SLACK_APP_CONFIG_REFRESH_TOKEN,
baseUrl: process.env.MASTRA_BASE_URL,
}),
},
})
When credentials aren't available at construction time (for example, entered through the Editor UI or loaded from a vault), construct the provider without them and call configure() later:
const slack = new SlackProvider()
await slack.configure({
refreshToken: process.env.SLACK_APP_CONFIG_REFRESH_TOKEN,
})
Constructor parametersDirect link to Constructor parameters
SlackProviderConfig combines Slack-specific fields, Slack-adapter overrides (toolDisplay, streaming, typingStatus), and a curated subset of ChannelConfig options (such as handlers, inlineMedia, and state) forwarded to every connected agent. All fields are optional.
refreshToken?:
configure(). If omitted, the provider starts unconfigured and cannot create apps until configure() is called or tokens are loaded from storage. Generate it under "Your App Configuration Tokens" at api.slack.com/apps.token?:
refreshToken.baseUrl?:
connect() to create apps. Can also be set via setBaseUrl() or auto-detected from the Mastra server config. For local development, use a tunnel such as cloudflared.encryptionKey?:
MASTRA_ENCRYPTION_KEY env var. If omitted, secrets are stored in plaintext (not recommended for production).storage?:
ChannelsStorage from the global storage. Throws if no persistent storage is available.redirectPath?:
onInstall?:
streaming?:
{ updateIntervalMs } to customize the post-and-edit interval, or false to buffer text until step-finish. Disabling streaming restricts toolDisplay to static modes.toolDisplay?:
'cards', 'text', 'timeline', 'grouped', 'hidden', or a function. 'hidden' suppresses tool call/result rendering entirely. 'timeline' and 'grouped' require streaming. With streaming: false, only static modes are available and the default is 'cards'.typingStatus?:
false to disable, or pass a function to return custom status text per stream chunk (return undefined to fall back to the default for that chunk).waitUntil?:
waitUntil for the current Slack webhook request. Required on serverless runtimes where Hono can't bridge the platform's ExecutionContext (Vercel, AWS Lambda). Without it, the invocation freezes after the 200 ack and kills the run mid-flight. Pass the bare waitUntil(promise) from your platform SDK (for example, @vercel/functions). Cloudflare Workers and Netlify users typically don't need this.resolveWaitUntil?:
waitUntil from the request's Hono Context when the runtime exposes it through the request and core's default doesn't cover it. Resolution order: waitUntil → resolveWaitUntil → core default.handlers?:
onDirectMessage, onMention). Forwarded to AgentChannels for every agent connected via this provider.inlineMedia?:
inlineLinks?:
threadContext?:
tools?:
add_reaction, remove_reaction).state?:
MastraStateAdapter backed by the Mastra instance's configured storage, so subscriptions persist across restarts.chatOptions?:
logger?:
SlackAdapter. Defaults to the adapter's ConsoleLogger.MethodsDirect link to Methods
Agent connectionsDirect link to Agent connections
connect(agentId, options?)Direct link to connectagentid-options
Creates a new Slack app for the agent via the Manifest API and returns an OAuth result with the authorization URL to redirect the user to. Requires baseUrl to be set. If a pending installation already exists for the agent, returns its existing authorization URL instead of creating a duplicate app.
const result = await slack.connect('support-agent', {
name: 'Support Bot',
})
// Redirect the user to result.authorizationUrl to install the app
Returns: Promise<ChannelConnectResult>
interface ChannelConnectResult {
type: 'oauth'
installationId: string
authorizationUrl: string
}
SlackConnectOptions is serializable and can be stored for stored agents:
name?:
description?:
iconUrl?:
manifest?:
redirectUrl?:
redirectPath or /.disconnect(agentId)Direct link to disconnectagentid
Disconnects an agent from Slack by deleting its app and removing the installation from storage.
await slack.disconnect('support-agent')
Returns: Promise<void>
getInstallation(agentId)Direct link to getinstallationagentid
Returns the Slack installation for an agent, or null if none exists.
const installation = await slack.getInstallation('support-agent')
Returns: Promise<SlackInstallation | null>
listInstallations()Direct link to listinstallations
Lists all Slack installations (public info only), including active and pending.
const installations = await slack.listInstallations()
Returns: Promise<ChannelInstallationInfo[]>
ConfigurationDirect link to Configuration
configure(credentials)Direct link to configurecredentials
Provides or clears Slack App Configuration credentials at runtime. Use this when credentials aren't available at construction time. Pass null to clear credentials and delete stored tokens.
// Provide credentials (persists to storage immediately)
await slack.configure({ refreshToken: 'xoxe-1-...' })
// Clear credentials and stored tokens
await slack.configure(null)
Returns: Promise<void>
setBaseUrl(baseUrl)Direct link to setbaseurlbaseurl
Sets the public base URL used for webhook and OAuth callbacks. Use this when the URL isn't known at construction time and can't be auto-detected from the server config.
slack.setBaseUrl('https://abc123.trycloudflare.com')
initialize()Direct link to initialize
Recreates a SlackAdapter for each active installation in storage and injects AgentChannels into the corresponding agent so it receives Slack events on startup. Doesn't auto-provision new apps; use connect() to create one. Mastra calls this automatically, so you rarely call it directly.
await slack.initialize()
Returns: Promise<void>
Default manifestDirect link to Default manifest
When connect() builds a Slack app, the generated manifest requests a default set of bot scopes and event subscriptions. Override them with the manifest option on connect().
| Default bot scopes | Default bot events |
|---|---|
chat:write | app_mention |
chat:write.public | message.channels |
im:write | message.groups |
channels:history | message.im |
channels:read | message.mpim |
groups:history | |
groups:read | |
im:history | |
im:read | |
mpim:history | |
mpim:read | |
app_mentions:read | |
users:read | |
reactions:write | |
files:read | |
assistant:write |
Accessing the providerDirect link to Accessing the provider
Access the registered provider through the typed channels getter, keyed by the id you registered it under:
const result = await mastra.channels.slack.connect('support-agent')
When the key is only known at runtime, look it up by string id and pass the concrete type:
const slack = mastra.getChannelProvider<SlackProvider>('slack')
const result = await slack.connect('support-agent')
Storage requirementDirect link to Storage requirement
SlackProvider requires persistent storage on Mastra to encrypt and persist installations and rotating configuration tokens. The constructor throws if no persistent storage is available and no custom storage is passed.
RelatedDirect link to Related
- ChannelProvider: the interface
SlackProviderimplements - Channels: concepts, platform setup, and the
createSlackAdapterpath - Channels reference: the
channelsconfig on theAgentconstructor