A pattern for connecting Slack bots to Mastra agents with streaming responses and conversation memory.
This example includes two demo agents (reverse, caps) — each gets its own Slack app and webhook route.
Slack message → /slack/{app}/events → Mastra agent → streaming response back to Slack
- One Slack app per agent — each agent has its own bot token and signing secret
- Streaming updates — shows typing indicators while the agent thinks/uses tools
- Thread memory — conversations are scoped to Slack threads via Mastra memory
pnpm installCreate .env:
OPENAI_API_KEY=sk-your-key
# Each Slack app needs its own credentials
SLACK_REVERSE_BOT_TOKEN=xoxb-...
SLACK_REVERSE_SIGNING_SECRET=...
SLACK_CAPS_BOT_TOKEN=xoxb-...
SLACK_CAPS_SIGNING_SECRET=...For each agent you want to expose:
- api.slack.com/apps → Create New App → From scratch
- OAuth & Permissions → Add Bot Token Scopes and Get Token:
app_mentions:read— receive @mentionschannels:history— read messages in public channelschat:write— send messagesim:history— read direct messages- Copy Bot User OAuth Token to .env
- Event Subscriptions → Enable and set Request URL:
https://your-server.com/slack/{agentName}/events
- Subscribe to bot events:
app_mention,message.im - Agents & AI Apps → Toggle on to enable agent features
- Basic Information → copy Signing Secret to .env
# Dev with ngrok for webhooks
ngrok http 4111
pnpm dev// src/mastra/agents/my-agent.ts
import { Agent } from '@mastra/core/agent';
import { Memory } from '@mastra/memory';
export const myAgent = new Agent({
name: 'my-agent',
instructions: 'Your agent instructions...',
model: 'openai/gpt-4o-mini',
memory: new Memory({ options: { lastMessages: 20 } }),
});// src/mastra/index.ts
import { myAgent } from './agents/my-agent';
export const mastra = new Mastra({
agents: { myAgent },
// ...
});// src/mastra/slack/routes.ts
const slackApps: SlackAppConfig[] = [
{
name: 'my-agent', // Route: /slack/my-agent/events
botToken: process.env.SLACK_MY_AGENT_BOT_TOKEN!,
signingSecret: process.env.SLACK_MY_AGENT_SIGNING_SECRET!,
agentName: 'myAgent', // Must match key in mastra.agents
},
];Follow the Slack app setup above, then add the credentials to .env.
src/mastra/
├── agents/
│ ├── caps-agent.ts # Simple text transformation agent
│ └── reverse-agent.ts # Agent with tool + workflow capabilities
├── slack/
│ ├── chunks.ts # Handle nested streaming chunk events
│ ├── constants.ts # Animation timing configuration
│ ├── routes.ts # Slack webhook handlers (creates one per app)
│ ├── status.ts # Format status text with spinners
│ ├── streaming.ts # Stream agent responses to Slack
│ ├── types.ts # TypeScript type definitions
│ ├── utils.ts # Helper functions
│ └── verify.ts # Slack request signature verification
├── workflows/
│ └── reverse-workflow.ts # Multi-step text transformation workflow
└── index.ts # Mastra instance with agents and routes
routes.ts— Defines webhook endpoints and maps Slack apps to agentsstreaming.ts— Streams responses with animated spinners and tool/workflow indicatorsstatus.ts— Formats status messages (thinking, tool calls, workflow steps)verify.ts— Validates Slack request signatures for security