Production-Ready Slack Bot with Async Processing Architecture
This repository demonstrates how to build a production-ready AI-powered Slack bot using modern serverless technologies: Hono, QStash, and the AI SDK. The bot generates creative poetry in response to direct messages and channel mentions, while implementing a robust two-tier architecture to handle Slack's strict 3-second response requirements.
- Async Processing Architecture: Handle Slack's 3-second timeout using QStash for background processing
- Modern Web Framework: Build fast APIs with Hono's lightweight, edge-optimized framework
- AI-Powered Responses: Generate creative poetry using the AI SDK with OpenAI GPT-4 mini
- Production-Grade Event Handling: Implement reliable webhook processing with retry logic
- TypeScript Best Practices: Full type safety for Slack events and AI responses
- Security Implementation: Slack request signature verification and secure API handling
Slack's Events API has a strict requirement: your server must respond with HTTP 200 within 3 seconds or the event will be considered failed. According to Slack's documentation, failure conditions include:
- Response timeout: Taking longer than 3 seconds to respond
- Invalid responses: Any non-200 HTTP status code (except redirects)
- SSL issues: Certificate validation failures
- Connection problems: Server unreachability
When your server fails to respond within 3 seconds, Slack implements an exponential backoff retry strategy:
- Immediate retry - Almost instant retry
- 1-minute retry - Second attempt after 1 minute
- 5-minute retry - Final attempt after 5 minutes
Critical Impact: If your app fails to respond successfully to more than 95% of events within 60 minutes, Slack will temporarily disable your event subscriptions.
This bot solves the timeout challenge using QStash (Upstash's message queue) to implement a two-tier async processing architecture:
π± Slack Event β π Webhook (< 3s response) β π¬ QStash Queue β π€ AI Processing β π¬ Response
Benefits of this approach:
- β Instant response: Webhook responds to Slack in milliseconds
- β Reliable processing: QStash ensures messages are processed even if AI generation takes time
- β Automatic retries: QStash handles failed processing attempts
- β Scalable: Handle high event volumes without timeout issues
- β Cost-effective: Only pay for actual processing time
| Aspect | Serverless Functions (This Approach) | @slack/bolt Framework |
|---|---|---|
| Learning Curve | π Steeper - understand Slack APIs directly | π’ Gentler - high-level abstractions |
| Control & Flexibility | π― Full control over request/response flow | π Framework conventions and limitations |
| Hosting Costs | π° Pay-per-request, near $0 for low traffic | πΈ Persistent server costs (always running) |
| Scaling | π Automatic infinite scaling | π Manual server scaling required |
| Cold Start Issues | β Always warm, no cold starts | |
| Infrastructure | βοΈ Zero server management | π₯οΈ Server maintenance and monitoring |
| Debugging | π More manual event inspection | π οΈ Built-in debugging tools |
| Long-running Tasks | β Limited by function timeouts | β Handle extended operations |
| Understanding | π§ Deep knowledge of Slack mechanics | π¦ Abstracted implementation details |
- Building cost-effective bots with sporadic usage
- Learning how Slack APIs work under the hood
- Need maximum flexibility in request handling
- Want zero infrastructure management
- Prefer TypeScript with full type control
- Need rapid prototyping with minimal setup
- Handling complex workflows and long-running tasks
- Want official Slack support and updates
- Team prefers framework conventions over custom code
- Building enterprise apps with dedicated infrastructure
- Direct Message Support: Send the bot a private message with any prompt and receive a personalized poem
- Channel Mentions: Mention the bot in any channel (
@botname your prompt) to get a public poetry response - Two-Tier Async Architecture: Instant webhook responses + background AI processing via QStash
- AI-Powered Creativity: Uses OpenAI GPT-4 mini via AI SDK to generate high-quality poetry
- Production-Grade Reliability: Handles Slack's 3-second timeout with robust retry mechanisms
- Type Safety: Full TypeScript implementation with comprehensive Slack event types
- Security: Slack request signature verification for secure webhook handling
src/
βββ index.ts # Hono app with two-tier async processing
βββ lib/
β βββ types.ts # TypeScript types for Slack events
β βββ verify-slack-request.ts # Slack signature verification
- π Hono: Ultra-fast web framework optimized for edge runtimes
- π¬ QStash: Serverless message queue for async background processing
- π€ AI SDK: Type-safe AI integration for OpenAI GPT-4 mini
- β‘ Vercel: Serverless deployment platform with automatic scaling
- π TypeScript: Full type safety for Slack events and AI responses
graph LR
A[Slack Event] --> B[Hono Webhook]
B --> C{Event Valid?}
C -->|Yes| D[QStash Publish]
C -->|No| E[Return 200 OK]
D --> E
E --> F[< 3 Second Response]
D --> G[QStash Queue]
G --> H[Background Processor]
H --> I[AI SDK + OpenAI]
I --> J[Generated Poetry]
J --> K[Slack API Response]
Tier 1 - Instant Webhook Response (/custom-bot/events):
- Receives Slack events via Hono framework
- Validates request signatures and event types
- Publishes valid events to QStash queue
- Returns HTTP 200 to Slack (< 3 seconds guaranteed)
Tier 2 - Async AI Processing (/api/process-message):
- QStash triggers background processing endpoint
- AI SDK generates poetry using OpenAI GPT-4 mini
- Posts generated response back to original Slack channel
- Handles longer processing times without timeout issues
The bot uses intelligent event filtering and async processing:
- Trigger: User sends a direct message to the bot
- Instant Response: Webhook validates and queues event via QStash (< 3s)
- Async Processing: Background worker generates poetry using AI SDK
- Final Response: Bot posts generated poem back to the user
- Trigger: User mentions the bot in a channel (
@botname write about sunsets) - Instant Response: Webhook strips bot mention and queues clean text via QStash
- Async Processing: AI generates poetry based on the clean prompt
- Final Response: Bot posts poem as public reply in the channel
The webhook tier filters events before queuing:
- β Valid events: Direct messages and app mentions with content
- β Bot messages: Ignored to prevent infinite loops
- β System messages: Messages with subtypes are filtered out
- β Empty content: Messages without text content are ignored
- β Invalid events: Non-event_callback types rejected early
- No timeouts: AI generation can take 10+ seconds without affecting Slack
- Reliable delivery: QStash ensures messages are processed even if temporary failures occur
- Automatic retries: Failed AI generations are automatically retried by QStash
- Scalable: Handle multiple conversations simultaneously without blocking
This tutorial takes the "learn by building" approach by implementing Slack bot functionality from scratch. You'll gain deep understanding of:
- Raw Webhook Handling: How Slack sends events to your application
- Event Type Processing: Manual parsing and routing of different Slack events
- Security Implementation: Signature verification to prevent unauthorized requests
- State Management: Redis-based deduplication and session handling
- API Integration: Direct calls to Slack's Web API without abstractions
- Serverless Patterns: Designing functions for optimal performance and cost
Perfect for developers who want to:
- Understand Slack's architecture beyond framework abstractions
- Implement custom logic that doesn't fit framework patterns
- Build ultra-lightweight bots with minimal dependencies
- Learn transferable skills for other webhook-based APIs
- Vercel CLI installed globally
- QStash account for async message processing
- Slack app with appropriate permissions
Create a .env.local file with the following variables:
SLACK_SIGNING_SECRET=your_slack_signing_secret
SLACK_BOT_TOKEN=xoxb-your-bot-token
OPENAI_API_KEY=your_openai_api_key
QSTASH_TOKEN=your_qstash_token
BASE_URL=https://your-domain.vercel.appGetting QStash credentials:
- Sign up at Upstash Console
- Create a new QStash database
- Copy the
QSTASH_TOKENfrom your dashboard
- Create a new Slack app at api.slack.com
- Enable Event Subscriptions and set your webhook URL to:
https://your-domain.vercel.app/custom-bot/events - Subscribe to these Bot Events:
message.im(for direct messages)app_mention(for channel mentions)
- Install the app to your workspace and copy the Bot User OAuth Token
Your Slack app needs these scopes:
chat:write- Send messages as the botapp_mentions:read- Receive app mention eventsim:read- Receive direct message events
To develop locally:
npm install
vc devOpen http://localhost:3000 to verify the server is running.
- Direct Message Test: Send a DM to your bot with any text (e.g., "ocean sunset")
- Channel Mention Test: In a channel, type
@your-bot-name write about mountains - Check Logs: Monitor the console for detailed event processing logs
To build locally:
npm install
vc buildTo deploy:
npm install
vc deployThe bot provides comprehensive logging across both processing tiers:
Webhook Tier Logging:
- Event Reception: Logs all incoming Slack events with sanitized content
- Event Filtering: Clear messages about why events are ignored or processed
- QStash Publishing: Confirms successful queuing of events for background processing
- Response Times: Tracks webhook response times to ensure < 3 second compliance
Background Processing Tier:
- AI Generation: Logs when AI poetry generation starts and completes
- Slack API Responses: Logs success/failure of message posting to Slack
- Error Handling: Detailed error logging for troubleshooting failed processing
- Queue Processing: QStash automatically provides retry and failure metrics
- Signature Verification: All webhook requests verified against Slack's signing secret
- Async Reliability: QStash ensures message processing even during temporary failures
- Type Safety: Comprehensive TypeScript types prevent runtime errors
- Input Validation: Proper filtering of bot messages and invalid content
- Automatic Retries: QStash handles failed AI processing attempts automatically
- Rate Limiting Protection: Background processing prevents webhook timeout issues
The bot uses OpenAI GPT-4 mini via the AI SDK with this configuration:
const { text } = await generateText({
model: "openai/gpt-4.1-mini", // Cost-effective model optimized for creative tasks
system: "You are an arts teacher who writes the best possible poetry.",
prompt: `Write a poem about the following prompt: ${userMessage}`,
});Why GPT-4 mini?
- Cost-effective: Significantly cheaper than full GPT-4 for creative tasks
- Fast generation: Quick response times perfect for async processing
- Creative quality: Excellent for poetry and creative writing tasks
- Extend Functionality: Add slash commands, interactive components, or file uploads
- Advanced QStash Patterns: Implement delayed jobs, scheduled poetry, or batch processing
- AI Enhancements: Add conversation memory, style preferences, or multi-modal inputs
- Production Hardening: Add comprehensive error handling, monitoring, and alerting
- Slack Events API - Critical timeout and retry behavior
- QStash Documentation - Async message processing patterns
- AI SDK Guide - Type-safe AI integration patterns
- Hono Documentation - Ultra-fast web framework for edge runtimes
- Vercel Functions - Serverless deployment and scaling
- Cloudflare Workers: Deploy the same Hono app to Cloudflare's edge network
- AWS Lambda: Adapt for Lambda with API Gateway (may need timeout adjustments)
- Railway/Fly.io: Traditional hosting with persistent QStash connections
- Deno Deploy: Edge deployment with native TypeScript support