Connecting the Claude Agent SDK to Slack

Create a Slack app, configure bot scopes and socket mode, install Slack Bolt, and wire up channel mentions and DMs. The full integration from app creation to first response.

4 min read
Slack agent SDK Claude Slack bot Slack Bolt agent connect agent Slack Slack socket mode bot

Two requirements before you write code

An Anthropic API key. Your Claude.ai subscription works for local development. A deployed Slack bot runs in the cloud without a subscription session — it needs an API key. Get one from console.anthropic.com. Treat it like a password.

A Slack workspace. Everything in this guide works on Slack's free plan.

Creating your Slack app

Go to api.slack.com/apps and click Create New AppFrom Scratch. Name it anything. Select your workspace.

Enable socket mode

Under Socket Mode, turn it on and generate a token. This is your SLACKAPPTOKEN. Copy it immediately.

Add bot token scopes

Under OAuth & PermissionsBot Token Scopes, add these five scopes:

  • app_mentions:read
  • chat:write
  • im:history
  • im:read
  • im:write

Save changes, then click Install to Workspace. After installing, copy the Bot User OAuth Token — this is your SLACKBOTTOKEN.

Subscribe to events

Under Event Subscriptions, enable events and subscribe to:

  • app_mention
  • message.im

Enable DMs

Under App HomeMessages Tab, enable Allow users to send Slash commands and messages from the messages tab.

Setting up your environment

Create a .env file in your project root:

ANTHROPIC_API_KEY=sk-ant-...
SLACK_BOT_TOKEN=xoxb-...
SLACK_APP_TOKEN=xapp-...

Add this to your .gitignore:

.env

Never commit these values. If one ends up in a public repository, rotate it immediately.

Installing Slack Bolt

bun add @slack/bolt

Writing the bot server

Create src/bot.ts:

import { App } from "@slack/bolt";
import { agentChat } from "./agent";

const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  appToken: process.env.SLACK_APP_TOKEN,
  socketMode: true,
});

// Handle @mentions in channels
app.event("app_mention", async ({ event, say }) => {
  const threadTs = event.thread_ts ?? event.ts;

  try {
    const { response } = await agentChat(event.text);
    await say({ text: response, thread_ts: threadTs });
  } catch (error) {
    await say({ text: "Something went wrong.", thread_ts: threadTs });
  }
});

// Handle DMs
app.event("message", async ({ event, say }) => {
  // Prevent infinite loops — skip bot messages
  if ("bot_id" in event) return;

  const threadTs = "thread_ts" in event ? event.thread_ts ?? event.ts : undefined;

  try {
    const { response } = await agentChat(
      "text" in event ? event.text ?? "" : ""
    );
    await say({ text: response, thread_ts: threadTs });
  } catch (error) {
    await say({ text: "Something went wrong.", thread_ts: threadTs });
  }
});

async function startBot() {
  await app.start();
  console.log("Bot is running.");
}

startBot();

The bot message guard is essential. Without the if ("bot_id" in event) return check, every response your bot posts triggers the message event again. You get an infinite loop that burns through API credits in seconds.

Running the bot

bun src/bot.ts

Go to your Slack workspace and @mention your app in a channel. Add the bot to the channel when prompted. You should see a response within a few seconds.

For DMs: find your app in the Slack sidebar under Apps, send a direct message.

What you have at this point

Channel mentions and DMs both work. The agent responds to every message. Each response is threaded under the original message.

What is not working yet:

  • Session persistence (each message starts a fresh conversation)
  • A thinking indicator
  • Slack-formatted markdown in responses

Those are covered in the Polishing the Slack Experience and Session Persistence guides.

> Real-world note: This same Bolt setup works for other messaging services. Discord, Telegram, and Microsoft Teams all have similar event-driven APIs. Once you understand the Slack pattern — receive event, call agentChat, post response — adapting it to another service is mostly swapping out the event handlers and posting functions.

---

Author: FractionalSkill

Keep Going

Ready to Start Building?

Pick the next step that matches where you are right now.

Tutorial
Claude Code Basics

Start with the terminal basics. A hands-on, step-by-step guide to your first 10 minutes with Claude Code.

Start the Tutorial
Guide
AI-Powered Workflows

Automate your client work. Learn how to connect AI tools into workflows that handle repetitive tasks for you.

Read the Guide
Community
Join the Community

Connect with other fractional leaders building with AI. Share workflows, get feedback, and learn from operators who are ahead of you.

Apply to Join