How to Build an Ollama Slack Bot: Local AI in Your Workspace

Connecting Ollama to Slack gives your team an AI assistant inside the tool you already use — no switching to a browser tab, no sharing API keys, no data leaving your infrastructure. When someone messages your bot, their message goes to your server, Ollama generates a response, and the reply appears in Slack. The architecture is simple, the setup takes about an hour, and the result is a private team AI assistant that costs nothing per query.

What You Need

To build this, you need: a Slack workspace where you can create apps (free or paid), a server where Ollama is running and accessible (a machine on your local network with a tunnel, or a VPS), and Python with a few libraries. The Slack bot receives messages via Socket Mode, calls Ollama, and posts the response back. You don’t need Slack’s paid plan — the free Slack workspace supports custom apps.

Creating the Slack App

Go to api.slack.com/apps and click “Create New App” then “From scratch”. Name your bot (e.g. “Ollama Assistant”) and select your workspace. Once created, navigate to OAuth and Permissions and add bot token scopes: app_mentions:read, chat:write, channels:history, im:history, and im:write. Install to Workspace and copy the Bot User OAuth Token (starts with xoxb-). From Basic Information, copy the Signing Secret. Enable Socket Mode and generate an App-Level Token (starts with xapp-). Finally, enable Event Subscriptions and subscribe to the app_mention and message.im bot events.

Building the Bot

pip install slack-bolt ollama python-dotenv

Create the main bot file:

import os
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
import ollama
from dotenv import load_dotenv

load_dotenv()

app = App(token=os.environ["SLACK_BOT_TOKEN"])
MODEL = os.environ.get("OLLAMA_MODEL", "llama3.2")

def get_response(prompt: str) -> str:
    response = ollama.chat(
        model=MODEL,
        messages=[
            {
                "role": "system",
                "content": "You are a helpful assistant in a Slack workspace. Be concise. Use Slack formatting where appropriate."
            },
            {"role": "user", "content": prompt}
        ]
    )
    return response["message"]["content"]

@app.event("app_mention")
def handle_mention(event, say):
    text = event.get("text", "")
    # Strip the bot mention token
    clean = " ".join(text.split()[1:]).strip()
    if not clean:
        say("Hi! Ask me anything.")
        return
    say(get_response(clean))

@app.event("message")
def handle_dm(event, say):
    if event.get("channel_type") != "im":
        return
    text = event.get("text", "").strip()
    if text:
        say(get_response(text))

if __name__ == "__main__":
    SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start()

Create a .env file with your tokens:

SLACK_BOT_TOKEN=xoxb-your-bot-token
SLACK_APP_TOKEN=xapp-your-app-token
OLLAMA_MODEL=llama3.2

Run with: python bot.py. In Slack, invite your bot to a channel with /invite and then @mention it with a question. Responses appear within a few seconds depending on model and hardware.

Adding Conversation Memory

The basic bot above has no memory — each message is treated as a fresh conversation. For a more natural experience where the bot remembers what was said earlier in a thread, maintain conversation history per Slack thread:

from collections import defaultdict

# Store conversation history per thread
thread_history = defaultdict(list)
SYSTEM_MSG = {"role": "system", "content": "You are a helpful Slack assistant. Be concise and use Slack formatting where appropriate."}

def get_response_with_memory(prompt: str, thread_ts: str) -> str:
    history = thread_history[thread_ts]
    history.append({"role": "user", "content": prompt})

    # Keep last 10 exchanges to manage context length
    recent = history[-20:]

    response = ollama.chat(
        model=MODEL,
        messages=[SYSTEM_MSG] + recent
    )
    reply = response["message"]["content"]
    history.append({"role": "assistant", "content": reply})
    return reply

@app.event("app_mention")
def handle_mention(event, say):
    text = " ".join(event.get("text", "").split()[1:]).strip()
    thread_ts = event.get("thread_ts") or event.get("ts")
    if text:
        say(get_response_with_memory(text, thread_ts), thread_ts=thread_ts)

Replying with thread_ts=thread_ts keeps responses in the Slack thread, and using the thread timestamp as the conversation key means each Slack thread has its own conversation history. The 20-message cap (10 exchanges) prevents the context window from growing indefinitely.

Figure 1 — Ollama Slack Bot Architecture

Slack User @mentions bot or sends DM Slack API Socket Mode Event delivery Response posting Python Bot slack-bolt Event handlers Thread memory Ollama Local inference All LLM inference runs locally — only Slack API calls leave your server

Deploying the Bot

For the bot to be reachable by Slack, it needs to run on a machine that’s on and connected. Three practical deployment options:

Always-on development machine: The simplest approach — run the bot on a machine that’s always powered on (a home server, NAS, or desktop you don’t turn off). The bot uses Socket Mode so it doesn’t need a public IP or port forwarding. It initiates an outbound WebSocket connection to Slack’s servers, which Slack uses to deliver events. This works behind NAT and firewalls with no configuration.

VPS with Ollama: Deploy both the bot and Ollama on a cloud VM. The bot connects to localhost:11434 directly — no tunnel needed. A Hetzner CX22 (2 vCPU, 4GB RAM) is sufficient for the bot itself; you’ll need a GPU instance for fast inference, which costs more but gives you proper response times. This is the right architecture for a team-facing bot that needs to be reliably available.

Systemd service (Linux): On any Linux machine, create a systemd service so the bot starts automatically:

# /etc/systemd/system/ollama-slackbot.service
[Unit]
Description=Ollama Slack Bot
After=network.target

[Service]
Type=simple
User=youruser
WorkingDirectory=/home/youruser/ollama-slackbot
EnvironmentFile=/home/youruser/ollama-slackbot/.env
ExecStart=/usr/bin/python3 bot.py
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl enable ollama-slackbot
sudo systemctl start ollama-slackbot

Adding Slash Commands

Slash commands let users trigger specific bot functions with predictable syntax. In your Slack app settings, navigate to Slash Commands and create commands like /ask, /summarise, or /model (to switch the active model). For HTTP-based slash commands you need a public URL — either your VPS or a tunnel. For development, Socket Mode slash commands are simpler:

@app.command("/ask")
def handle_ask(ack, respond, command):
    ack()  # acknowledge immediately (required within 3 seconds)
    prompt = command.get("text", "").strip()
    if not prompt:
        respond("Usage: /ask [your question]")
        return
    response = get_response(prompt)
    respond(response)

@app.command("/model")
def handle_model(ack, respond, command):
    ack()
    global MODEL
    new_model = command.get("text", "").strip()
    if new_model:
        MODEL = new_model
        respond(f"Switched to model: {MODEL}")
    else:
        respond(f"Current model: {MODEL}")

Register these commands in your Slack app settings under “Slash Commands” with the command name and a description. They’ll appear in Slack’s autocomplete when users type /.

Figure 2 — Practical Slack Bot Use Cases with Ollama

Bot capability Implementation Ollama model General Q&A assistant@mention or DM handlerllama3.1:8b Code review helper/review slash commandqwen2.5-coder:7b Meeting summariserPost transcript, bot repliesmistral-small3 Internal docs searchRAG over uploaded docsnomic-embed-text + llama3.1

Rate Limiting and Error Handling

A shared team bot needs rate limiting to prevent one person from overwhelming your Ollama instance with a burst of requests. The simplest approach is a per-user cooldown — track the last request time per Slack user ID and decline requests within the cooldown window. Ollama itself will queue concurrent requests, but queuing too many causes timeouts. For the error handling: wrap every Ollama call in a try-except, and if inference fails (timeout, OOM, model not loaded), send an informative error message back to Slack rather than letting the bot go silent. Also acknowledge Slack events within 3 seconds — the Slack API will retry unacknowledged events, creating duplicate messages. With slack-bolt, the ack() call in event handlers and slash commands handles this — ensure it’s called before any slow operations. The combination of immediate acknowledgement, graceful error handling, and per-user rate limiting makes the difference between a bot that feels reliable and one that confuses users with silence or duplicate responses when under load.

Privacy and Data Considerations

One of the main reasons to build an Ollama-backed Slack bot rather than using a commercial AI integration is that your conversation data stays on your server rather than being sent to OpenAI, Anthropic, or another cloud provider. Every message your users send to the bot travels to Slack’s servers (as all Slack messages do) and then to your bot server — but the actual LLM inference happens locally, and no user query content reaches an external AI API. For teams handling sensitive business information, client data, or confidential internal discussions, this is a meaningful privacy advantage. Document this clearly when you deploy the bot to your team: “Your questions go to our server where a local AI model answers them — they don’t go to OpenAI or any external AI service.” This transparency helps users trust the tool and use it appropriately for sensitive questions they might otherwise avoid asking a cloud-backed assistant.

Extending the Bot: Adding Document Context

Once the basic mention-and-respond bot is working, the most impactful upgrade is adding document context — giving the bot access to your team’s internal documentation so it can answer questions grounded in your actual knowledge base rather than just its training data. The simplest approach: preload a set of documents at bot startup (your team wiki, README files, product documentation), embed them with nomic-embed-text via Ollama, store in an in-memory vector store, and modify your response function to retrieve relevant chunks before calling the main LLM. A user asking “what’s our process for deploying to production?” gets an answer based on your actual runbook rather than a generic description of deployment processes. The implementation combines the bot code above with a LlamaIndex or ChromaDB retrieval step — about 30 additional lines that transform the bot from a generic assistant into a team-specific knowledge tool. This is where local AI bots provide their clearest value over cloud alternatives: your private internal documentation stays private, the retrieval and generation both happen on your infrastructure, and the bot becomes genuinely useful for team-specific questions that a generic cloud assistant can’t answer well.

The Path From Prototype to Production

Getting a basic Ollama Slack bot working is a satisfying afternoon project. Making it reliable enough for daily team use requires a few more steps: persistent conversation history (use SQLite or Redis instead of in-memory dicts so history survives bot restarts), structured logging (write each interaction to a file or database for debugging and usage analysis), a health check endpoint (so you know when the bot is down without waiting for someone to report it), and a simple admin command for restarting or switching models without SSH access. None of these are complex, but together they transform a prototype into infrastructure your team actually depends on. The most important step is documenting what your bot can and can’t do — set appropriate expectations with your team about response speed, knowledge limitations, and when to use the bot versus searching documentation directly. A well-documented, reliably deployed Ollama Slack bot becomes one of those quiet productivity wins that team members start relying on without thinking about it — which is exactly the right outcome for internal AI tooling.

Choosing a Model for Your Slack Bot

The right Ollama model for a Slack bot depends on what your team will use it for and how fast they expect responses. For a general-purpose assistant that answers varied questions across a team, Llama 3.1 8B or Qwen 2.5 7B hit the right balance — fast enough for comfortable Slack use (responses in 3–10 seconds on a mid-range GPU), capable enough to handle most business questions well. If your team’s primary use is coding questions and code review, Qwen 2.5 Coder 7B is a better choice than a general model. If speed is critical — users expect near-instant responses and slow responses lead to abandonment — consider Llama 3.2 3B, which generates 2–3x faster than the 8B at some quality cost. For teams with capable server hardware (24GB+ VRAM), Mistral Small 3 24B or Qwen 2.5 14B provide noticeably better reasoning and a more impressive first impression for users who are evaluating whether to trust the bot. The practical recommendation: start with Llama 3.1 8B, gather feedback from your team for a few weeks, and upgrade the model if users consistently find responses inadequate. The model is a single configuration change — the bot code doesn’t need to change when you switch models via the environment variable.

Leave a Comment