| 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-...
export SLACK_APP_TOKEN=xapp-...
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 channel
respond - Reply using response_url
client - WebClient for Slack API calls
body - Full request payload
logger - Logger instance
context - 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_id expires in 3 seconds and is single-use - open modals immediately after ack()
- Global shortcuts do NOT include channel ID - use
conversations_select in modal if needed
response_url is valid for 30 minutes, max 5 uses, default ephemeral
- Modal title max 24 characters,
private_metadata max 3000 characters
- View stack max 3 views deep
- Include
hash parameter when calling views_update to prevent race conditions
- For HTTP mode, all Bolt endpoints use
/slack/events path
- For
view_closed events, set notify_on_close: True when creating the view
chat_postMessage requires bot to be in channel (or use im:write for DMs)
- Python Web API methods use underscores (
chat_postMessage), not dots