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

context-and-utilities.mddocs/

Context Objects & Utilities

Rich context objects providing utilities for acknowledging requests, sending messages, making API calls, and accessing request data. Includes the argument injection system for clean listener functions.

Capabilities

Core Context Object

The BoltContext provides access to all utilities and request data within listeners.

class BoltContext:
    """
    Context object containing utilities and request data.
    
    Properties:
        client (WebClient): Slack API client instance
        ack (Ack): Function to acknowledge requests
        say (Say): Function to send messages to channel
        respond (Respond): Function to respond to interactions
        complete (Complete): Function to complete workflow steps
        fail (Fail): Function to fail workflow steps
        logger (Logger): App logger instance
        listener_runner: Thread listener runner
        
        # AI Assistant utilities
        set_status (SetStatus): Set assistant conversation status
        set_title (SetTitle): Set assistant conversation title
        set_suggested_prompts (SetSuggestedPrompts): Set suggested prompts
        save_thread_context (SaveThreadContext): Save conversation context
        get_thread_context: Get conversation context (async only)
    """
    
    def to_copyable(self):
        """
        Create a copyable version of the context.
        
        Returns:
            BoltContext: Copyable context instance
        """

Request and Response Objects

Core objects representing incoming requests and outgoing responses.

class BoltRequest:
    """
    Incoming request wrapper.
    
    Properties:
        raw_body (str): Raw request body string
        query (dict): Query parameters
        headers (dict): Request headers
        content_type (str): HTTP content type
        body (dict): Parsed request body
        context (BoltContext): Associated context
        lazy_only (bool): Lazy execution mode flag
        lazy_function_name (str): Lazy function name
        mode (str): Request mode ("http" or "socket_mode")
    """
    
    def to_copyable(self):
        """Create copyable request instance."""

class BoltResponse:
    """
    Outgoing response object.
    
    Properties:
        status (int): HTTP status code
        headers (dict): Response headers
        body (str): Response body
    """

Acknowledgment Functions

Functions for acknowledging Slack interactions (required within 3 seconds).

class Ack:
    """Acknowledge function for responding to Slack interactions."""
    
    def __call__(self, response=None):
        """
        Acknowledge a Slack interaction.
        
        Args:
            response (dict, optional): Optional response payload
                - For commands: Response text or response object
                - For actions: Updated message or modal
                - For view submissions: Response action or errors
        """

# Usage examples:
def handle_command(ack, respond, command):
    ack()  # Simple acknowledgment
    respond("Processing your request...")

def handle_action(ack, body):
    ack({"text": "Button clicked!"})  # Acknowledge with response

def handle_view_submission(ack, view):
    # Acknowledge with validation errors
    if not view["state"]["values"]["field"]["value"]:
        ack({
            "response_action": "errors",
            "errors": {
                "field": "This field is required"
            }
        })
    else:
        ack()  # Success acknowledgment

Say Function

Send messages to the channel where an event occurred.

class Say:
    """Function to send messages to the event channel."""
    
    def __call__(
        self,
        text: str = None,
        blocks: list = None,
        attachments: list = None,
        thread_ts: str = None,
        reply_broadcast: bool = None,
        unfurl_links: bool = None,
        unfurl_media: bool = None,
        **kwargs
    ):
        """
        Send a message to the channel.
        
        Args:
            text (str): Message text (required if blocks not provided)
            blocks (list): Block Kit blocks
            attachments (list): Message attachments (legacy)
            thread_ts (str): Thread timestamp to reply in thread
            reply_broadcast (bool): Broadcast thread reply to channel
            unfurl_links (bool): Enable link unfurling
            unfurl_media (bool): Enable media unfurling
            **kwargs: Additional chat.postMessage parameters
            
        Returns:
            dict: API response with message data
        """

# Usage examples:
def handle_message(say):
    say("Hello!")  # Simple text message
    
    say(
        text="Fallback text",
        blocks=[
            {
                "type": "section",
                "text": {"type": "mrkdwn", "text": "*Bold text* in Block Kit"}
            }
        ]
    )  # Rich Block Kit message
    
    say("Thread reply", thread_ts=message["ts"])  # Reply in thread

Respond Function

Respond to interactions using response URLs (commands, actions, shortcuts).

class Respond:
    """Function to respond to interactions using response URLs."""
    
    def __call__(
        self,
        text: str = None,
        blocks: list = None,
        attachments: list = None,
        response_type: str = "ephemeral",
        replace_original: bool = None,
        delete_original: bool = None,
        unfurl_links: bool = None,
        unfurl_media: bool = None,
        **kwargs
    ):
        """
        Respond to an interaction.
        
        Args:
            text (str): Response text
            blocks (list): Block Kit blocks
            attachments (list): Message attachments
            response_type (str): "ephemeral" (private) or "in_channel" (public)
            replace_original (bool): Replace the original message
            delete_original (bool): Delete the original message
            unfurl_links (bool): Enable link unfurling
            unfurl_media (bool): Enable media unfurling
            **kwargs: Additional response parameters
            
        Returns:
            dict: Response data
        """

# Usage examples:
def handle_command(ack, respond):
    ack()
    respond("This is a private response")  # Only visible to user
    respond("This is public", response_type="in_channel")  # Visible to all

def handle_button_click(ack, respond):
    ack()
    respond(
        text="Updated message",
        replace_original=True  # Replace the message containing the button
    )

Complete and Fail Functions

Functions for workflow step completion and failure handling.

class Complete:
    """Function to mark workflow steps as complete."""
    
    def __call__(self, outputs: dict = None):
        """
        Mark a workflow step as complete.
        
        Args:
            outputs (dict): Step output values for subsequent steps
        """

class Fail:
    """Function to mark workflow steps as failed."""
    
    def __call__(self, error: str):
        """
        Mark a workflow step as failed.
        
        Args:
            error (str): Error message describing the failure
        """

# Usage in workflow steps:
def execute_step(step, complete, fail):
    try:
        # Step execution logic
        result = process_data(step["inputs"])
        complete(outputs={"result": result})
    except Exception as e:
        fail(error=f"Step failed: {str(e)}")

AI Assistant Utilities

Functions for managing AI assistant conversations and context.

class SetStatus:
    """Set status for AI assistant conversations."""
    
    def __call__(self, text: str):
        """
        Set the assistant status text.
        
        Args:
            text (str): Status message to display
        """

class SetTitle:
    """Set title for AI assistant conversations."""
    
    def __call__(self, title: str):
        """
        Set the conversation title.
        
        Args:
            title (str): Conversation title
        """

class SetSuggestedPrompts:
    """Set suggested prompts for AI assistant conversations."""
    
    def __call__(self, prompts: list):
        """
        Set suggested prompts for the user.
        
        Args:
            prompts (list): List of suggested prompt strings
        """

class SaveThreadContext:
    """Save context data for AI assistant conversations."""
    
    def __call__(self, context: dict):
        """
        Save thread context data.
        
        Args:
            context (dict): Context data to persist
        """

# Usage in assistant handlers:
@app.assistant()
def handle_assistant_message(set_status, set_title, save_thread_context):
    set_status("Processing your request...")
    set_title("Customer Support Chat")
    save_thread_context({"topic": "billing", "priority": "high"})

Slack Web API Client

Direct access to the Slack Web API client for advanced operations.

# WebClient is from slack_sdk package
from slack_sdk import WebClient

# Available as 'client' in all listeners
def handle_event(client: WebClient):
    """
    Use the client for direct API calls.
    
    Common methods:
    - client.chat_postMessage()
    - client.users_info()
    - client.conversations_list()
    - client.files_upload()
    - client.views_open()
    - client.views_update()
    """

# Usage examples:
def handle_command(ack, respond, client, command):
    ack()
    
    # Get user info
    user_info = client.users_info(user=command["user_id"])
    real_name = user_info["user"]["real_name"]
    
    # Post to different channel
    client.chat_postMessage(
        channel="#general",
        text=f"{real_name} used the /weather command"
    )
    
    respond("Weather data sent to #general")

def open_modal(ack, body, client):
    ack()
    
    # Open a modal view
    client.views_open(
        trigger_id=body["trigger_id"],
        view={
            "type": "modal",
            "title": {"type": "plain_text", "text": "My Modal"},
            "blocks": [...]
        }
    )

Logger

Access to the app's logger instance for debugging and monitoring.

# Logger is Python's standard logging.Logger
import logging

def handle_event(logger: logging.Logger):
    """
    Use logger for debugging and monitoring.
    
    Available methods:
    - logger.debug()
    - logger.info()
    - logger.warning()
    - logger.error()
    - logger.exception()
    """

# Usage examples:
def handle_command(ack, command, logger):
    ack()
    
    logger.info(f"Command received: {command['command']} from user {command['user_id']}")
    
    try:
        # Process command
        result = complex_operation()
        logger.debug(f"Operation completed: {result}")
    except Exception as e:
        logger.exception("Command processing failed")
        raise e

Request Body and Payload Data

Access to raw request data and parsed payloads.

def handle_event(body: dict, payload: dict):
    """
    Access request data directly.
    
    Args:
        body (dict): Complete request body from Slack
        payload (dict): Parsed event payload (event-specific)
    """

# Usage examples:
def handle_action(ack, body, action):
    ack()
    
    # body contains full request context
    user_id = body["user"]["id"]
    team_id = body["team"]["id"]
    trigger_id = body.get("trigger_id")
    
    # action contains specific action data
    action_id = action["action_id"]
    value = action.get("value")

def handle_view_submission(ack, body, view):
    ack()
    
    # Extract form values from view state
    values = view["state"]["values"]
    form_data = {}
    
    for block_id, block_values in values.items():
        for action_id, element in block_values.items():
            form_data[action_id] = element["value"]

Multi-Workspace Context

Access to workspace and user identification for multi-workspace apps.

def handle_event(
    enterprise_id: str,
    team_id: str,
    user_id: str,
    channel_id: str
):
    """
    Access workspace context data.
    
    Args:
        enterprise_id (str): Enterprise Grid organization ID (if applicable)
        team_id (str): Workspace/team ID
        user_id (str): User ID who triggered the event
        channel_id (str): Channel ID where event occurred
    """

# Usage for multi-workspace features:
def handle_message(message, say, team_id, user_id):
    # Customize behavior per workspace
    if team_id == "T123456789":
        say("Welcome to our main workspace!")
    else:
        say("Hello from a connected workspace!")
    
    # Log user activity per workspace
    log_user_activity(team_id, user_id, "message_sent")

Usage Examples

Complete Handler with All Context

@app.command("/status")
def status_command(
    ack,
    respond,
    command,
    client,
    logger,
    body,
    user_id,
    team_id,
    context
):
    """Complete example using all available context."""
    
    # Always acknowledge first
    ack()
    
    # Log the request
    logger.info(f"Status command from user {user_id} in team {team_id}")
    
    # Get additional user info
    try:
        user_info = client.users_info(user=user_id)
        user_name = user_info["user"]["real_name"]
        
        # Respond with status
        respond(f"Hello {user_name}! System status: All systems operational 🟢")
        
        # Optional: Post to admin channel
        if command.get("text") == "admin":
            client.chat_postMessage(
                channel="#admin-alerts",
                text=f"Status check requested by {user_name}"
            )
            
    except Exception as e:
        logger.exception("Failed to process status command")
        respond("Sorry, there was an error processing your request.")

Modal Interaction Flow

@app.action("create_ticket")
def open_ticket_modal(ack, body, client):
    """Open ticket creation modal."""
    ack()
    
    modal_view = {
        "type": "modal",
        "callback_id": "ticket_modal",
        "title": {"type": "plain_text", "text": "Create Support Ticket"},
        "submit": {"type": "plain_text", "text": "Create"},
        "blocks": [
            {
                "type": "input",
                "block_id": "title_block",
                "element": {
                    "type": "plain_text_input",
                    "action_id": "title_input",
                    "placeholder": {"type": "plain_text", "text": "Brief description"}
                },
                "label": {"type": "plain_text", "text": "Issue Title"}
            },
            {
                "type": "input",
                "block_id": "priority_block",
                "element": {
                    "type": "static_select",
                    "action_id": "priority_select",
                    "options": [
                        {"text": {"type": "plain_text", "text": "Low"}, "value": "low"},
                        {"text": {"type": "plain_text", "text": "Medium"}, "value": "medium"},
                        {"text": {"type": "plain_text", "text": "High"}, "value": "high"}
                    ]
                },
                "label": {"type": "plain_text", "text": "Priority"}
            }
        ]
    }
    
    client.views_open(trigger_id=body["trigger_id"], view=modal_view)

@app.view_submission("ticket_modal")
def handle_ticket_submission(ack, body, view, client, logger):
    """Handle ticket creation form submission."""
    
    # Extract form data
    values = view["state"]["values"]
    title = values["title_block"]["title_input"]["value"]
    priority = values["priority_block"]["priority_select"]["selected_option"]["value"]
    
    # Validate input
    if len(title) < 5:
        ack({
            "response_action": "errors",
            "errors": {
                "title_block": "Title must be at least 5 characters"
            }
        })
        return
    
    # Create ticket
    try:
        ticket_id = create_support_ticket(title, priority, body["user"]["id"])
        logger.info(f"Created ticket {ticket_id} for user {body['user']['id']}")
        
        # Success - close modal and notify user
        ack({
            "response_action": "clear"
        })
        
        # Send confirmation DM
        client.chat_postMessage(
            channel=body["user"]["id"],
            text=f"✅ Support ticket #{ticket_id} created successfully!\n"
                 f"*Title:* {title}\n"
                 f"*Priority:* {priority.title()}"
        )
        
    except Exception as e:
        logger.exception("Failed to create support ticket")
        ack({
            "response_action": "errors",
            "errors": {
                "title_block": "Failed to create ticket. Please try again."
            }
        })

Related Topics

  • Event Listeners & Request Handling - How to set up event handlers
  • Web Framework Integration - Using context objects with different frameworks
  • OAuth & Multi-Workspace Installation - Multi-workspace context 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