Skip to main content
The Slack interface connects your agent to a Slack workspace. It supports Socket Mode (for development) and HTTP Events API (for production), handles DMs and channel @mentions, threads conversations automatically, and provides rich Block Kit interactions — slash commands, buttons, modals, shortcuts, and reactions.

Setup

1. Create a Slack App

  1. Go to api.slack.com/apps and click Create New App
  2. Choose From scratch, name your app, and select a workspace

2. Enable Socket Mode

  1. Go to Settings → Socket Mode and enable it
  2. Generate an App-Level Token with the connections:write scope (starts with xapp-)

3. Add Bot Token Scopes

Go to OAuth & Permissions → Scopes → Bot Token Scopes and add:
ScopePurpose
chat:writeSend messages
app_mentions:readRespond to @mentions
channels:historyRead channel messages
im:historyRead DMs
files:readDownload shared files
files:writeUpload files
users:readResolve user info
reactions:writeAdd typing/done reactions

4. Subscribe to Events

Go to Event Subscriptions → Subscribe to bot events and add:
  • message.im — Direct messages
  • app_mention — @mentions in channels
  • message.channels — Channel messages (if you want thread replies)

5. Install and Run

Install the app to your workspace, then copy the Bot User OAuth Token (starts with xoxb-).
export SLACK_BOT_TOKEN="xoxb-..."
export SLACK_APP_TOKEN="xapp-..."
import asyncio
import os
from definable.agent import Agent
from definable.agent.interface import SlackInterface

agent = Agent(
    model="openai/gpt-4o",
    instructions="You are a helpful Slack assistant.",
)

interface = SlackInterface(
    agent=agent,
    bot_token=os.environ["SLACK_BOT_TOKEN"],
    app_token=os.environ["SLACK_APP_TOKEN"],
)

asyncio.run(interface.serve_forever())
Your bot is now live. Mention it in a channel or send a DM to start chatting.

Installation

pip install 'definable[slack]'
This installs slack-bolt and aiohttp as dependencies.

SlackInterface Parameters

Authentication

bot_token
str
required
Slack Bot User OAuth Token (xoxb-...).
app_token
str
Slack App-Level Token (xapp-...). Required when mode="socket".
signing_secret
str
Signing secret for request verification. Required when mode="http".

Receiver Mode

mode
str
default:"socket"
How the bot receives events. "socket" for development (WebSocket, no public URL needed), "http" for production (Events API, requires public URL).

HTTP Events API Settings

events_path
str
default:"/slack/events"
URL path for the Events API endpoint (HTTP mode only).
interactions_path
str
default:"/slack/interactions"
URL path for interactive components (HTTP mode only).

Channel Behavior

respond_to_mentions
bool
default:true
Respond when @mentioned in channels.
respond_to_dms
bool
default:true
Respond to direct messages.
respond_to_thread_replies
bool
default:true
Respond when a user replies in a thread the bot started.
thread_replies_in_channel
bool
default:true
Always reply in a thread when in channels (keeps channels tidy).
thread_replies_in_dm
bool
default:false
Reply in threads in DMs. When false, replies appear as top-level DM messages.

Typing Indicators

typing_reaction
str
default:"hourglass_flowing_sand"
Emoji reaction added while the agent processes. Set to "" to disable.
done_reaction
str
default:""
Emoji reaction added when the agent finishes. Set to "" to disable.

Text Formatting

convert_markdown
bool
default:true
Automatically convert standard Markdown to Slack mrkdwn format (**bold***bold*, [text](url)<url|text>, etc.).
max_message_length
int
default:40000
Maximum message length. Messages exceeding this are split at paragraph/sentence boundaries.

Access Control

allowed_user_ids
List[str]
Only accept messages from these Slack user IDs. All users allowed if not set.
allowed_channel_ids
List[str]
Only accept messages from these channel IDs. All channels allowed if not set.

Rate Limiting & Timeouts

max_retries
int
default:3
Maximum retries for Slack API calls on rate limit (429) responses.
connect_timeout
float
HTTP connection timeout in seconds.
request_timeout
float
HTTP request timeout in seconds.

Slash Commands

slash_commands
Dict[str, str]
Slash commands to register. Maps command name to description. Commands are routed through the agent pipeline by default.
route_commands_to_agent
bool
default:true
Whether slash commands are sent to the agent. When false, commands only dispatch to registered callbacks.

Socket Mode (Development)

Socket Mode uses a WebSocket connection — no public URL, no HTTPS, no firewall configuration. Ideal for development.
interface = SlackInterface(
    agent=agent,
    bot_token="xoxb-...",
    app_token="xapp-...",   # required for socket mode
    mode="socket",           # default
)
Socket Mode works behind NATs and firewalls with zero networking setup. Use it for local development and testing.

HTTP Events API (Production)

For production, use HTTP mode with Slack’s Events API. Events are pushed to your server over HTTPS.
interface = SlackInterface(
    agent=agent,
    bot_token="xoxb-...",
    signing_secret="your-signing-secret",  # required for HTTP mode
    mode="http",
    events_path="/slack/events",
    interactions_path="/slack/interactions",
)
Requirements:
  • A publicly accessible HTTPS URL
  • The signing secret from your app’s Basic Information page
  • Event subscriptions configured to point at your URL
The signing_secret is required for HTTP mode. It verifies that incoming requests are genuinely from Slack, preventing unauthorized access.

Threading

The Slack interface automatically manages thread context:
  • Channel messages: Replies always go to a thread (when thread_replies_in_channel=True)
  • Thread replies: When a user replies in a bot thread, the conversation continues in that thread with full history
  • DMs: By default, replies appear as top-level messages (set thread_replies_in_dm=True for threaded DMs)
Each thread maintains its own session with conversation history, so multiple threads can run independent conversations simultaneously.

Media Support

The interface handles Slack file uploads automatically:
Slack TypeConverted ToNotes
Images (png, jpg, gif)ImageDownloaded and passed to the agent
Audio filesAudioIncludes file metadata
DocumentsFileIncludes filename and mime type
Files shared in messages are downloaded from Slack and passed to the agent’s images, audio, and files parameters.

Block Kit Interactions

Slash Commands

Register slash commands that route through the agent:
interface = SlackInterface(
    agent=agent,
    bot_token="xoxb-...",
    app_token="xapp-...",
    slash_commands={
        "/ask": "Ask the AI assistant a question",
        "/summarize": "Summarize the current conversation",
    },
)
You must also register slash commands in your Slack app settings at Features → Slash Commands. The slash_commands parameter tells the interface to listen for them.

Custom Command Handlers

Handle commands with custom logic instead of (or alongside) the agent:
async def handle_status(ack, body, client):
    await ack()
    await client.chat_postMessage(
        channel=body["channel_id"],
        text="All systems operational.",
    )

interface.on_command("/status", handle_status)

Buttons and Actions

Register handlers for interactive components:
from definable.agent.interface.slack.formatter import (
    section_block, actions_block, button_element,
)

# Send a message with buttons
await interface.send_blocks(
    channel="C0123456789",
    blocks=[
        section_block("Would you like to proceed?"),
        actions_block([
            button_element("Yes", "approve_action", style="primary"),
            button_element("No", "reject_action", style="danger"),
        ]),
    ],
)

# Handle button clicks
async def on_approve(ack, body, client):
    await ack()
    await client.chat_postMessage(
        channel=body["channel"]["id"],
        text="Approved!",
    )

interface.on_action("approve_action", on_approve)

Modals

Open and handle modal dialogs:
from definable.agent.interface.slack.formatter import (
    modal_view, input_block, plain_text_input,
)

# Open a modal from a command or action
async def open_feedback_modal(ack, body, client):
    await ack()
    await interface.open_modal(
        body["trigger_id"],
        modal_view(
            "Feedback",
            blocks=[
                input_block("Your feedback", plain_text_input("feedback_input", multiline=True)),
            ],
            callback_id="feedback_submitted",
            submit="Submit",
        ),
    )

# Handle modal submission
async def on_feedback(ack, body, client):
    await ack()
    values = body["view"]["state"]["values"]
    # Process the submitted feedback...

interface.on_view("feedback_submitted", on_feedback)

Shortcuts

Handle global and message shortcuts:
async def on_summarize_shortcut(ack, body, client):
    await ack()
    # Open a modal or process the shortcut...

interface.on_shortcut("summarize_message", on_summarize_shortcut)

Reactions

React to emoji reactions:
async def on_thumbs_up(event):
    print(f"User {event['user']} reacted with :+1: on {event['item']['ts']}")

interface.on_reaction_added(on_thumbs_up)

App Home Tab

Publish a custom App Home tab:
from definable.agent.interface.slack.formatter import (
    home_tab_view, header_block, section_block, divider_block,
)

async def on_home(event):
    await interface.publish_home(
        event["user"],
        home_tab_view([
            header_block("Welcome to AI Assistant"),
            divider_block(),
            section_block("Send me a DM or @mention me in a channel to get started."),
        ]),
    )

interface.on_home_opened(on_home)

Block Kit Builders

The formatter module provides pure-dict builders for Slack’s Block Kit — no SDK dependency needed:
from definable.agent.interface.slack.formatter import (
    # Blocks
    header_block, section_block, divider_block,
    actions_block, context_block, image_block, input_block,
    # Elements
    button_element, static_select_element, plain_text_input, option_object,
    # Text objects
    plain_text, mrkdwn_text,
    # Views
    modal_view, home_tab_view,
)

Additional API Methods

The interface provides methods beyond basic messaging:
MethodDescription
update_message(channel, ts, ...)Edit an existing message
send_ephemeral(channel, user, text)Send a message only visible to one user
send_blocks(channel, blocks, ...)Send rich Block Kit messages
open_modal(trigger_id, view)Open a modal dialog
update_modal(view_id, view)Update an open modal
push_modal(trigger_id, view)Push a new view onto the modal stack
publish_home(user_id, view)Publish an App Home tab
schedule_message(channel, text, post_at)Schedule a message for later
delete_scheduled_message(channel, id)Cancel a scheduled message
delete_message(channel, ts)Delete a message
get_permalink(channel, ts)Get a permanent link to a message
set_topic(channel, topic)Set a channel’s topic
pin_message(channel, ts)Pin a message
unpin_message(channel, ts)Unpin a message

Access Control

Restrict who can interact with the bot:
interface = SlackInterface(
    agent=agent,
    bot_token="xoxb-...",
    app_token="xapp-...",
    allowed_user_ids=["U0123456789", "U9876543210"],   # Only these users
    allowed_channel_ids=["C0123456789"],                 # Only these channels
)
Messages from unauthorized users or channels are silently ignored.

Agent with Tools and Memory

import asyncio
import os
from definable.agent import Agent
from definable.agent.interface import SlackInterface
from definable.memory import Memory, SQLiteStore
from definable.tool.decorator import tool

@tool
def search_docs(query: str) -> str:
    """Search the documentation for an answer."""
    return f"Found results for: {query}"

@tool
def get_weather(city: str) -> str:
    """Get the current weather for a city."""
    return f"Sunny, 24°C in {city}"

agent = Agent(
    model="openai/gpt-4o",
    instructions="You are a helpful Slack assistant with search and weather tools.",
    tools=[search_docs, get_weather],
    memory=Memory(store=SQLiteStore("./slack_memory.db")),
)

interface = SlackInterface(
    agent=agent,
    bot_token=os.environ["SLACK_BOT_TOKEN"],
    app_token=os.environ["SLACK_APP_TOKEN"],
    done_reaction="white_check_mark",
)

asyncio.run(interface.serve_forever())

Error Handling

The Slack interface maps API errors to the standard exception hierarchy:
ScenarioExceptionRecovery
Invalid bot tokenInterfaceAuthenticationErrorCheck token validity
Rate limited (429)InterfaceRateLimitErrorAuto-retried up to max_retries
Invalid channel/userInterfaceMessageErrorCheck IDs and permissions
Network failureInterfaceConnectionErrorAuto-reconnect (Socket Mode)
When an error occurs during message processing, the configured error_message is sent to the user, and all on_error hooks are invoked.