Systems Library / AI Model Setup / How to Build Your First AI-Powered Slack Bot
AI Model Setup foundations

How to Build Your First AI-Powered Slack Bot

Create a Slack bot that responds to messages using Claude or GPT.

Jay Banlasan

Jay Banlasan

The AI Systems Guy

Building an AI-powered Slack bot puts your AI assistant where your team already works. The build ai slack bot tutorial python path I use takes about 30 minutes for a working bot and another hour to make it production-ready. Once it is live, your team can ask questions, run automations, and get AI assistance without leaving Slack. I have built these for internal knowledge base search, daily report generation, and client status updates.

The architecture is straightforward: Slack sends events to your server via webhooks, your server calls an AI API, and your server posts the response back to Slack. You need a publicly accessible URL, which you can get with ngrok for local testing and a VPS for production.

What You Need Before Starting

Step 1: Create a Slack App

  1. Go to api.slack.com/apps

  2. Click "Create New App" > "From scratch"

  3. Name it (e.g., "AI Assistant") and select your workspace

  4. In the left sidebar, go to "OAuth and Permissions"

  5. Under "Bot Token Scopes," add these permissions:

    • app_mentions:read - See when the bot is mentioned
    • channels:history - Read messages in channels
    • chat:write - Post messages
    • im:history - Read direct messages
    • im:write - Send direct messages
  6. Click "Install to Workspace" and authorize

  7. Copy the "Bot User OAuth Token" (starts with xoxb-)

  8. Go to "Basic Information" and copy the "Signing Secret"

Add to .env:

SLACK_BOT_TOKEN=xoxb-your-token-here
SLACK_SIGNING_SECRET=your-signing-secret-here
ANTHROPIC_API_KEY=sk-ant-your-key-here

Step 2: Set Up ngrok for Local Testing

Install ngrok from ngrok.com and run it:

ngrok http 3000

Copy the forwarding URL (e.g., https://abc123.ngrok.io). You will use this in step 3.

Step 3: Install Dependencies and Write the Bot

pip install slack-bolt anthropic python-dotenv
# bot.py
import os
import anthropic
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
from dotenv import load_dotenv

load_dotenv()

# Initialize Slack app
app = App(
    token=os.getenv("SLACK_BOT_TOKEN"),
    signing_secret=os.getenv("SLACK_SIGNING_SECRET")
)

# Initialize AI client
claude = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))

SYSTEM_PROMPT = """You are a helpful AI assistant in a Slack workspace.
Be concise. Use Slack markdown formatting where appropriate (bold with *text*, bullets with bullets).
Keep responses under 300 words unless the user asks for more detail."""


def ask_ai(user_message: str) -> str:
    """Send a message to Claude and get a response."""
    response = claude.messages.create(
        model="claude-haiku-20240307",  # Fast and cheap for Slack
        max_tokens=500,
        system=SYSTEM_PROMPT,
        messages=[{"role": "user", "content": user_message}]
    )
    return response.content[0].text


# Respond to direct messages
@app.message()
def handle_dm(message, say):
    if message.get("channel_type") == "im":
        user_text = message.get("text", "")
        if user_text:
            response = ask_ai(user_text)
            say(response)


# Respond to @mentions in channels
@app.event("app_mention")
def handle_mention(event, say):
    # Remove the @bot mention from the text
    user_text = event.get("text", "")
    # Strip the bot user ID mention
    import re
    clean_text = re.sub(r"<@[A-Z0-9]+>", "", user_text).strip()
    
    if clean_text:
        response = ask_ai(clean_text)
        say(response)
    else:
        say("Hey! Ask me anything.")


if __name__ == "__main__":
    app.start(port=3000)

Step 4: Configure Event Subscriptions in Slack

  1. In your Slack app settings, go to "Event Subscriptions"
  2. Enable events
  3. Set Request URL to https://your-ngrok-url.ngrok.io/slack/events
  4. Slack will send a challenge. Your running app will respond automatically.
  5. Under "Subscribe to bot events," add:
    • app_mention
    • message.im
  6. Save changes

Step 5: Add Conversation Memory Per User

from collections import defaultdict

# In-memory conversation history per user (use Redis in production)
user_conversations: dict[str, list] = defaultdict(list)
MAX_HISTORY = 10


def ask_ai_with_memory(user_id: str, user_message: str) -> str:
    """
    Respond to a user while maintaining their conversation history.
    """
    history = user_conversations[user_id]
    history.append({"role": "user", "content": user_message})
    
    # Trim history
    if len(history) > MAX_HISTORY:
        user_conversations[user_id] = history[-MAX_HISTORY:]
        history = user_conversations[user_id]
    
    response = claude.messages.create(
        model="claude-haiku-20240307",
        max_tokens=500,
        system=SYSTEM_PROMPT,
        messages=history
    )
    
    reply = response.content[0].text
    history.append({"role": "assistant", "content": reply})
    
    return reply


# Reset command
@app.message("reset")
def reset_conversation(message, say):
    if message.get("channel_type") == "im":
        user_id = message["user"]
        user_conversations[user_id] = []
        say("Conversation reset. Starting fresh!")

Step 6: Add Slash Commands

Register slash commands in your Slack app settings, then handle them:

# Handle /summarize command
@app.command("/summarize")
def handle_summarize(ack, respond, command):
    ack()  # Always acknowledge within 3 seconds
    
    text = command.get("text", "").strip()
    if not text:
        respond("Usage: /summarize [text to summarize]")
        return
    
    response = claude.messages.create(
        model="claude-haiku-20240307",
        max_tokens=200,
        messages=[{
            "role": "user",
            "content": f"Summarize this in 3 bullet points:\n\n{text}"
        }]
    )
    
    respond(response.content[0].text)


# Handle /ask command
@app.command("/ask")
def handle_ask(ack, respond, command):
    ack()
    question = command.get("text", "").strip()
    if question:
        answer = ask_ai(question)
        respond(answer)
    else:
        respond("Usage: /ask [your question]")

Step 7: Deploy to Production

For a VPS deployment, use Socket Mode instead of HTTP events. Socket Mode creates a WebSocket connection from your server to Slack, so you do not need a public URL:

  1. In Slack app settings, enable "Socket Mode" under "Socket Mode"
  2. Generate an App-Level Token with connections:write scope
  3. Add to .env: SLACK_APP_TOKEN=xapp-your-token-here
# Production deployment with Socket Mode
if __name__ == "__main__":
    handler = SocketModeHandler(app, os.getenv("SLACK_APP_TOKEN"))
    handler.start()

Run as a systemd service or with PM2 for automatic restarts.

What to Build Next

Related Reading

Want this system built for your business?

Get a free assessment. We will map every system your business needs and show you the ROI.

Get Your Free Assessment

Related Systems