Slack + Mastra

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.

How It Works

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

Setup

1. Install

 1pnpm install

2. Environment Variables

Create .env:

 1OPENAI_API_KEY=sk-your-key
 2
 3## Each Slack app needs its own credentials
 4SLACK_REVERSE_BOT_TOKEN=xoxb-...
 5SLACK_REVERSE_SIGNING_SECRET=...
 6
 7SLACK_CAPS_BOT_TOKEN=xoxb-...
 8SLACK_CAPS_SIGNING_SECRET=...

3. Create Slack Apps

For each agent you want to expose:

  1. api.slack.com/appsCreate New AppFrom scratch
  2. OAuth & Permissions → Add Bot Token Scopes and Get Token:
    • app_mentions:read — receive @mentions
    • channels:history — read messages in public channels
    • chat:write — send messages
    • im:history — read direct messages
    • Copy Bot User OAuth Token to .env
  3. Event Subscriptions → Enable and set Request URL:
    • https://your-server.com/slack/{agentName}/events
  4. Subscribe to bot events: app_mention, message.im
  5. Agents & AI Apps → Toggle on to enable agent features
  6. Basic Information → copy Signing Secret to .env

4. Run

 1## Dev with ngrok for webhooks
 2ngrok http 4111
 3pnpm dev

Adding Your Own Agents

1. Create the Agent

 1// src/mastra/agents/my-agent.ts
 2import { Agent } from '@mastra/core/agent';
 3import { Memory } from '@mastra/memory';
 4
 5export const myAgent = new Agent({
 6  name: 'my-agent',
 7  instructions: 'Your agent instructions...',
 8  model: 'openai/gpt-4o-mini',
 9  memory: new Memory({ options: { lastMessages: 20 } }),
10});

2. Register with Mastra

 1// src/mastra/index.ts
 2import { myAgent } from './agents/my-agent';
 3
 4export const mastra = new Mastra({
 5  agents: { myAgent },
 6  // ...
 7});

3. Add Slack Route

 1// src/mastra/slack/routes.ts
 2const slackApps: SlackAppConfig[] = [
 3  {
 4    name: 'my-agent', // Route: /slack/my-agent/events
 5    botToken: process.env.SLACK_MY_AGENT_BOT_TOKEN!,
 6    signingSecret: process.env.SLACK_MY_AGENT_SIGNING_SECRET!,
 7    agentName: 'myAgent', // Must match key in mastra.agents
 8  },
 9];

4. Create Slack App & Add Env Vars

Follow the Slack app setup above, then add the credentials to .env.

Project Structure

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

Key Files

  • routes.ts — Defines webhook endpoints and maps Slack apps to agents
  • streaming.ts — Streams responses with animated spinners and tool/workflow indicators
  • status.ts — Formats status messages (thinking, tool calls, workflow steps)
  • verify.ts — Validates Slack request signatures for security