How to Build Your First AI-Powered Slack Bot
Create a Slack bot that responds to messages using Claude or GPT.
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
- A Slack workspace where you have admin access
- Python 3.9+ with
slack-boltandanthropicoropenaiinstalled - A public URL for your bot endpoint (ngrok for testing)
- An AI API key
- About 30 minutes
Step 1: Create a Slack App
Go to api.slack.com/apps
Click "Create New App" > "From scratch"
Name it (e.g., "AI Assistant") and select your workspace
In the left sidebar, go to "OAuth and Permissions"
Under "Bot Token Scopes," add these permissions:
app_mentions:read- See when the bot is mentionedchannels:history- Read messages in channelschat:write- Post messagesim:history- Read direct messagesim:write- Send direct messages
Click "Install to Workspace" and authorize
Copy the "Bot User OAuth Token" (starts with
xoxb-)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
- In your Slack app settings, go to "Event Subscriptions"
- Enable events
- Set Request URL to
https://your-ngrok-url.ngrok.io/slack/events - Slack will send a challenge. Your running app will respond automatically.
- Under "Subscribe to bot events," add:
app_mentionmessage.im
- 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:
- In Slack app settings, enable "Socket Mode" under "Socket Mode"
- Generate an App-Level Token with
connections:writescope - 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
- Add a knowledge base lookup so the bot can answer company-specific questions accurately
- Build a
/reportcommand that queries your databases and posts a formatted summary - Add Slack Block Kit formatting for richer responses with buttons, dropdowns, and structured layouts
Related Reading
- How to Build a Multi-Turn Conversation with Claude - The conversation memory pattern this bot uses
- How to Set Up Anthropic Claude with System Prompts - Fine-tune the bot's personality and format
- How to Handle AI API Rate Limits Gracefully - Busy Slack workspaces can hit rate limits quickly
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