CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-slack-bolt

The Bolt Framework for Python - a comprehensive framework for building Slack applications with decorator-based API for handling events, actions, and interactive components

Pending
Overview
Eval results
Files

event-listeners.mddocs/

Event Listeners & Request Handling

Decorator-based event handling for all Slack event types including messages, slash commands, interactive components, shortcuts, and view submissions. Supports event filtering, custom matchers, and argument injection.

Capabilities

Message Events

Listen for message events in channels, direct messages, and threads.

def message(self, keyword=None, *matchers):
    """
    Listen for message events.
    
    Args:
        keyword (str, optional): Text pattern to match in messages
        *matchers: Additional listener matcher instances
        
    Returns:
        Decorator function for message handlers
    """

# Usage examples:
@app.message("hello")              # Match messages containing "hello"
@app.message(re.compile(r"hi"))    # Match with regex
@app.message()                     # Match all messages

def handle_message(message, say, client, logger):
    """
    Message handler function.
    
    Args:
        message (dict): Message event data
        say (callable): Function to send message to same channel
        client (WebClient): Slack API client
        logger (Logger): App logger instance
    """

Slash Commands

Handle slash command invocations.

def command(self, command, *matchers):
    """
    Listen for slash command events.
    
    Args:
        command (str): Command name (e.g., "/weather", "/help")
        *matchers: Additional listener matcher instances
        
    Returns:
        Decorator function for command handlers
    """

# Usage:
@app.command("/weather")
def handle_weather_command(ack, respond, command, logger):
    """
    Command handler function.
    
    Args:
        ack (callable): Function to acknowledge the command (required)
        respond (callable): Function to send response to user
        command (dict): Command payload data
        logger (Logger): App logger instance
    """
    ack()  # Must acknowledge within 3 seconds
    location = command.get('text', 'San Francisco')
    respond(f"Weather in {location}: Sunny ☀️")

Generic Events

Listen for any Slack event type from the Events API.

def event(self, event_type, *matchers):
    """
    Listen for Events API events.
    
    Args:
        event_type (str): Slack event type (e.g., "app_mention", "team_join")
        *matchers: Additional listener matcher instances
        
    Returns:
        Decorator function for event handlers
    """

# Usage examples:
@app.event("app_mention")
@app.event("team_join")
@app.event("reaction_added")

def handle_app_mention(event, say, client):
    """
    Event handler function.
    
    Args:
        event (dict): Event data from Slack
        say (callable): Function to send message to event channel
        client (WebClient): Slack API client
    """

Interactive Component Actions

Handle clicks on buttons, select menus, and other interactive components.

def action(self, action_id, *matchers):
    """
    Listen for interactive component actions.
    
    Args:
        action_id (str): Action ID of the interactive component
        *matchers: Additional listener matcher instances
        
    Returns:
        Decorator function for action handlers
    """

def block_action(self, action_id, *matchers):
    """
    Listen for Block Kit element actions (alias for action).
    
    Args:
        action_id (str): Action ID of the block element
        *matchers: Additional listener matcher instances
    """

def attachment_action(self, callback_id, *matchers):
    """
    Listen for legacy attachment actions.
    
    Args:
        callback_id (str): Callback ID of the attachment action
        *matchers: Additional listener matcher instances
    """

# Usage:
@app.action("approve_button")
@app.action("user_select")
@app.block_action("priority_select")

def handle_button_click(ack, body, respond, client):
    """
    Action handler function.
    
    Args:
        ack (callable): Function to acknowledge the action (required)
        body (dict): Full request body
        respond (callable): Function to update/respond to the interaction
        client (WebClient): Slack API client
    """
    ack()  # Must acknowledge within 3 seconds

Shortcuts

Handle global shortcuts and message shortcuts.

def shortcut(self, callback_id, *matchers):
    """
    Listen for shortcuts (both global and message shortcuts).
    
    Args:
        callback_id (str): Callback ID of the shortcut
        *matchers: Additional listener matcher instances
    """

def global_shortcut(self, callback_id, *matchers):
    """
    Listen specifically for global shortcuts.
    
    Args:
        callback_id (str): Callback ID of the global shortcut
        *matchers: Additional listener matcher instances
    """

def message_shortcut(self, callback_id, *matchers):
    """
    Listen specifically for message shortcuts.
    
    Args:
        callback_id (str): Callback ID of the message shortcut
        *matchers: Additional listener matcher instances
    """

# Usage:
@app.global_shortcut("create_task")
@app.message_shortcut("save_message")

def handle_shortcut(ack, shortcut, client):
    """
    Shortcut handler function.
    
    Args:
        ack (callable): Function to acknowledge the shortcut
        shortcut (dict): Shortcut payload data
        client (WebClient): Slack API client
    """

Modal Views

Handle modal view submissions, closures, and interactions.

def view(self, callback_id, *matchers):
    """
    Listen for view events (submissions and closures).
    
    Args:
        callback_id (str): Callback ID of the view
        *matchers: Additional listener matcher instances
    """

def view_submission(self, callback_id, *matchers):
    """
    Listen specifically for view submissions.
    
    Args:
        callback_id (str): Callback ID of the view
        *matchers: Additional listener matcher instances
    """

def view_closed(self, callback_id, *matchers):
    """
    Listen specifically for view closures.
    
    Args:
        callback_id (str): Callback ID of the view
        *matchers: Additional listener matcher instances
    """

# Usage:
@app.view_submission("task_modal")
@app.view_closed("survey_modal")

def handle_view_submission(ack, body, view, client):
    """
    View handler function.
    
    Args:
        ack (callable): Function to acknowledge the submission
        body (dict): Full request body
        view (dict): View payload data
        client (WebClient): Slack API client
    """

Options Loading

Handle dynamic option loading for select menus.

def options(self, action_id, *matchers):
    """
    Listen for options loading requests.
    
    Args:
        action_id (str): Action ID of the select menu
        *matchers: Additional listener matcher instances
    """

def block_suggestion(self, action_id, *matchers):
    """
    Listen for block element suggestions (alias for options).
    
    Args:
        action_id (str): Action ID of the block element
        *matchers: Additional listener matcher instances
    """

# Usage:
@app.options("user_select")
def load_user_options(ack, options, client):
    """
    Options handler function.
    
    Args:
        ack (callable): Function to acknowledge with options
        options (dict): Options request data
        client (WebClient): Slack API client
    """
    # Return options to populate the select menu
    ack(options=[
        {"text": {"type": "plain_text", "text": "Option 1"}, "value": "option1"},
        {"text": {"type": "plain_text", "text": "Option 2"}, "value": "option2"}
    ])

Legacy Dialog Support

Handle legacy dialog interactions (deprecated, use modals instead).

def dialog_submission(self, callback_id, *matchers):
    """
    Listen for dialog submissions (legacy).
    
    Args:
        callback_id (str): Callback ID of the dialog
        *matchers: Additional listener matcher instances
    """

def dialog_cancellation(self, callback_id, *matchers):
    """
    Listen for dialog cancellations (legacy).
    
    Args:
        callback_id (str): Callback ID of the dialog
        *matchers: Additional listener matcher instances
    """

def dialog_suggestion(self, action_id, *matchers):
    """
    Listen for dialog option suggestions (legacy).
    
    Args:
        action_id (str): Action ID of the dialog element
        *matchers: Additional listener matcher instances
    """

Custom Functions

Handle custom function calls (Slack platform functions).

def function(self, callback_id, *matchers):
    """
    Listen for custom function calls.
    
    Args:
        callback_id (str): Function callback ID
        *matchers: Additional listener matcher instances
    """

# Usage:
@app.function("process_data")
def handle_function_call(ack, inputs, complete, fail, logger):
    """
    Function handler.
    
    Args:
        ack (callable): Function to acknowledge the call
        inputs (dict): Function input parameters
        complete (callable): Function to mark completion with outputs
        fail (callable): Function to mark failure with error
        logger (Logger): App logger instance
    """

Workflow Steps

Handle workflow step interactions.

def step(self, step):
    """
    Add a workflow step to the app.
    
    Args:
        step: WorkflowStep instance
    """

# Usage with WorkflowStep:
from slack_bolt.workflows.step import WorkflowStep

def edit_step(ack, step, configure):
    ack()
    configure(blocks=[...])  # Configure step UI

def execute_step(step, complete, fail):
    # Step execution logic
    complete(outputs={"result": "success"})

ws = WorkflowStep(
    callback_id="my_step",
    edit=edit_step,
    save=lambda ack, view: ack(),
    execute=execute_step
)

app.step(ws)

Listener Matchers

Built-in Matchers

Custom matching logic for fine-grained event filtering:

from slack_bolt.listener_matcher import CustomListenerMatcher

def custom_matcher(body):
    """
    Custom matcher function.
    
    Args:
        body (dict): Request body
        
    Returns:
        bool: True if listener should handle this request
    """
    return body.get("event", {}).get("channel_type") == "im"

# Usage:
@app.message(CustomListenerMatcher(custom_matcher))
def handle_dm_only(message, say):
    say("This only responds to direct messages!")

Combining Matchers

Combine multiple matchers for complex filtering:

@app.message("hello", CustomListenerMatcher(lambda body: not body.get("event", {}).get("bot_id")))
def handle_human_hello(message, say):
    say("Hello, human!")

Argument Injection

Available Arguments

All listener functions support argument injection with these available parameters:

class Args:
    """Available argument names for dependency injection in listeners."""
    
    # Core objects
    logger: Logger
    client: WebClient
    context: BoltContext
    body: dict
    payload: dict
    
    # Utility functions
    ack: Ack
    say: Say
    respond: Respond
    complete: Complete
    fail: Fail
    
    # Event-specific data
    event: dict
    message: dict
    command: dict
    action: dict
    shortcut: dict
    view: dict
    options: dict
    
    # Request metadata
    request: BoltRequest
    response: BoltResponse
    
    # Multi-workspace data
    enterprise_id: str
    team_id: str
    user_id: str
    channel_id: str
    
    # AI Assistant utilities
    set_status: SetStatus
    set_title: SetTitle
    set_suggested_prompts: SetSuggestedPrompts
    save_thread_context: SaveThreadContext

Function Signature Examples

Listeners can use any combination of available arguments:

# Minimal signature
@app.message("hello")
def simple_handler(say):
    say("Hello!")

# Full signature with all common arguments
@app.command("/complex")
def complex_handler(ack, body, command, respond, client, logger, context):
    ack()
    logger.info(f"Command received: {command}")
    # Complex logic here...

# Event-specific arguments
@app.event("app_mention")
def mention_handler(event, say, user_id, channel_id):
    say(f"Thanks for the mention in <#{channel_id}>, <@{user_id}>!")

Usage Examples

Message Pattern Matching

import re

# Exact text match
@app.message("help")
def show_help(say):
    say("Here's how to use this bot...")

# Regex pattern
@app.message(re.compile(r"weather in (\w+)"))
def weather_query(message, say):
    city = re.search(r"weather in (\w+)", message['text']).group(1)
    say(f"The weather in {city} is sunny!")

# Multiple patterns
@app.message("hello")
@app.message("hi")
@app.message("hey")
def greet_user(message, say):
    say(f"Hello <@{message['user']}>!")

Command with Sub-commands

@app.command("/todo")
def todo_command(ack, respond, command):
    ack()
    
    text = command.get('text', '').strip()
    parts = text.split(' ', 1)
    subcommand = parts[0].lower() if parts else 'help'
    
    if subcommand == 'add':
        task = parts[1] if len(parts) > 1 else ''
        respond(f"Added task: {task}")
    elif subcommand == 'list':
        respond("Here are your tasks: ...")
    else:
        respond("Usage: /todo [add|list] [task]")

Modal Workflow

@app.action("open_modal")
def open_modal(ack, body, client):
    ack()
    
    client.views_open(
        trigger_id=body["trigger_id"],
        view={
            "type": "modal",
            "callback_id": "task_modal",
            "title": {"type": "plain_text", "text": "Create Task"},
            "blocks": [
                {
                    "type": "input",
                    "block_id": "task_input",
                    "element": {
                        "type": "plain_text_input",
                        "action_id": "task_text"
                    },
                    "label": {"type": "plain_text", "text": "Task Description"}
                }
            ],
            "submit": {"type": "plain_text", "text": "Create"}
        }
    )

@app.view_submission("task_modal")
def handle_task_submission(ack, body, view, logger):
    # Extract form data
    task_text = view["state"]["values"]["task_input"]["task_text"]["value"]
    
    # Process the task...
    logger.info(f"Creating task: {task_text}")
    
    # Acknowledge and close modal
    ack()

Related Topics

  • Context Objects & Utilities - Details on say, respond, ack, and other utilities
  • OAuth & Multi-Workspace Installation - Multi-workspace event handling patterns

Install with Tessl CLI

npx tessl i tessl/pypi-slack-bolt

docs

app-configuration.md

context-and-utilities.md

event-listeners.md

framework-integration.md

index.md

oauth-and-installation.md

tile.json