Skip to main content

Slack

Use Slack with Mastra in two ways:

  • Agent tools let an agent act in Slack, for example to read conversations or send messages.
  • Agent chat lets people message your agent in Slack channel threads or direct messages. Mastra runs the agent for each message and streams the response back to Slack. The Slack adapter handles Slack AI indicators and interactive cards for you.

Mastra Connect sets up both and keeps Slack credentials on the Mastra platform. For agent chat, you can also create and manage your own Slack app instead.

Connect
Direct link to Connect

Before you start, complete the Connect setup to install @mastra/connect and configure your platform project.

Slack tools and Slack chat use separate connections with different credentials, so one connection can't serve both:

  • slack authorizes a workspace for agent tools.
  • slack-channels stores an app configuration token for agent chat.

To use both, add both connections.

Agent tools
Direct link to Agent tools

Give agents tools to read conversations, send and schedule messages, and manage channels in Slack.

Connect an account with the slack provider ID. Run this command from the directory that contains your .env file:

mastra connect add slack

Then pass tools() to the agent and select the provider:

src/mastra/agents/slack-agent.ts
import { Agent } from '@mastra/core/agent'
import { tools } from '@mastra/connect'

export const slackAgent = new Agent({
id: 'slack-agent',
name: 'Slack agent',
instructions:
'You help people read conversations, send and schedule messages, and manage channels in Slack.',
model: '__GATEWAY_OPENAI_MODEL_LUNA__',
tools: tools({ providers: ['slack'] }),
})

The agent gets 52 Slack tools, with keys such as slack_add_reaction. See Slack tools for the full list, and the tools() parameters to restrict tools or require approval before a call runs.

Agent chat
Direct link to Agent chat

Slack chat uses an app configuration token, which lets Mastra create a Slack app for each agent. Mastra creates and manages these apps. It doesn't use a Slack app that you created yourself, such as one from the self-managed setup.

Your server needs a public URL that Slack can reach for webhook delivery and OAuth callbacks. Mastra platform supplies this URL. When you host elsewhere, set MASTRA_SERVER_URL to your public server URL. For local development, use a public HTTPS tunnel.

  1. Open Slack apps, then open Your App Configuration Tokens.

  2. Generate an app configuration token for the workspace where the agent will run.

  3. Run mastra connect add slack-channels and complete the authorization flow. The platform stores and rotates the configuration credential.

  4. Pass channels() to the Mastra constructor. It registers the Slack channel provider and its routes:

    src/mastra/index.ts
    import { Mastra } from '@mastra/core'
    import { channels } from '@mastra/connect'
    import { assistant } from './agents/assistant'

    export const mastra = new Mastra({
    agents: { assistant },
    channels: await channels({ providers: ['slack'] }),
    })

    The slack key in channels() refers to the slack-channels connection.

  5. Start your Mastra application.

  6. In Studio, connect the Slack channel to an agent. Mastra creates a Slack app and returns an authorization URL. Open it, choose the workspace, and approve the bot scopes.

The default Slack manifest lists the requested scopes and event subscriptions.

Self-managed setup
Direct link to Self-managed setup

Create a Slack app yourself and store its credentials in your Mastra environment. Use this path for agent chat when you want to control the Slack app directly.

Installation
Direct link to Installation

Install the Slack adapter from the Chat SDK:

npm install @chat-adapter/slack

Add createSlackAdapter() to the agent's channels.adapters object:

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: 'Help people plan tasks, answer questions, and coordinate work in Slack.',
model: 'anthropic/claude-opus-5-5',
channels: {
adapters: {
slack: createSlackAdapter(),
},
},
})

Create a Slack app
Direct link to Create a Slack app

To connect your agent, create a Slack app in the workspace where you want it to run. The Slack app controls your agent's display in Slack, its capabilities, and the events it receives.

This guide uses a manifest: a configuration file that creates the Slack app settings for you. This is the fastest path when you are adding your agent to your own workspace. It doesn't cover the platform OAuth flow where other workspaces install your agent.

Create the Slack app from a manifest:

  1. Open api.slack.com/apps.
  2. Select Create an app.
  3. Select From a manifest.
  4. Choose the workspace where the agent should run.
  5. Paste this manifest, then select Create. Slack accepts JSON or YAML, so use whichever tab matches the format shown in the app creation modal:
{
"display_information": {
"name": "mastra-agent"
},
"features": {
"app_home": {
"home_tab_enabled": false,
"messages_tab_enabled": true,
"messages_tab_read_only_enabled": false
},
"bot_user": {
"display_name": "mastra-agent",
"always_online": true
}
},
"oauth_config": {
"scopes": {
"bot": [
"im:write",
"app_mentions:read",
"channels:history",
"channels:read",
"chat:write",
"users:read",
"im:read",
"im:history"
]
},
"pkce_enabled": false
},
"settings": {
"event_subscriptions": {
"request_url": "https://<YOUR-PUBLIC-URL>/api/agents/<YOUR-AGENT-ID>/channels/slack/webhook",
"bot_events": ["app_mention", "message.channels", "message.im"]
},
"interactivity": {
"is_enabled": true,
"request_url": "https://<YOUR-PUBLIC-URL>/api/agents/<YOUR-AGENT-ID>/channels/slack/webhook"
},
"org_deploy_enabled": false,
"socket_mode_enabled": false,
"token_rotation_enabled": false,
"is_mcp_enabled": false
}
}

This manifest configures:

  • display_information.name and features.bot_user.display_name: Set your agent's name in Slack. You can update it at any time. Remember to reinstall the app after changing names or permissions.
  • app_home.messages_tab_enabled and app_home.messages_tab_read_only_enabled: Enable direct messages from the Slack app's Messages tab.
  • always_online: Shows the Slack bot user as always available.
  • oauth_config.scopes.bot: Grants permission to post and read messages in channels where the bot is present. It also covers mentions and direct messages, together with user lookup.
  • event_subscriptions: Tells Slack which message events to send to the webhook.
  • interactivity: Enables interactive cards and tells Slack where to send card actions.

After the app is created, open Install App, select Install to Workspace, and approve the requested scopes.

Set Slack credentials
Direct link to Set Slack credentials

Set the Slack credentials in Mastra so it can verify Slack requests and send messages back to Slack.

In the Slack app settings, copy these values:

  • Basic Information > App Credentials > Signing Secret
  • OAuth & Permissions > Bot User OAuth Token

Set them in your Mastra environment:

.env
SLACK_SIGNING_SECRET=your-signing-secret
SLACK_BOT_TOKEN=xoxb-your-bot-token

Mastra reads these environment variables automatically.

Configure the webhook route
Direct link to Configure the webhook route

Slack sends channel activity to Mastra through webhooks. A webhook is an HTTP endpoint Slack calls when something happens, such as a new message, a mention, or a user selecting an interactive card.

Mastra automatically registers a Slack webhook route for your agent:

/api/agents/<YOUR-AGENT-ID>/channels/slack/webhook

Build the webhook URL from your public Mastra server URL and the generated route:

https://<YOUR-PUBLIC-URL>/api/agents/<YOUR-AGENT-ID>/channels/slack/webhook

Slack can't send events to localhost. For local development, keep the Mastra dev server running and expose http://localhost:4111 with a tunnel before you save the request URL in Slack.

Use a tunnel such as cloudflared or ngrok for local development:

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

Use the generated tunnel host as <YOUR-PUBLIC-URL>, for example:

https://abc123.trycloudflare.com/api/agents/your-agent/channels/slack/webhook

Update the request URLs in Slack:

  1. In the Slack app settings, open Event Subscriptions.
  2. Replace Request URL with the final webhook URL.
  3. Select Save Changes.
  4. Open Interactivity & Shortcuts.
  5. Replace Request URL with the same webhook URL.
  6. Select Save Changes.
  7. If Slack asks you to reinstall the app, open OAuth & Permissions and select Reinstall to Workspace.

Try it in Slack
Direct link to Try it in Slack

Open a direct message with the Slack bot user and send a message. Direct messages work because the manifest includes the message.im event and im:* scopes.

To use the agent in a channel, invite the Slack bot user first:

/invite @your-bot-name

Mention the bot in the channel:

@your-bot-name What can you help me with?

The agent responds in the thread. Response content depends on the model, instructions, memory, and tools configured on the agent.

Authentication
Direct link to Authentication

The Slack adapter has no built-in user allowlist. Once the app is installed, anyone in the workspace can talk to the agent by sending it a direct message or mentioning it in a channel where it's a member. Slack verifies each request with the signing secret, and Mastra runs the agent for every valid message the webhook receives.

The main mechanism for controlling access is channel membership. The bot only receives events from direct messages and from channels it has been invited to, so the set of channels the bot belongs to defines who can reach it. Keep the bot out of channels where it shouldn't respond, and remove it from a channel to cut off access.

For finer control, gate on the sender's identity. Every request carries the sender's Slack user ID in the channel request context, so you can allow or deny specific users in an input processor or tool before the agent acts.

Server authentication
Direct link to Server authentication

The Slack webhook route is exempt from Mastra's server authentication. Slack can't send a bearer token, so Mastra registers the channel webhook as a public route and verifies each request with the Slack signing secret instead. This holds even when you enable a provider like MastraAuthSimple: the rest of your API stays protected, but the webhook route relies on the signing secret rather than your server auth. With the self-managed setup, keep SLACK_SIGNING_SECRET set so the adapter can reject requests that Slack didn't sign.

External channels
Direct link to External channels

Shared channels (Slack Connect) let people from other workspaces join a conversation. If a workspace member adds the bot to a shared channel, everyone in that channel can talk to the agent, including external members outside your organization. Anyone who can reach the agent can also reach the tools and data it has access to.

Treat adding the bot to a shared or external channel as granting those participants access to the agent. Before you do, confirm the agent's tools and data are safe to expose to outside members, and gate on the sender's user ID when you need to restrict who the agent responds to.

Request context
Direct link to Request context

On every message, Mastra places a channel context object on the request context under the channel key. It carries the sender's Slack display name and user ID, the bot's own identity, and details about where the message came from. Read it from an input processor or a tool to identify the user or branch on the conversation type:

src/mastra/tools/whoami.ts
import { createTool } from '@mastra/core/tools'
import type { ChannelContext } from '@mastra/core/channels'
import { z } from 'zod'

export const whoami = createTool({
id: 'whoami',
description: 'Return the Slack identity of the current user',
inputSchema: z.object({}),
execute: async (_input, context) => {
const channel = context?.requestContext?.get('channel') as ChannelContext | undefined

return {
platform: channel?.platform,
userId: channel?.userId,
userName: channel?.userName,
isDM: channel?.isDM,
}
},
})

The channel context includes:

  • botMention, botUserId, and botUserName: The bot's own identity on Slack.
  • channelId and threadId: The Slack channel and thread the message arrived on.
  • isDM: Whether the message is a direct message.
  • platform: The platform identifier, slack for this adapter.
  • userId and userName: The sender's Slack user ID and display name.

Mastra also turns this context into a short system message. The agent learns the platform and its own identity, plus whether the conversation is a direct message or a public channel. See thread context in the channels overview for how to change that behavior.

Production deployment
Direct link to Production deployment

With the self-managed setup, update both request URLs in the Slack app settings to the production webhook URL when you deploy the Mastra server. The tunnel URL used for local development is temporary and changes when the tunnel restarts.

Channels on serverless platforms may need waitUntil and shared pub/sub configuration so background responses and thread leases work across short-lived instances. See serverless deployment in the channels overview.

Idle servers
Direct link to Idle servers

Platform servers scale down to idle when they aren't receiving traffic, and that's fine for Slack. The next event, such as a mention or direct message, wakes the server by delivering its webhook request, and the server resumes handling requests. The first response after the server has been idle can take a little longer while it starts up, which is expected. Slack expects a 200 acknowledgement within 3 seconds and retries the event up to three times when delivery fails or times out, so a very slow cold start may take a retry before the agent responds. Subsequent messages respond at normal speed while the server stays warm.