How Maka Integrates with Messaging Platforms Like Slack and Discord: A Bot Bridge Architecture
Maka integrates with Slack and Discord through a unified Bot Bridge pattern where platform-specific implementations—SlackBotBridge and DiscordBotBridge—translate external protocols into a common internal event system managed by the BotRegistry.
Maka's messaging platform integration is built on a clean abstraction layer that treats every chat service as a Bot Bridge. This architecture lets developers add new platforms without touching core runtime logic. In apache/maka, the bridge pattern lives in packages/runtime/src/bots/ and provides consistent lifecycle management, event transformation, and message delivery across diverse protocols.
The Bot Bridge Interface: Maka's Integration Foundation
Every messaging platform in Maka implements the BotBridge interface. This contract defines four core methods:
start()– Opens the platform connectionstop()– Gracefully closes the connectionsendMessage(chatId, text, options?)– Delivers outbound messagessendTypingIndicator?(chatId)– Optional typing notifications
Both SlackBotBridge and DiscordBotBridge satisfy this interface, allowing the BotRegistry to manage them polymorphically. The registry itself, located at packages/runtime/src/bots/bot-registry.ts, handles instantiation, event wiring, and provides a uniform API for sending messages.
Slack Integration: Socket Mode and Web API
The SlackBotBridge implementation in packages/runtime/src/bots/slack-bridge.ts connects to Slack using dual clients: @slack/socket-mode for real-time events and @slack/web-api for outbound messages.
Connection Architecture
Slack integration uses SocketModeClient to maintain a persistent WebSocket connection. This approach avoids public URL requirements and handles reconnection automatically. The bridge authenticates with both a bot token (xoxb-) and an app-level token (xapp-).
Event Flow: Slack to Maka
Incoming Slack events arrive as SlackEventEnvelope objects. The bridge transforms these through slackMessageToEvent() into the neutral BotMessageEvent shape:
| Slack Field | Maka Field |
|---|---|
event.ts |
messageId |
event.channel |
chatId |
event.text |
text |
event.thread_ts |
threadId |
Outbound Message Handling
Outbound messages use WebClient.chat.postMessage. When you supply replyToMessageId, the bridge automatically sets thread_ts to preserve conversation context:
import { SlackBotBridge } from '@maka/runtime/bots/slack-bridge';
const slackSettings = {
enabled: true,
token: 'xoxb-SLACK-BOT-TOKEN',
appSecret: 'xapp-SLACK-APP-TOKEN',
};
const bridge = new SlackBotBridge(slackSettings);
await bridge.start();
// Send with thread reply
const ts = await bridge.sendMessage(
'C01ABCD2EFG',
'Reply in thread',
{ replyToMessageId: '1612345678.000200' }
);
await bridge.stop();
Discord Integration: Gateway Bridge and REST API
The DiscordBotBridge in packages/runtime/src/bots/discord-bridge.ts extends GatewayBridgeBase to handle Discord's more complex WebSocket gateway protocol with its opcodes, heartbeats, and resume sequences.
Low-Level Gateway Management
Discord requires explicit WebSocket lifecycle management. The bridge implements:
fetchGatewayUrl()– Retrieves the gateway endpoint with bot authenticationbuildIdentifyPayload()– Constructs the identify payload with intent flagsbuildResumePayload()– Handles session resumption for reconnections
Intent-Based Event Subscription
Unlike Slack's automatic event streaming, Discord uses gateway intents to filter which events the bot receives. The DiscordBotBridge configures these in buildIdentifyPayload, ensuring only relevant events like MESSAGE_CREATE are processed.
Message Handling: Chunking and Rate Limits
Discord imposes a 2000-character limit on message content. The bridge automatically handles this through splitDiscordContent(), breaking long messages into sequential chunks. Rate limiting is managed via classifyDiscordSendResponse() which parses Discord's X-RateLimit-Remaining headers:
import { DiscordBotBridge } from '@maka/runtime/bots/discord-bridge';
const discordSettings = {
enabled: true,
token: 'Bot DISCORD-TOKEN',
};
const bridge = new DiscordBotBridge('discord', discordSettings);
await bridge.start();
// Automatically chunked if >2000 chars
const longText = 'A'.repeat(5000);
const messageId = await bridge.sendMessage('123456789012345678', longText);
await bridge.stop();
Threading via Message References
Discord replies use message_reference objects rather than simple thread IDs. The buildDiscordSendBody() helper constructs these references when replyToMessageId is provided, mapping to Discord's referenced_message.message_id field.
BotRegistry: The Central Hub for Messaging Platform Integration
The BotRegistry orchestrates all platform bridges. Located at packages/runtime/src/bots/bot-registry.ts, it provides three key capabilities:
- Bridge instantiation – Creates
SlackBotBridgeorDiscordBotBridgebased onsettings.channelsconfiguration - Event aggregation – Forwards
'message'and'statusChange'events from all bridges to core runtime handlers - Unified send API –
registry.sendMessage(platform, chatId, text, options)dispatches to the correct bridge
Complete Working Example
import { BotRegistry } from '@maka/runtime/bots/bot-registry';
const registry = new BotRegistry({
onIncomingMessage: (msg) => console.log('From', msg.platform, ':', msg.text),
onStatusChange: (status) => console.log(status.platform, 'is', status.state),
});
// Apply configuration for multiple platforms
await registry.applySettings({
channels: {
slack: { enabled: true, token: 'xoxb-…', appSecret: 'xapp-…' },
discord: { enabled: true, token: 'Bot …' },
},
});
// Send to either platform identically
await registry.sendMessage('slack', 'C12345678', 'Hello Slack!');
await registry.sendMessage('discord', '987654321012345678', 'Hello Discord!');
Key Architectural Decisions in Maka's Messaging Integration
Protocol abstraction strength – The BotMessageEvent neutral format decouples business logic from platform specifics. Fields like platform, chatId, messageId, and threadId mean runtime code never branches on if (platform === 'slack').
Connection strategy divergence – Slack uses Socket Mode (managed WebSocket library), while Discord requires manual gateway implementation. Both resolve to the same event emitter pattern via their bridges.
Error handling scope – Platform-specific concerns (Discord rate limits, Slack token rotation) stay encapsulated in bridges. The registry only sees statusChange events: connecting, connected, disconnected, error.
Summary
- Maka's Bot Bridge pattern in
packages/runtime/src/bots/unifies Slack, Discord, and future platforms under one interface - SlackBotBridge uses
@slack/socket-modeand@slack/web-apiwith automatic thread context viathread_ts - DiscordBotBridge extends
GatewayBridgeBasefor manual gateway management, plus automatic message chunking and rate-limit handling - BotRegistry provides the central integration point with
applySettings()for configuration andsendMessage()for unified outbound delivery - Adding new messaging platforms requires only implementing the four-method
BotBridgeinterface
Frequently Asked Questions
How do I add a new messaging platform to Maka?
Implement the BotBridge interface in a new class following the SlackBotBridge and DiscordBotBridge patterns. Your bridge must handle connection lifecycle, transform incoming events to BotMessageEvent, and implement sendMessage() for outbound delivery. Register it in BotRegistry's instantiation logic, and it automatically participates in the unified event system.
Does Maka support Slack's HTTP Event Subscriptions instead of Socket Mode?
The current SlackBotBridge in packages/runtime/src/bots/slack-bridge.ts exclusively uses Socket Mode via @slack/socket-mode. HTTP Event Subscriptions would require a separate bridge implementation handling HTTP POST requests and signature verification instead of WebSocket connections.
How does Maka handle Discord's strict rate limits?
The DiscordBotBridge implements rate-limit awareness in classifyDiscordSendResponse(), which parses Discord's X-RateLimit-Remaining, X-RateLimit-Reset, and Retry-After headers. The bridge can queue or retry requests based on these values, though the exact retry strategy depends on your runtime configuration.
Can I use multiple Slack workspaces or Discord bots simultaneously?
Yes. The BotRegistry supports multiple bridge instances of the same platform type through distinct configuration keys. Each workspace or bot requires its own entry in settings.channels with unique tokens, and the registry instantiates separate SlackBotBridge or DiscordBotBridge instances for each.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →