slack-bot-builder

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Slack Bot Builder

Slack 机器人构建指南

Patterns

设计模式

Bolt App Foundation Pattern

Bolt应用基础模式

The Bolt framework is Slack's recommended approach for building apps. It handles authentication, event routing, request verification, and HTTP request processing so you can focus on app logic.
Key benefits:
  • Event handling in a few lines of code
  • Security checks and payload validation built-in
  • Organized, consistent patterns
  • Works for experiments and production
Available in: Python, JavaScript (Node.js), Java
When to use: ['Starting any new Slack app', 'Migrating from legacy Slack APIs', 'Building production Slack integrations']
python
undefined
Bolt框架是Slack官方推荐的应用构建方案。它负责处理身份验证、事件路由、请求验证以及HTTP请求处理,让您可以专注于应用逻辑的开发。
核心优势:
  • 仅需几行代码即可实现事件处理
  • 内置安全检查和负载验证功能
  • 结构化、一致性的设计模式
  • 适用于实验项目和生产环境
支持语言:Python、JavaScript(Node.js)、Java
适用场景:['启动全新Slack应用开发', '从旧版Slack API迁移', '构建生产环境Slack集成']
python
undefined

Python Bolt App

Python Bolt App

from slack_bolt import App from slack_bolt.adapter.socket_mode import SocketModeHandler import os
from slack_bolt import App from slack_bolt.adapter.socket_mode import SocketModeHandler import os

Initialize with tokens from environment

Initialize with tokens from environment

app = App( token=os.environ["SLACK_BOT_TOKEN"], signing_secret=os.environ["SLACK_SIGNING_SECRET"] )
app = App( token=os.environ["SLACK_BOT_TOKEN"], signing_secret=os.environ["SLACK_SIGNING_SECRET"] )

Handle messages containing "hello"

Handle messages containing "hello"

@app.message("hello") def handle_hello(message, say): """Respond to messages containing 'hello'.""" user = message["user"] say(f"Hey there <@{user}>!")
@app.message("hello") def handle_hello(message, say): """Respond to messages containing 'hello'.""" user = message["user"] say(f"Hey there <@{user}>!")

Handle slash command

Handle slash command

@app.command("/ticket") def handle_ticket_command(ack, body, client): """Handle /ticket slash command.""" # Acknowledge immediately (within 3 seconds) ack()
# Open a modal for ticket creation
client.views_open(
    trigger_id=body["trigger_id"],
    view={
        "type": "modal",
        "callback_id": "ticket_modal",
        "title": {"type": "plain_text", "text": "Create Ticket"},
        "submit": {"type": "plain_text", "text": "Submit"},
        "blocks": [
            {
                "type": "input",
                "block_id": "title_block",
                "element": {
                    "type": "plain_text_input",
                    "action_id": "title_input"
                },
                "label": {"type": "plain_text", "text": "Title"}
            },
            {
                "type": "input",
                "block_id": "desc_block",
                "element": {
                    "type": "plain_text_input",
                    "multiline": True,
                    "action_id": "desc_input"
                },
                "label": {"type": "plain_text", "text": "Description"}
            },
            {
                "type": "input",
                "block_id": "priority_block",
                "element": {
                    "type": "static_select",
                    "action_id": "priority_select",
undefined
@app.command("/ticket") def handle_ticket_command(ack, body, client): """Handle /ticket slash command.""" # Acknowledge immediately (within 3 seconds) ack()
# Open a modal for ticket creation
client.views_open(
    trigger_id=body["trigger_id"],
    view={
        "type": "modal",
        "callback_id": "ticket_modal",
        "title": {"type": "plain_text", "text": "Create Ticket"},
        "submit": {"type": "plain_text", "text": "Submit"},
        "blocks": [
            {
                "type": "input",
                "block_id": "title_block",
                "element": {
                    "type": "plain_text_input",
                    "action_id": "title_input"
                },
                "label": {"type": "plain_text", "text": "Title"}
            },
            {
                "type": "input",
                "block_id": "desc_block",
                "element": {
                    "type": "plain_text_input",
                    "multiline": True,
                    "action_id": "desc_input"
                },
                "label": {"type": "plain_text", "text": "Description"}
            },
            {
                "type": "input",
                "block_id": "priority_block",
                "element": {
                    "type": "static_select",
                    "action_id": "priority_select",
undefined

Block Kit UI Pattern

Block Kit UI模式

Block Kit is Slack's UI framework for building rich, interactive messages. Compose messages using blocks (sections, actions, inputs) and elements (buttons, menus, text inputs).
Limits:
  • Up to 50 blocks per message
  • Up to 100 blocks in modals/Home tabs
  • Block text limited to 3000 characters
Use Block Kit Builder to prototype: https://app.slack.com/block-kit-builder
When to use: ['Building rich message layouts', 'Adding interactive components to messages', 'Creating forms in modals', 'Building Home tab experiences']
python
from slack_bolt import App
import os

app = App(token=os.environ["SLACK_BOT_TOKEN"])

def build_notification_blocks(incident: dict) -> list:
    """Build Block Kit blocks for incident notification."""
    severity_emoji = {
        "critical": ":red_circle:",
        "high": ":large_orange_circle:",
        "medium": ":large_yellow_circle:",
        "low": ":white_circle:"
    }

    return [
        # Header
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": f"{severity_emoji.get(incident['severity'], '')} Incident Alert"
            }
        },
        # Details section
        {
            "type": "section",
            "fields": [
                {
                    "type": "mrkdwn",
                    "text": f"*Incident:*\n{incident['title']}"
                },
                {
                    "type": "mrkdwn",
                    "text": f"*Severity:*\n{incident['severity'].upper()}"
                },
                {
                    "type": "mrkdwn",
                    "text": f"*Service:*\n{incident['service']}"
                },
                {
                    "type": "mrkdwn",
                    "text": f"*Reported:*\n<!date^{incident['timestamp']}^{date_short} {time}|{incident['timestamp']}>"
                }
            ]
        },
        # Description
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": f"*Description:*\n{incident['description'][:2000]}"
            }
        },
        # Divider
        {"type": "divider"},
        # Action buttons
        {
            "type": "actions",
            "block_id": f"incident_actions_{incident['id']}",
            "elements": [
                {
                    "type": "button",
                    "text": {"type": "plain_text", "text": "Acknowledge"},
                    "style": "primary",
                    "action_id": "acknowle
Block Kit是Slack用于构建丰富交互式消息的UI框架。您可以使用块(Sections、Actions、Inputs)和元素(按钮、菜单、文本输入框)来组合消息内容。
限制说明:
  • 每条消息最多支持50个块
  • 模态框/主页标签中最多支持100个块
  • 块文本内容限制为3000字符
使用Block Kit Builder进行原型设计:https://app.slack.com/block-kit-builder
适用场景:['构建丰富消息布局', '为消息添加交互式组件', '在模态框中创建表单', '构建主页标签体验']
python
from slack_bolt import App
import os

app = App(token=os.environ["SLACK_BOT_TOKEN"])

def build_notification_blocks(incident: dict) -> list:
    """Build Block Kit blocks for incident notification."""
    severity_emoji = {
        "critical": ":red_circle:",
        "high": ":large_orange_circle:",
        "medium": ":large_yellow_circle:",
        "low": ":white_circle:"
    }

    return [
        # Header
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": f"{severity_emoji.get(incident['severity'], '')} Incident Alert"
            }
        },
        # Details section
        {
            "type": "section",
            "fields": [
                {
                    "type": "mrkdwn",
                    "text": f"*Incident:*\n{incident['title']}"
                },
                {
                    "type": "mrkdwn",
                    "text": f"*Severity:*\n{incident['severity'].upper()}"
                },
                {
                    "type": "mrkdwn",
                    "text": f"*Service:*\n{incident['service']}"
                },
                {
                    "type": "mrkdwn",
                    "text": f"*Reported:*\n<!date^{incident['timestamp']}^{date_short} {time}|{incident['timestamp']}>"
                }
            ]
        },
        # Description
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": f"*Description:*\n{incident['description'][:2000]}"
            }
        },
        # Divider
        {"type": "divider"},
        # Action buttons
        {
            "type": "actions",
            "block_id": f"incident_actions_{incident['id']}",
            "elements": [
                {
                    "type": "button",
                    "text": {"type": "plain_text", "text": "Acknowledge"},
                    "style": "primary",
                    "action_id": "acknowle

OAuth Installation Pattern

OAuth安装模式

Enable users to install your app in their workspaces via OAuth 2.0. Bolt handles most of the OAuth flow, but you need to configure it and store tokens securely.
Key OAuth concepts:
  • Scopes define permissions (request minimum needed)
  • Tokens are workspace-specific
  • Installation data must be stored persistently
  • Users can add scopes later (additive)
70% of users abandon installation when confronted with excessive permission requests - request only what you need!
When to use: ['Distributing app to multiple workspaces', 'Building public Slack apps', 'Enterprise-grade integrations']
python
from slack_bolt import App
from slack_bolt.oauth.oauth_settings import OAuthSettings
from slack_sdk.oauth.installation_store import FileInstallationStore
from slack_sdk.oauth.state_store import FileOAuthStateStore
import os
允许用户通过OAuth 2.0在其工作区中安装您的应用。Bolt框架会处理OAuth流程的大部分工作,但您需要进行相关配置并安全地存储令牌。
OAuth核心概念:
  • 权限范围(Scopes)定义应用权限(仅请求必要的权限)
  • 令牌与工作区绑定
  • 安装数据必须持久化存储
  • 用户可后续添加权限范围(增量式)
当用户面对过多的权限请求时,70%的人会放弃安装——请仅请求必要的权限!
适用场景:['向多个工作区分发应用', '构建公开Slack应用', '企业级集成']
python
from slack_bolt import App
from slack_bolt.oauth.oauth_settings import OAuthSettings
from slack_sdk.oauth.installation_store import FileInstallationStore
from slack_sdk.oauth.state_store import FileOAuthStateStore
import os

For production, use database-backed stores

For production, use database-backed stores

For example: PostgreSQL, MongoDB, Redis

For example: PostgreSQL, MongoDB, Redis

class DatabaseInstallationStore: """Store installation data in your database."""
async def save(self, installation):
    """Save installation when user completes OAuth."""
    await db.installations.upsert({
        "team_id": installation.team_id,
        "enterprise_id": installation.enterprise_id,
        "bot_token": encrypt(installation.bot_token),
        "bot_user_id": installation.bot_user_id,
        "bot_scopes": installation.bot_scopes,
        "user_id": installation.user_id,
        "installed_at": installation.installed_at
    })

async def find_installation(self, *, enterprise_id, team_id, user_id=None, is_enterprise_install=False):
    """Find installation for a workspace."""
    record = await db.installations.find_one({
        "team_id": team_id,
        "enterprise_id": enterprise_id
    })

    if record:
        return Installation(
            bot_token=decrypt(record["bot_token"]),
            # ... other fields
        )
    return None
class DatabaseInstallationStore: """Store installation data in your database."""
async def save(self, installation):
    """Save installation when user completes OAuth."""
    await db.installations.upsert({
        "team_id": installation.team_id,
        "enterprise_id": installation.enterprise_id,
        "bot_token": encrypt(installation.bot_token),
        "bot_user_id": installation.bot_user_id,
        "bot_scopes": installation.bot_scopes,
        "user_id": installation.user_id,
        "installed_at": installation.installed_at
    })

async def find_installation(self, *, enterprise_id, team_id, user_id=None, is_enterprise_install=False):
    """Find installation for a workspace."""
    record = await db.installations.find_one({
        "team_id": team_id,
        "enterprise_id": enterprise_id
    })

    if record:
        return Installation(
            bot_token=decrypt(record["bot_token"]),
            # ... other fields
        )
    return None

Initialize OAuth-enabled app

Initialize OAuth-enabled app

app = App( signing_secret=os.environ["SLACK_SIGNING_SECRET"], oauth_settings=OAuthSettings( client_id=os.environ["SLACK_CLIENT_ID"], client_secret=os.environ["SLACK_CLIENT_SECRET"], scopes=[ "channels:history", "channels:read", "chat:write", "commands", "users:read" ], user_scopes=[], # User token scopes if needed installation_store=DatabaseInstallationStore(), state_store=FileOAuthStateStore(expiration_seconds=600) ) )
app = App( signing_secret=os.environ["SLACK_SIGNING_SECRET"], oauth_settings=OAuthSettings( client_id=os.environ["SLACK_CLIENT_ID"], client_secret=os.environ["SLACK_CLIENT_SECRET"], scopes=[ "channels:history", "channels:read", "chat:write", "commands", "users:read" ], user_scopes=[], # User token scopes if needed installation_store=DatabaseInstallationStore(), state_store=FileOAuthStateStore(expiration_seconds=600) ) )

OAuth routes are handled a

OAuth routes are handled a

undefined
undefined

⚠️ Sharp Edges

⚠️ 注意事项

IssueSeveritySolution
Issuecritical## Acknowledge immediately, process later
Issuecritical## Proper state validation
Issuecritical## Never hardcode or log tokens
Issuehigh## Request minimum required scopes
Issuemedium## Know and respect the limits
Issuehigh## Socket Mode: Only for development
Issuecritical## Bolt handles this automatically
问题严重程度解决方案
问题严重## 立即确认,延后处理
问题严重## 正确的状态验证
问题严重## 切勿硬编码或记录令牌
问题## 请求必要的最小权限范围
问题## 了解并遵守限制
问题## Socket Mode:仅用于开发环境
问题严重## Bolt框架会自动处理此问题