# How to Create an AI-Powered Slack Bot for Your Team

> Build an AI Slack bot in an afternoon. Step-by-step setup with Bolt for Python, Claude or OpenAI, and a deploy path that actually works.

- Source: https://zarifautomates.com/blog/how-to-create-ai-powered-slack-bot-for-your-team
- Published: 2026-07-02
- Updated: 2026-07-02
- Pillar: AI Automation Fundamentals
- Tags: slack-bot, ai-automation, claude-api, openai, bolt-python, tutorial
- Author: Zarif

---

Most teams talk about wanting an AI Slack bot. Most teams never ship one because every tutorial assumes you've already done it before. This is the version I wish existed when I built my first one.

An AI-powered Slack bot is a Slack app that listens for messages, mentions, or slash commands inside a workspace, sends those events to an LLM (Claude, GPT, Gemini), and posts the model's response back into Slack. The "AI" part is just an HTTP call. The "Slack bot" part is plumbing.

- The official Slack samples (bolt-python-ai-chatbot and bolt-python-assistant-template) are the fastest path to a working bot — they ship in under an hour if you follow the steps in order.
- You need three credentials: a Slack Bot Token, a Slack App Token, and an LLM API key (Anthropic, OpenAI, or both). That's it.
- Use Socket Mode for development, switch to HTTP events when you deploy to production. This single decision causes 80% of beginner pain.
- Streaming responses (using Slack's chat_stream utility) makes the bot feel 10x faster than the same model returning the same answer in one block.
- Don't build from scratch. Fork the official template, customize, deploy. Total build time for a useful bot: 2 to 4 hours.

## What You're Actually Building

Before code, get the architecture in your head. A Slack bot has four moving pieces:

A Slack App (configured at api.slack.com) defines the bot's permissions, name, and event subscriptions. A backend server (your code) receives events from Slack, calls an LLM, and posts replies. The LLM API (Anthropic, OpenAI, etc.) generates the response. A connection between Slack and your backend uses either Socket Mode (WebSocket, easy for dev) or HTTP Events (public URL, required for production at scale).

The first time you build this, the surprising part is that 70% of the work is Slack configuration and deployment, not AI. Once you accept that, the project becomes much simpler.

## What You Need Before You Start

You need a Slack workspace where you have admin permission to install apps, an Anthropic or OpenAI API key (about $5 of credit is plenty for development), Python 3.10+ installed locally, and roughly two hours of focused time.

Skip ahead if you've done any of this before. If you haven't, expect the Slack permissions step to take longer than the code.

## Step 1: Create the Slack App

Go to api.slack.com/apps and click Create New App. Pick "From scratch," name it, and select your workspace.

Once created, you need to enable Socket Mode under Settings → Socket Mode. Toggle it on, generate an App-Level Token with `connections:write` scope, and save the `xapp-...` token. This is your Slack App Token.

Under Features → OAuth & Permissions, scroll to Bot Token Scopes and add: `app_mentions:read`, `chat:write`, `chat:write.public`, `channels:history`, `groups:history`, `im:history`, `im:read`, `im:write`, `mpim:history`, `assistant:write` (only if you're building the Assistant variant).

Then scroll up and click Install to Workspace. After approval you get the Bot Token starting with `xoxb-`. Save it.

Under Features → Event Subscriptions, toggle Enable Events on. Subscribe to bot events: `app_mention`, `message.im`, and `message.channels`. Save changes.

Under Features → App Home, enable the "Always Show My Bot as Online" toggle and check "Allow users to send Slash commands and messages from the messages tab."

Slack permission changes require reinstalling the app. Every time you add a scope, click "Reinstall to Workspace" or your bot will silently fail to read events. This single issue is the cause of half the "my bot doesn't respond" Stack Overflow threads.

## Step 2: Fork the Official Template

Don't write from scratch. Slack maintains two official samples:

The first is `slack-samples/bolt-python-ai-chatbot`, a multi-provider chatbot supporting Anthropic and OpenAI with mention-based, DM-based, and slash-command interaction. The second is `slack-samples/bolt-python-assistant-template`, which uses Slack's newer Assistants UI with a side panel and suggested prompts.

For a normal team Slack bot, fork the AI Chatbot template. Clone it locally:

```bash
git clone https://github.com/slack-samples/bolt-python-ai-chatbot.git
cd bolt-python-ai-chatbot
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

The codebase is small enough to read in one sitting. Open `app.py` first — that's the entry point.

## Step 3: Wire In Your Credentials

Create a `.env` file at the project root:

```
SLACK_BOT_TOKEN=xoxb-your-bot-token
SLACK_APP_TOKEN=xapp-your-app-token
ANTHROPIC_API_KEY=sk-ant-your-key
OPENAI_API_KEY=sk-your-key
```

You only need the LLM keys for the providers you plan to use. The template lets users switch between models from inside the app's Home tab.

Run it locally:

```bash
python app.py
```

If you set up Slack correctly, the terminal prints something like "Connected to Slack." Now go to Slack, find your bot in the Apps sidebar, and DM it. It should respond.

If it doesn't respond, the issue is almost always one of three things: a missing scope (re-install the app after adding scopes), the wrong token (check that `SLACK_APP_TOKEN` starts with `xapp-` not `xoxb-`), or the bot wasn't invited to the channel where you @-mentioned it.

## Step 4: Customize the System Prompt and Behavior

Open `app/listeners/messages.py` (or the equivalent in the assistant template). The interesting part is the function that calls the LLM. The default system prompt is generic. Replace it with something specific to your team.

```python
SYSTEM_PROMPT = """You are an internal assistant for [Team Name].
Your job is to answer questions about our product, summarize threads,
and pull information from our docs. Be concise. If you don't know
something, say so — never make up an answer about internal systems."""
```

This single line of customization is what separates "another generic chatbot" from "the bot that actually saves the team time." The base template is just plumbing — your value lives in the system prompt and any tools you bolt on.

For Anthropic Claude responses, the call inside the template looks like:

```python
response = anthropic_client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    system=SYSTEM_PROMPT,
    messages=conversation_history,
)
```

For OpenAI:

```python
response = openai_client.chat.completions.create(
    model="gpt-4.1",
    messages=[{"role": "system", "content": SYSTEM_PROMPT}, *conversation_history],
)
```

Both providers now support streaming, which makes the bot feel real-time instead of frozen-then-paste.

## Step 5: Add Streaming for a Real-Time Feel

A bot that returns one giant block of text after 8 seconds feels broken. A bot that types out the answer word-by-word feels alive. Slack's Bolt for Python framework added a `chat_stream()` utility specifically for this.

Replace your single `chat_postMessage` call with the streaming pattern:

```python
async def respond_streaming(say, conversation_history):
    initial_msg = await say("Thinking...")
    full_response = ""
    
    async with anthropic_client.messages.stream(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        system=SYSTEM_PROMPT,
        messages=conversation_history,
    ) as stream:
        async for chunk in stream.text_stream:
            full_response += chunk
            # Update Slack message every ~30 tokens
            if len(full_response) % 100 == 0:
                await client.chat_update(
                    channel=initial_msg["channel"],
                    ts=initial_msg["ts"],
                    text=full_response,
                )
    
    # Final update with complete response
    await client.chat_update(
        channel=initial_msg["channel"],
        ts=initial_msg["ts"],
        text=full_response,
    )
```

Slack rate-limits message updates, so don't update on every token. Update every 100 characters or every half-second, whichever comes first.

## Step 6: Deploy It Properly

Socket Mode is fine for testing on your laptop. For production, you should switch to HTTP Events with a public URL. The deployment options that work well in 2026:

Render or Railway both deploy a Python web app from a Git repo with one click. Set the environment variables in the dashboard, point Slack's Event Subscription URL at `https://your-app.onrender.com/slack/events`, and you're live. Cost is about $5 to $7 per month for a small bot.

Fly.io and AWS Lambda also work, with Lambda being the most cost-effective at low usage volume but adding cold-start latency that hurts the user experience.

For internal tools that don't need to be always-on, you can keep Socket Mode in production. Run the bot on a small VPS (DigitalOcean droplet at $4/mo or a Raspberry Pi on the office network) and you never have to deal with public URLs, ngrok, or webhook signing.

## Step 7: Add Tools (The Part That Makes It Useful)

A bot that just chats is mildly useful. A bot that can search your docs, query your database, post to your project tracker, or summarize a Slack thread is transformative.

Both Anthropic and OpenAI support function calling (Anthropic calls it Tool Use). The pattern: define a function, describe it in JSON schema, and let the model decide when to call it.

```python
tools = [
    {
        "name": "search_docs",
        "description": "Search internal documentation by keyword",
        "input_schema": {
            "type": "object",
            "properties": {
                "query": {"type": "string"}
            },
            "required": ["query"]
        }
    }
]

response = anthropic_client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    tools=tools,
    messages=conversation_history,
)
```

When Claude returns a tool_use block, you execute the actual function (search your docs, hit your database, whatever) and pass the result back. This is the difference between "AI Slack bot" and "AI agent in Slack" — and it's a 50-line change once you have the chat working.

For a full team-internal use case, consider giving the bot a tool to search your Notion, Confluence, or Google Drive. The minute the bot can answer "what's our refund policy?" or "find me the design doc on Project X," people use it daily. Without that, they use it occasionally.

## Common Failure Modes

I've shipped a half-dozen of these for clients and my own teams. The same things break every time.

The bot doesn't respond when @-mentioned in a public channel. Cause: the bot wasn't invited to the channel. Slack bots only see messages in channels they've been added to.

The bot replies in DMs but not channels. Cause: missing `channels:history` scope or you forgot to subscribe to the `message.channels` event.

The bot replies twice. Cause: you have two instances of `app.py` running (probably one in another terminal you forgot about) or you're handling both `app_mention` and `message` events without deduplication.

The bot is slow. Cause: you're not streaming. Add `chat_stream()` and the perceived latency drops by an order of magnitude.

The bot stops responding after 10 minutes. Cause: Socket Mode connection dropped. Bolt should auto-reconnect, but if you're running on a free Heroku/Render dyno that sleeps, the connection dies. Use a paid tier or switch to HTTP Events.

## What This Costs to Run

A small team bot doing 50 to 200 messages per day:

Hosting on Render or Railway: $5 to $7 per month. LLM calls: depends on model and message length, typically $5 to $30 per month for a small team using Claude Sonnet 4.6 or GPT-4.1. Slack: free for the bot itself, your existing workspace plan applies.

Total: roughly $15 to $40 per month for a useful internal AI Slack bot. Compare that to the per-seat pricing of Slack's official AI features ($10 per user per month) and the math gets compelling fast for any team over 5 people.

## FAQs

## Related Guides

- [How to Build AI-Powered Form Processing](/blog/how-to-build-ai-powered-form-processing)
- [How to Build an AI-Powered Data Dashboard](/blog/how-to-build-an-ai-powered-data-dashboard)
- [How to Automate Competitor Monitoring with AI](/blog/how-to-automate-competitor-monitoring-with-ai)
- [How to Create AI-Powered Membership Sites](/blog/how-to-create-ai-powered-membership-sites)

**Do I need to use Python or can I use Node/TypeScript?**

Bolt is officially supported in Python, JavaScript/TypeScript, and Java. The Python and JS templates are the most up-to-date. If you're already a JS shop, use Bolt for JavaScript — the structure is identical to the Python version. The choice of language matters less than the choice of Bolt vs raw Slack API (always use Bolt).

**Should I use Claude or GPT for the underlying model?**

Both work great. Claude (Sonnet 4.6 or Opus 4.6) is generally better at long, nuanced replies and following detailed system prompts. GPT-4.1 is faster and slightly cheaper at equivalent quality tiers. The official Slack template lets users swap between providers from the App Home tab — give your team both and let them pick.

**How do I keep the bot from leaking sensitive data to the LLM provider?**

Three options. First, host an open-source model (Llama 3.3, Qwen, Mistral) on your own infrastructure and route the bot to it instead of a cloud API. Second, use Anthropic's or OpenAI's enterprise tiers with zero-data-retention contracts. Third, redact sensitive fields (PII, secrets, internal IDs) in your code before sending the prompt. For most internal tools, option two is the right balance.

**Can the bot read message history in a channel?**

Yes, but only after you grant the `channels:history`, `groups:history`, `im:history`, and `mpim:history` scopes and the bot is invited to the channel. The bot can call `conversations.history` to fetch the last N messages, then pass them as context to the LLM. This is how you build "summarize this thread" or "what did the team decide?" features.

**Is it worth building a custom bot when Slack has its own AI feature?**

For most teams, yes. Slack AI is good but generic. A custom bot lets you control the system prompt (so it speaks like your team), connect to your specific tools (your docs, your database, your stack), and pay only for what you use. Slack AI is $10 per user per month. A custom bot serving 20 people typically costs $30 per month total.

**How long does this actually take?**

First-time builders, 4 to 8 hours over a couple sittings. The Slack permissions and deployment steps eat the time, not the code. Once you've shipped one, the next is a 90-minute job. The real time investment is in the system prompt, the tools you wire up, and the iteration to make it actually useful for your team.

## Final Word

The official `bolt-python-ai-chatbot` template will get you to a working bot in under an hour. The next 80% of the value comes from customizing the system prompt, adding tools that hit your team's actual systems, and shipping it where it sleeps inside Slack instead of forcing people to open a separate app.

Don't try to build the perfect bot on day one. Ship a generic one this afternoon, watch how your team uses it for a week, and let the actual usage tell you which features to add.
