Slack Bot Smart
Streamline your workflow with this build, slack, apps, using. Includes structured workflows, validation checks, and reusable patterns for enterprise communication.
Slack Bot Smart
A comprehensive skill for building Slack bots using the Bolt framework ā covering app setup, event handling, slash commands, interactive components, message formatting with Block Kit, middleware patterns, and deployment to production.
When to Use This Skill
Choose Slack Bot Smart when you need to:
- Build a Slack bot with slash commands and event listeners
- Create interactive workflows with buttons, modals, and menus
- Integrate external services with Slack notifications
- Build message formatting with Block Kit
- Deploy a production-ready Slack application
Consider alternatives when:
- You need a simple webhook notification (use Slack webhooks directly)
- You're building a Discord bot (use a Discord bot skill)
- You need a Microsoft Teams bot (use a Teams bot skill)
Quick Start
# Initialize a Slack bot project mkdir my-slack-bot && cd my-slack-bot npm init -y npm install @slack/bolt dotenv
// app.js ā Bolt app setup const { App } = require("@slack/bolt"); require("dotenv").config(); const app = new App({ token: process.env.SLACK_BOT_TOKEN, signingSecret: process.env.SLACK_SIGNING_SECRET, socketMode: true, appToken: process.env.SLACK_APP_TOKEN, }); // Slash command app.command("/hello", async ({ command, ack, respond }) => { await ack(); await respond({ text: `Hey <@${command.user_id}>! How can I help?`, response_type: "ephemeral", }); }); // Message event listener app.message("hello bot", async ({ message, say }) => { await say({ text: `Hi <@${message.user}>! š`, blocks: [ { type: "section", text: { type: "mrkdwn", text: `Hi <@${message.user}>! How can I help you today?`, }, accessory: { type: "button", text: { type: "plain_text", text: "Get Help" }, action_id: "help_button", }, }, ], }); }); // Button interaction app.action("help_button", async ({ body, ack, respond }) => { await ack(); await respond("Here's what I can do: `/hello`, `/status`, `/deploy`"); }); (async () => { await app.start(3000); console.log("ā” Slack bot is running on port 3000"); })();
Core Concepts
Bolt App Architecture
| Component | Purpose | Handler Type |
|---|---|---|
| Commands | Slash command handlers | app.command() |
| Events | Message and workspace events | app.event() |
| Actions | Button, menu, and select interactions | app.action() |
| Views | Modal submissions and updates | app.view() |
| Shortcuts | Global and message shortcuts | app.shortcut() |
| Middleware | Cross-cutting concerns | app.use() |
Block Kit Message Formatting
// Rich message with Block Kit const statusMessage = { blocks: [ { type: "header", text: { type: "plain_text", text: "Deployment Status" }, }, { type: "section", fields: [ { type: "mrkdwn", text: "*Service:*\napi-gateway" }, { type: "mrkdwn", text: "*Environment:*\nproduction" }, { type: "mrkdwn", text: "*Version:*\nv2.3.1" }, { type: "mrkdwn", text: "*Status:*\nā Deployed" }, ], }, { type: "divider" }, { type: "actions", elements: [ { type: "button", text: { type: "plain_text", text: "View Logs" }, action_id: "view_logs", url: "https://logs.example.com/api-gateway", }, { type: "button", text: { type: "plain_text", text: "Rollback" }, action_id: "rollback", style: "danger", confirm: { title: { type: "plain_text", text: "Confirm Rollback" }, text: { type: "mrkdwn", text: "Roll back to v2.3.0?" }, confirm: { type: "plain_text", text: "Rollback" }, deny: { type: "plain_text", text: "Cancel" }, }, }, ], }, ], };
Modal Interactions
// Open a modal from a slash command app.command("/feedback", async ({ command, ack, client }) => { await ack(); await client.views.open({ trigger_id: command.trigger_id, view: { type: "modal", callback_id: "feedback_modal", title: { type: "plain_text", text: "Submit Feedback" }, submit: { type: "plain_text", text: "Submit" }, blocks: [ { type: "input", block_id: "category", element: { type: "static_select", action_id: "category_select", options: [ { text: { type: "plain_text", text: "Bug" }, value: "bug" }, { text: { type: "plain_text", text: "Feature" }, value: "feature" }, { text: { type: "plain_text", text: "Other" }, value: "other" }, ], }, label: { type: "plain_text", text: "Category" }, }, { type: "input", block_id: "details", element: { type: "plain_text_input", action_id: "details_input", multiline: true, }, label: { type: "plain_text", text: "Details" }, }, ], }, }); }); // Handle modal submission app.view("feedback_modal", async ({ ack, body, view }) => { await ack(); const category = view.state.values.category.category_select.selected_option.value; const details = view.state.values.details.details_input.value; console.log(`Feedback: ${category} ā ${details}`); });
Configuration
| Parameter | Description | Example |
|---|---|---|
bot_token | Slack Bot User OAuth Token | process.env.SLACK_BOT_TOKEN |
signing_secret | Slack app signing secret | process.env.SLACK_SIGNING_SECRET |
app_token | App-level token for Socket Mode | process.env.SLACK_APP_TOKEN |
socket_mode | Use Socket Mode instead of HTTP | true |
port | HTTP server port (if not Socket Mode) | 3000 |
log_level | Logging verbosity | "info" / "debug" |
Best Practices
-
Use Socket Mode during development, HTTP endpoints in production ā Socket Mode requires no public URL and works behind firewalls, making it perfect for development. For production, switch to HTTP endpoints behind a load balancer for reliability and observability.
-
Always
ack()interactions within 3 seconds ā Slack requires acknowledgment of every interaction within 3 seconds. Callack()immediately, then process the request asynchronously. Failing to ack causes the user to see a timeout error even if your bot eventually responds. -
Use Block Kit Builder to prototype messages visually ā Slack's Block Kit Builder (app.slack.com/block-kit-builder) lets you design and preview message layouts visually, then copy the JSON into your code. Building complex Block Kit JSON by hand is error-prone and slow.
-
Store tokens in environment variables with clear naming ā Slack apps use multiple tokens (bot token, signing secret, app token). Name them clearly (
SLACK_BOT_TOKEN,SLACK_SIGNING_SECRET) and never commit them to source control. Rotate tokens immediately if exposed. -
Implement error handling middleware ā Add a global error handler with
app.error()that logs errors with context (user, command, channel) and sends a user-friendly ephemeral message. Unhandled errors cause silent failures that are difficult to debug.
Common Issues
Bot doesn't receive messages in channels ā The bot must be invited to a channel to receive message events there. Additionally, ensure the channels:history and chat:write scopes are added, and the message.channels event is subscribed in your app configuration.
Slash commands work in DM but not in channels ā Verify that the command is registered in the Slack app configuration (not just in your code). Also check that the request URL (for HTTP mode) is publicly accessible and correctly configured in the Slack API dashboard.
Modal fails to open with "expired trigger_id" ā Trigger IDs expire after 3 seconds. If your command handler does any processing before calling views.open(), the trigger ID may expire. Call views.open() as early as possible in the handler, or use ack() with a response_action to update the view.
Reviews
No reviews yet. Be the first to review this template!
Similar Templates
Full-Stack Code Reviewer
Comprehensive code review skill that checks for security vulnerabilities, performance issues, accessibility, and best practices across frontend and backend code.
Test Suite Generator
Generates comprehensive test suites with unit tests, integration tests, and edge cases. Supports Jest, Vitest, Pytest, and Go testing.
Pro Architecture Workspace
Battle-tested skill for architectural, decision, making, framework. Includes structured workflows, validation checks, and reusable patterns for development.