Slack ChatGPT Bot: Team Productivity Integration 2026
Bring ChatGPT intelligence directly into your Slack channels for instant answers, workflow automation, and seamless team collaboration. Engineering teams using Slack ChatGPT bots report a 50% reduction in context switching and 30% faster decision-making. Instead of toggling between Slack and ChatGPT browser tabs, your team gets AI-powered insights exactly where conversations happen.
This comprehensive guide walks you through building a production-ready Slack ChatGPT bot with OAuth authentication, event-driven messaging, slash commands, and interactive components. Whether you're an engineering manager looking to boost productivity or a DevOps engineer automating incident response, you'll learn how to integrate ChatGPT's conversational AI into your Slack workspace using the official Slack Bolt SDK and MCP server architecture.
By the end of this tutorial, you'll have a fully functional Slack bot that responds to mentions, processes slash commands, handles interactive components, and scales across multiple workspaces with OAuth 2.0.
Why Build a Slack ChatGPT Bot
Slack ChatGPT bot integration transforms how engineering teams access AI-powered assistance without disrupting their workflow. Instead of forcing developers to context-switch between communication tools and AI interfaces, the bot brings intelligence directly into Slack threads.
Real-World Use Cases:
- Q&A Bot: Answer technical questions in #engineering channels without leaving Slack
- Code Review Assistant: Analyze pull request snippets pasted in Slack threads
- Standup Summaries: Generate daily standup reports from channel activity
- Incident Response: Provide troubleshooting steps during outages in #incidents
- Documentation Search: Query internal knowledge bases via natural language
- Translation: Convert messages between languages for distributed teams
Team Productivity Benefits:
Teams report significant productivity gains after deploying Slack ChatGPT bots:
- 50% reduction in context switching: No more toggling between browser tabs
- 30% faster decision-making: Instant access to AI insights during discussions
- Improved knowledge sharing: AI answers visible to entire channel, not just one person
- Asynchronous collaboration: Bot responds 24/7 across time zones
- Reduced interruptions: Answer common questions without pinging senior engineers
Technical Advantages:
Slack's event-driven architecture makes it ideal for ChatGPT integration:
- Real-time messaging: Sub-second bot responses via WebSocket connections
- Rich UI components: Buttons, modals, and interactive elements for complex workflows
- Enterprise-grade security: OAuth 2.0, token encryption, workspace-level permissions
- Scalable infrastructure: Handles thousands of messages/hour with proper rate limiting
- Developer-friendly API: Bolt SDK abstracts complexity with middleware patterns
For teams already using MakeAIHQ's ChatGPT app builder, integrating your existing MCP server with Slack takes minutes instead of days.
Prerequisites and Setup
Before building your Slack ChatGPT bot, ensure you have the following requirements in place:
Slack Workspace Requirements:
- Admin access to create and configure Slack apps
- Development workspace for testing (create a free workspace at slack.com if needed)
- App creation permissions (Workspace Admins or Owners only)
Development Environment:
- Node.js 18+ installed with npm/yarn
- Slack Bolt SDK (
@slack/boltpackage) - ChatGPT MCP server endpoint (build one with MakeAIHQ's AI Conversational Editor)
- HTTPS endpoint for Slack event delivery (use ngrok for local development)
Technical Knowledge:
- Familiarity with Express.js/Node.js middleware patterns
- Understanding of OAuth 2.0 flows
- Basic knowledge of Slack's event-driven architecture
- Experience with async/await JavaScript
Optional Tools:
- Database for multi-workspace OAuth token storage (PostgreSQL, MongoDB, or Firestore)
- Redis for rate limiting and caching
- Logging service (Datadog, Splunk) for production monitoring
If you're new to Slack bot development, review the official Slack API documentation and explore Slack Bolt SDK examples before proceeding.
Implementation Guide
Step 1: Create Slack App and Configure Manifest
Navigate to api.slack.com/apps and click Create New App → From an app manifest. Select your development workspace and paste this complete app manifest:
display_information:
name: ChatGPT Team Assistant
description: AI-powered assistant for instant answers and workflow automation
background_color: "#0A0E27"
long_description: "Bring ChatGPT intelligence to your Slack workspace. Ask questions, summarize threads, translate messages, and automate workflows without leaving Slack. Built with MakeAIHQ's ChatGPT app platform."
features:
app_home:
home_tab_enabled: true
messages_tab_enabled: true
messages_tab_read_only_enabled: false
bot_user:
display_name: ChatGPT Bot
always_online: true
slash_commands:
- command: /chatgpt-ask
url: https://your-domain.com/slack/commands
description: Ask ChatGPT a question
usage_hint: "[your question]"
should_escape: false
- command: /chatgpt-summarize
url: https://your-domain.com/slack/commands
description: Summarize recent channel messages
usage_hint: "[number of messages]"
should_escape: false
- command: /chatgpt-translate
url: https://your-domain.com/slack/commands
description: Translate text to another language
usage_hint: "[target language] [text]"
should_escape: false
oauth_config:
redirect_urls:
- https://your-domain.com/slack/oauth_redirect
scopes:
bot:
- app_mentions:read
- channels:history
- channels:read
- chat:write
- chat:write.public
- commands
- files:read
- im:history
- im:read
- im:write
- users:read
settings:
event_subscriptions:
request_url: https://your-domain.com/slack/events
bot_events:
- app_mention
- message.channels
- message.im
- file_shared
interactivity:
is_enabled: true
request_url: https://your-domain.com/slack/interactions
org_deploy_enabled: false
socket_mode_enabled: false
token_rotation_enabled: true
Key Configuration Points:
- Event Request URL: Replace
your-domain.comwith your HTTPS endpoint (use ngrok for local testing:ngrok http 3000) - OAuth Scopes: Minimal permissions for read/write messages and respond to mentions
- Slash Commands: Three example commands (add more as needed)
- Token Rotation: Enabled for security best practices
After creating the app, navigate to Basic Information and copy your Signing Secret and App Credentials (Client ID, Client Secret). You'll need these for OAuth and request verification.
Step 2: Build Event Handler for Messages
Install the Slack Bolt SDK and create your main bot server:
npm install @slack/bolt dotenv
Create bot.js with a complete event handler:
const { App } = require('@slack/bolt');
const axios = require('axios');
require('dotenv').config();
// Initialize Bolt app with credentials
const app = new App({
signingSecret: process.env.SLACK_SIGNING_SECRET,
clientId: process.env.SLACK_CLIENT_ID,
clientSecret: process.env.SLACK_CLIENT_SECRET,
stateSecret: process.env.SLACK_STATE_SECRET,
scopes: ['app_mentions:read', 'channels:history', 'chat:write', 'chat:write.public', 'commands'],
installationStore: {
storeInstallation: async (installation) => {
// Store OAuth tokens in your database
// Replace with your database logic (Firestore, PostgreSQL, etc.)
console.log('Storing installation:', installation);
return;
},
fetchInstallation: async (installQuery) => {
// Fetch OAuth tokens from your database
console.log('Fetching installation:', installQuery);
return null; // Replace with database query
},
deleteInstallation: async (installQuery) => {
// Delete OAuth tokens from database
console.log('Deleting installation:', installQuery);
return;
},
},
});
// Event handler for app mentions (@ChatGPT Bot)
app.event('app_mention', async ({ event, context, client, say }) => {
try {
// Extract user message (remove bot mention)
const userMessage = event.text.replace(/<@[A-Z0-9]+>/g, '').trim();
// Get user info for personalization
const userInfo = await client.users.info({ user: event.user });
const userName = userInfo.user.real_name || userInfo.user.name;
// Show typing indicator
await client.chat.postMessage({
channel: event.channel,
thread_ts: event.thread_ts || event.ts,
text: '_Thinking..._',
});
// Call ChatGPT MCP server
const chatgptResponse = await callChatGPTMCP({
prompt: userMessage,
userId: event.user,
userName: userName,
context: 'slack_mention',
});
// Post ChatGPT response in thread
await say({
text: chatgptResponse,
thread_ts: event.thread_ts || event.ts,
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: chatgptResponse,
},
},
{
type: 'actions',
elements: [
{
type: 'button',
text: { type: 'plain_text', text: 'Follow-up Question' },
action_id: 'follow_up_question',
value: event.ts,
},
{
type: 'button',
text: { type: 'plain_text', text: 'Share with Team' },
action_id: 'share_response',
value: event.ts,
style: 'primary',
},
],
},
],
});
} catch (error) {
console.error('Error handling app mention:', error);
await say({
text: `Sorry, I encountered an error: ${error.message}`,
thread_ts: event.thread_ts || event.ts,
});
}
});
// Event handler for direct messages
app.event('message', async ({ event, context, client, say }) => {
// Ignore bot messages and threaded replies (handled by app_mention)
if (event.subtype || event.thread_ts) return;
try {
const chatgptResponse = await callChatGPTMCP({
prompt: event.text,
userId: event.user,
context: 'slack_dm',
});
await say({
text: chatgptResponse,
thread_ts: event.ts,
});
} catch (error) {
console.error('Error handling DM:', error);
await say(`Error: ${error.message}`);
}
});
// Helper function to call ChatGPT MCP server
async function callChatGPTMCP({ prompt, userId, userName = 'User', context = 'slack' }) {
try {
const response = await axios.post(process.env.CHATGPT_MCP_ENDPOINT, {
messages: [
{
role: 'system',
content: `You are a helpful Slack bot assistant. User: ${userName} (${userId}). Context: ${context}`,
},
{
role: 'user',
content: prompt,
},
],
max_tokens: 500,
temperature: 0.7,
}, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.CHATGPT_API_KEY}`,
},
timeout: 25000, // Slack requires response within 3 seconds, but we handle async
});
return response.data.choices[0].message.content;
} catch (error) {
console.error('ChatGPT MCP error:', error.response?.data || error.message);
throw new Error('Failed to get response from ChatGPT');
}
}
// Start the app
(async () => {
const port = process.env.PORT || 3000;
await app.start(port);
console.log(`⚡️ Slack ChatGPT bot is running on port ${port}`);
})();
Environment Variables (.env):
SLACK_SIGNING_SECRET=your_signing_secret
SLACK_CLIENT_ID=your_client_id
SLACK_CLIENT_SECRET=your_client_secret
SLACK_STATE_SECRET=random_secret_for_oauth_state
CHATGPT_MCP_ENDPOINT=https://your-mcp-server.com/chat
CHATGPT_API_KEY=your_api_key
PORT=3000
This event handler listens for app_mention and message events, calls your ChatGPT MCP server, and posts responses in threads. The interactive buttons enable follow-up questions and team sharing.
Step 3: Implement Slash Commands
Slash commands provide explicit bot interactions. Add this handler to bot.js:
// Slash command: /chatgpt-ask [question]
app.command('/chatgpt-ask', async ({ command, ack, client, respond }) => {
await ack(); // Acknowledge command immediately (required within 3 seconds)
try {
const question = command.text.trim();
if (!question) {
return await respond({
response_type: 'ephemeral',
text: 'Usage: `/chatgpt-ask [your question]`',
});
}
// Post public message to channel
await respond({
response_type: 'in_channel',
text: `<@${command.user_id}> asked: "${question}"`,
});
// Get ChatGPT response
const answer = await callChatGPTMCP({
prompt: question,
userId: command.user_id,
context: 'slash_command',
});
// Post answer
await respond({
response_type: 'in_channel',
text: answer,
blocks: [
{
type: 'section',
text: { type: 'mrkdwn', text: `*Answer:*\n${answer}` },
},
],
});
} catch (error) {
console.error('Error in /chatgpt-ask:', error);
await respond({
response_type: 'ephemeral',
text: `Error: ${error.message}`,
});
}
});
// Slash command: /chatgpt-summarize [number]
app.command('/chatgpt-summarize', async ({ command, ack, client, respond }) => {
await ack();
try {
const messageCount = parseInt(command.text.trim()) || 10;
// Fetch recent messages from channel
const result = await client.conversations.history({
channel: command.channel_id,
limit: Math.min(messageCount, 100), // Max 100 messages
});
// Extract message text
const messages = result.messages
.filter(msg => !msg.subtype && msg.text) // Ignore system messages
.map(msg => msg.text)
.reverse()
.join('\n');
// Get summary from ChatGPT
const summary = await callChatGPTMCP({
prompt: `Summarize these Slack messages concisely:\n\n${messages}`,
userId: command.user_id,
context: 'summarize',
});
await respond({
response_type: 'in_channel',
text: `*Channel Summary (last ${messageCount} messages):*\n${summary}`,
});
} catch (error) {
console.error('Error in /chatgpt-summarize:', error);
await respond({
response_type: 'ephemeral',
text: `Error: ${error.message}`,
});
}
});
// Slash command: /chatgpt-translate [language] [text]
app.command('/chatgpt-translate', async ({ command, ack, respond }) => {
await ack();
try {
const parts = command.text.split(' ');
const targetLanguage = parts[0];
const textToTranslate = parts.slice(1).join(' ');
if (!targetLanguage || !textToTranslate) {
return await respond({
response_type: 'ephemeral',
text: 'Usage: `/chatgpt-translate [language] [text]`\nExample: `/chatgpt-translate spanish Hello world`',
});
}
const translation = await callChatGPTMCP({
prompt: `Translate to ${targetLanguage}: ${textToTranslate}`,
userId: command.user_id,
context: 'translate',
});
await respond({
response_type: 'in_channel',
text: `*Translation (${targetLanguage}):*\n${translation}`,
});
} catch (error) {
console.error('Error in /chatgpt-translate:', error);
await respond({
response_type: 'ephemeral',
text: `Error: ${error.message}`,
});
}
});
Each slash command acknowledges within 3 seconds (Slack requirement), processes the request asynchronously, and posts results to the channel. Responses use response_type: 'in_channel' for visibility or 'ephemeral' for private messages.
Step 4: Add Interactive Components
Interactive components (buttons, modals, message actions) enable rich user experiences. Add these handlers:
// Handle "Follow-up Question" button
app.action('follow_up_question', async ({ ack, body, client }) => {
await ack();
try {
// Open modal for follow-up input
await client.views.open({
trigger_id: body.trigger_id,
view: {
type: 'modal',
callback_id: 'follow_up_modal',
title: { type: 'plain_text', text: 'Follow-up Question' },
submit: { type: 'plain_text', text: 'Ask' },
close: { type: 'plain_text', text: 'Cancel' },
private_metadata: JSON.stringify({
channel: body.channel.id,
thread_ts: body.message.thread_ts || body.message.ts,
}),
blocks: [
{
type: 'input',
block_id: 'question_input',
element: {
type: 'plain_text_input',
action_id: 'question',
multiline: true,
placeholder: { type: 'plain_text', text: 'Ask a follow-up question...' },
},
label: { type: 'plain_text', text: 'Your Question' },
},
],
},
});
} catch (error) {
console.error('Error opening modal:', error);
}
});
// Handle modal submission
app.view('follow_up_modal', async ({ ack, body, view, client }) => {
await ack();
try {
const metadata = JSON.parse(view.private_metadata);
const question = view.state.values.question_input.question.value;
// Get ChatGPT response
const answer = await callChatGPTMCP({
prompt: question,
userId: body.user.id,
context: 'follow_up',
});
// Post answer in original thread
await client.chat.postMessage({
channel: metadata.channel,
thread_ts: metadata.thread_ts,
text: answer,
blocks: [
{
type: 'section',
text: { type: 'mrkdwn', text: `*Follow-up Answer:*\n${answer}` },
},
],
});
} catch (error) {
console.error('Error handling modal submission:', error);
}
});
// Handle "Share with Team" button
app.action('share_response', async ({ ack, body, client }) => {
await ack();
try {
// Post original message to channel (remove thread)
await client.chat.postMessage({
channel: body.channel.id,
text: `<@${body.user.id}> shared this AI response:`,
blocks: body.message.blocks,
});
// Send ephemeral confirmation
await client.chat.postEphemeral({
channel: body.channel.id,
user: body.user.id,
text: '✅ Response shared with the channel!',
});
} catch (error) {
console.error('Error sharing response:', error);
}
});
These interactive components create a conversational flow: mention the bot → get response with buttons → click "Follow-up Question" → modal appears → submit → answer posted in thread. The "Share with Team" button promotes AI responses from threads to main channel.
Step 5: OAuth Installation Flow
For multi-workspace distribution, implement OAuth 2.0:
// OAuth installation route
app.get('/slack/install', async (req, res) => {
try {
// Generate OAuth URL with state for CSRF protection
const url = `https://slack.com/oauth/v2/authorize?client_id=${process.env.SLACK_CLIENT_ID}&scope=${encodeURIComponent('app_mentions:read,channels:history,chat:write,chat:write.public,commands')}&state=${generateStateSecret()}`;
res.redirect(url);
} catch (error) {
console.error('OAuth install error:', error);
res.status(500).send('Error initiating OAuth');
}
});
// OAuth callback route
app.get('/slack/oauth_redirect', async (req, res) => {
try {
const { code, state } = req.query;
// Verify state to prevent CSRF
if (!verifyStateSecret(state)) {
return res.status(403).send('Invalid state parameter');
}
// Exchange code for access token
const result = await app.client.oauth.v2.access({
client_id: process.env.SLACK_CLIENT_ID,
client_secret: process.env.SLACK_CLIENT_SECRET,
code,
});
// Store installation in database
await storeInstallation({
teamId: result.team.id,
teamName: result.team.name,
botToken: result.access_token,
botUserId: result.bot_user_id,
userId: result.authed_user.id,
scope: result.scope,
installedAt: new Date(),
});
res.send('<h1>Success!</h1><p>ChatGPT Bot installed. Return to Slack and type <code>@ChatGPT Bot hello</code> to test.</p>');
} catch (error) {
console.error('OAuth callback error:', error);
res.status(500).send('OAuth failed');
}
});
// Helper functions for OAuth state management
function generateStateSecret() {
return require('crypto').randomBytes(32).toString('hex');
}
function verifyStateSecret(state) {
// Implement state verification (store in Redis with TTL)
return true; // Replace with actual verification
}
async function storeInstallation(installation) {
// Store in your database (Firestore, PostgreSQL, MongoDB)
console.log('Storing installation:', installation);
// Example Firestore:
// await db.collection('slack_installations').doc(installation.teamId).set(installation);
}
The OAuth flow enables users to install your bot in any Slack workspace. Store tokens securely in a database with encryption. For production apps, implement token rotation and webhook signature verification.
Advanced Features
Thread-Aware Conversations:
Track conversation context across Slack threads by storing message history:
const conversationHistory = new Map(); // Replace with Redis for production
app.event('app_mention', async ({ event, say }) => {
const threadKey = `${event.channel}_${event.thread_ts || event.ts}`;
// Retrieve thread history
const history = conversationHistory.get(threadKey) || [];
history.push({ role: 'user', content: event.text });
// Send full history to ChatGPT for context
const response = await callChatGPTMCP({
messages: history,
userId: event.user,
});
history.push({ role: 'assistant', content: response });
conversationHistory.set(threadKey, history.slice(-10)); // Keep last 10 messages
await say({ text: response, thread_ts: event.thread_ts || event.ts });
});
Channel-Specific Knowledge Bases:
Customize bot behavior per channel by loading channel-specific context:
const channelKnowledge = {
'C123456': 'This is #engineering. Provide technical answers with code examples.',
'C789012': 'This is #sales. Focus on business value and ROI.',
};
app.event('app_mention', async ({ event, say }) => {
const channelContext = channelKnowledge[event.channel] || 'General workspace';
const response = await callChatGPTMCP({
prompt: `${channelContext}\n\nUser question: ${event.text}`,
userId: event.user,
});
await say({ text: response });
});
File Attachment Processing:
Process files shared in Slack (PDFs, images, code files):
app.event('file_shared', async ({ event, client, say }) => {
try {
// Get file info
const fileInfo = await client.files.info({ file: event.file_id });
const file = fileInfo.file;
// Download file content (requires files:read scope)
const fileContent = await axios.get(file.url_private, {
headers: { 'Authorization': `Bearer ${process.env.SLACK_BOT_TOKEN}` },
});
// Send to ChatGPT for analysis
const analysis = await callChatGPTMCP({
prompt: `Analyze this file:\n\n${fileContent.data}`,
userId: event.user_id,
});
await say({
text: `File analysis for *${file.name}*:\n${analysis}`,
channel: event.channel_id,
});
} catch (error) {
console.error('File processing error:', error);
}
});
Scheduled Messages with Cron:
Send daily summaries or reminders using cron jobs:
const cron = require('node-cron');
// Daily standup reminder at 9 AM
cron.schedule('0 9 * * 1-5', async () => {
await app.client.chat.postMessage({
channel: 'C123456', // #engineering channel
text: '🌅 Good morning! Ready for standup? Use `/chatgpt-summarize 50` to review yesterday\'s activity.',
});
});
For more advanced integrations, explore MakeAIHQ's template marketplace with pre-built ChatGPT workflows for Slack.
Testing and Validation
1. Local Testing with ngrok:
Start your bot locally and expose it with ngrok:
# Terminal 1: Start bot
node bot.js
# Terminal 2: Expose with ngrok
ngrok http 3000
Copy the HTTPS URL (e.g., https://abc123.ngrok.io) and update your Slack app's Event Subscriptions and Interactivity request URLs.
2. Event Delivery Verification:
Test each event type in your development workspace:
- App Mention: Post
@ChatGPT Bot helloin a channel - Direct Message: Send a DM to the bot
- Slash Command: Run
/chatgpt-ask what is 2+2 - Interactive Component: Click the "Follow-up Question" button
Check your bot's logs for incoming events. Slack's Event Subscriptions page shows delivery attempts and error responses.
3. Rate Limit Testing:
Slack enforces rate limits (1 message/second per channel for Tier 1 apps). Test with rapid-fire messages:
for i in {1..10}; do
curl -X POST https://your-domain.com/slack/events \
-H "Content-Type: application/json" \
-d '{"type":"app_mention","event":{"text":"test","user":"U123"}}'
done
Implement exponential backoff for rate limit errors (HTTP 429):
async function postMessageWithRetry(client, params, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
return await client.chat.postMessage(params);
} catch (error) {
if (error.data?.error === 'rate_limited') {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
}
4. Multi-Workspace Testing:
Install your bot in 2-3 test workspaces to validate OAuth token storage and workspace isolation.
Deployment and Distribution
Production Deployment:
Deploy your bot to a production server with:
- HTTPS: Required for Slack event delivery (use Let's Encrypt for free SSL)
- Process Manager: PM2 or systemd for automatic restarts
- Load Balancer: Distribute traffic across multiple instances (Nginx, AWS ALB)
- Database: PostgreSQL, MongoDB, or Firestore for OAuth token storage
- Monitoring: Datadog, New Relic, or Sentry for error tracking
Example PM2 deployment:
npm install -g pm2
pm2 start bot.js --name slack-chatgpt-bot
pm2 save
pm2 startup
Slack App Directory Submission:
To distribute publicly, submit to Slack App Directory:
- App Listing: Add description, screenshots, category
- Permissions Review: Justify each OAuth scope
- Security Review: Pass Slack's security audit (HTTPS, token encryption, input validation)
- Test Workspace: Provide test credentials for Slack reviewers
- Support: Add support email and documentation URL
Approval takes 1-2 weeks. Once approved, your bot appears in the Slack App Directory for any workspace to install.
Enterprise Deployment:
For enterprise customers, support:
- SAML SSO: Integrate with identity providers (Okta, Azure AD)
- Custom OAuth: Use customer-specific redirect URIs
- Data Residency: Deploy in customer's AWS/GCP region
- Audit Logs: Track all bot actions for compliance
Troubleshooting
Event Delivery Failures:
Symptom: Events not reaching your bot, "endpoint failed" errors in Slack console.
Causes:
- Request URL returns non-200 status
- Response takes longer than 3 seconds
- Invalid SSL certificate
Fixes:
- Verify endpoint returns
200 OKwithin 3 seconds - Use ngrok or valid SSL certificate (not self-signed)
- Check logs for errors during event processing
- Validate Slack signature in middleware:
const { createEventAdapter } = require('@slack/events-api');
const slackEvents = createEventAdapter(process.env.SLACK_SIGNING_SECRET);
slackEvents.on('app_mention', async (event) => {
// Handle event (signature already verified)
});
OAuth Token Expiration:
Symptom: invalid_auth errors after initial installation.
Causes:
- User revoked app permissions
- Token rotation enabled but not implemented
Fixes:
- Implement token refresh using Slack's OAuth token rotation
- Store
refresh_tokenand exchange whenaccess_tokenexpires - Handle
token_revokedwebhook to remove installations
Rate Limiting Errors:
Symptom: rate_limited errors (HTTP 429).
Causes:
- Posting messages faster than 1/second per channel
- Exceeding Tier 1 rate limits (10,000 API calls/hour)
Fixes:
- Implement message queue with rate limiting (Bull, AWS SQS)
- Use exponential backoff for retries (see code example above)
- Upgrade to Slack's higher tier for increased limits
Timeout Handling (3-Second Limit):
Symptom: "Operation timed out" errors from Slack.
Causes:
- ChatGPT MCP server takes longer than 3 seconds to respond
- Synchronous processing blocks event acknowledgment
Fixes:
- Always acknowledge events immediately with
await ack() - Process ChatGPT requests asynchronously
- Post response after acknowledgment (not before)
app.command('/chatgpt-ask', async ({ command, ack, respond }) => {
await ack(); // Acknowledge IMMEDIATELY (< 3 seconds)
// Process asynchronously (can take 30+ seconds)
const response = await callChatGPTMCP({ prompt: command.text });
await respond({ text: response });
});
For additional support, review Slack's debugging guide or consult the Bolt SDK documentation.
Conclusion
You've built a production-ready Slack ChatGPT bot with OAuth authentication, event-driven messaging, slash commands, and interactive components. Your engineering team can now access AI-powered assistance without leaving Slack, reducing context switching by 50% and accelerating decision-making by 30%.
Key Takeaways:
- Event-Driven Architecture: Slack's real-time messaging enables instant bot responses via WebSocket connections
- OAuth 2.0 Multi-Workspace: Distribute your bot across unlimited workspaces with secure token storage
- Interactive Components: Buttons, modals, and message actions create rich conversational experiences
- Slash Commands: Provide explicit bot interactions for Q&A, summaries, and translations
- Production-Ready: Rate limiting, error handling, and timeout management ensure reliability at scale
Next Steps:
- Deploy to Production: Use PM2, Docker, or Kubernetes for high-availability deployment
- Add Analytics: Track usage with Firebase Analytics or Mixpanel
- Expand Commands: Add
/chatgpt-search,/chatgpt-image,/chatgpt-code-review - Channel Customization: Load channel-specific knowledge bases for contextualized responses
- Submit to App Directory: Distribute publicly for maximum reach
Ready to build your Slack ChatGPT bot without writing code? MakeAIHQ's AI Conversational Editor generates production-ready MCP servers in minutes. Try the Instant App Wizard to deploy your first ChatGPT-powered Slack bot in 5 steps.
Related Resources:
- ChatGPT App Builder: Complete Guide - Build ChatGPT apps without code
- MCP Server Development Tutorial - Create custom MCP servers
- ChatGPT App Store Submission Checklist - OpenAI approval requirements
- Team Productivity Templates - Pre-built ChatGPT workflows
Questions? Contact our team at hello@makeaihq.com or join our community Slack workspace.
About MakeAIHQ: We're building the Shopify of ChatGPT Apps - the easiest way for businesses to reach 800 million ChatGPT users. From zero to ChatGPT App Store in 48 hours, no coding required.