name: slack-app-developer description: Build interactive Slack apps using the Bolt for Python framework with Block Kit UI, modals, slash commands, shortcuts, events, Socket Mode, and Web API integration. Use when building Slack bots, interactive Slack apps, Slack integrations with external services (REST API, webhooks, WebSocket), apps with buttons/modals/forms in Slack, Workflow Builder custom steps, or any Slack platform development. Triggers on Slack app code, slack_bolt, Block Kit JSON, app manifests, or Slack API usage.
Slack App Developer
Build interactive Slack apps in Python that integrate with external services via REST API, webhooks, or WebSocket using Bolt for Python.
Package: slack_bolt | Min Version: Python 3.7+
Quick Start
1. Create Project
slack create my-app --template slack-samples/bolt-python-getting-started-app
cd my-app && python3 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
2. Set Environment Variables
export SLACK_BOT_TOKEN=xoxb-... # OAuth & Permissions page
export SLACK_APP_TOKEN=xapp-... # Basic Information > App-Level Tokens (connections:write scope)
3. Minimal App
import os
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
app = App(token=os.environ["SLACK_BOT_TOKEN"])
@app.message("hello")
def message_hello(message, say):
say(f"Hey there <@{message['user']}>!")
if __name__ == "__main__":
SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start()
4. Manifest
Every app needs a manifest.json. Minimal example:
{
"display_information": { "name": "My App" },
"features": {
"bot_user": { "display_name": "MyBot", "always_online": true }
},
"oauth_config": {
"scopes": { "bot": ["channels:history", "chat:write", "im:history"] }
},
"settings": {
"event_subscriptions": { "bot_events": ["message.channels", "message.im"] },
"interactivity": { "is_enabled": true },
"socket_mode_enabled": true
}
}
Core Concepts
Critical Rule: Acknowledge within 3 seconds
All actions, commands, shortcuts, options, and view submissions MUST call ack() immediately. Do heavy work after acknowledging.
Listener Types
| Type | Decorator | Use Case |
|---|---|---|
| Messages | @app.message(pattern) |
React to messages |
| Events | @app.event(type) |
React to Slack events |
| Actions | @app.action(action_id) |
Button clicks, menu selects |
| Commands | @app.command("/cmd") |
Slash commands |
| Shortcuts | @app.shortcut(callback_id) |
Global/message shortcuts |
| Views | @app.view(callback_id) |
Modal submissions |
| Options | @app.options(action_id) |
Dynamic select menus |
| Custom Steps | @app.function(callback_id) |
Workflow Builder steps |
Listener Arguments
Common args available in all listeners (injected via kwargs):
ack- Acknowledge the request (required for actions/commands/shortcuts/views)say- Send message to originating channelrespond- Reply usingresponse_urlclient- WebClient for Slack API callsbody- Full request payloadlogger- Logger instancecontext- Enrichable context dictionary
Additional by type:
- Actions:
action(triggered element data) - Events:
event(event data) - Commands:
command(command data) - Shortcuts:
shortcut(shortcut data) - Views:
view(view state with input values) - Custom Steps:
inputs,complete,fail
Input Value Access Pattern
For modal submissions, values are at:
val = view["state"]["values"]["block_id"]["action_id"]["value"]
Python Web API Method Names
Python uses underscores instead of dots: chat_postMessage, views_open, views_update, views_publish, reactions_add.
Workflow Decision Tree
User wants to...
- Send notifications to Slack from external service -> Incoming Webhooks or Web API
chat_postMessage - Respond to messages/keywords ->
@app.message()listener - Add slash commands ->
@app.command()+ manifest slash_commands - Collect user input -> Open modal with
client.views_open(), handle with@app.view() - React to button clicks/menus ->
@app.action()listener - Show a dashboard per user -> App Home with
@app.event('app_home_opened')+views_publish - Create Workflow Builder steps ->
@app.function()with manifest functions definition - Call external API from Slack -> Action/command handler makes HTTP request
- Receive external webhooks -> Custom route with Flask adapter
- Real-time bidirectional sync -> Background WebSocket thread + Slack Socket Mode
References
Consult these based on the task:
- Bolt Python patterns and code: Read references/bolt-python.md for all listener examples, Socket Mode, async, lazy listeners (FaaS), middleware, error handling, Web API, custom steps
- Block Kit, modals, and interactivity: Read references/interactivity-and-block-kit.md for block types, interactive elements, modal structure, payload types, response URLs, incoming webhooks
- Manifest, tokens, events, deployment: Read references/manifest-and-config.md for full manifest schema, token types, OAuth scopes, Events API, Socket Mode vs HTTP, security, rate limits, Lambda deployment
- External service integration: Read references/integration-patterns.md for Slack-to-API, API-to-Slack, bidirectional WebSocket, approval workflows, webhook receivers
Key Gotchas
trigger_idexpires in 3 seconds and is single-use - open modals immediately afterack()- Global shortcuts do NOT include channel ID - use
conversations_selectin modal if needed response_urlis valid for 30 minutes, max 5 uses, default ephemeral- Modal title max 24 characters,
private_metadatamax 3000 characters - View stack max 3 views deep
- Include
hashparameter when callingviews_updateto prevent race conditions - For HTTP mode, all Bolt endpoints use
/slack/eventspath - For
view_closedevents, setnotify_on_close: Truewhen creating the view chat_postMessagerequires bot to be in channel (or useim:writefor DMs)- Python Web API methods use underscores (
chat_postMessage), not dots