Skip to main content

Chat Gateway

The Chat Gateway is the server-side routing layer behind Codebolt's channel plugins. It lets a plugin receive messages from an external surface, map them into stable Codebolt threads, run the right agent, and route replies back to the originating platform.

Use this when you want Codebolt to act through:

  • Telegram, Slack, Discord, Teams, or WhatsApp
  • a custom operator console or support inbox
  • a branded AI character with stable cross-session memory
  • any persistent message surface that should keep its own routing rules
Chat gateway architecture showing external surfaces, a channel plugin, the server gateway modules, persistent routing state, thread history, and the agent process.Persistent Messaging Through The Chat GatewayExternal SurfacesAny message source can connect here as long as the plugin can normalize it into stable routing fields.TelegramSlackDiscordCustom WebchatPLUGINChat Gateway Pluginplatform SDK + config UI + `plugin.gateway`What the plugin ownsconnect to the platformload config from `kvStore`call `registerChannel()` and `routeMessage()`SRVCodebolt Server Chat Gatewaystable thread mapping, agent lifecycle, reply dispatchGHGateway Handlernormalize inbound messageregister channel + reply targetRGRouting Gatewayresolve thread + agentqueue work or spawn processRRResponse Routerwatch gateway-managed threadsdispatch replies back to pluginReply path and proactive path stay separate`gateway.reply` returns conversation output. `gateway.messageToChannel` pushes a fresh outbound message.Persistent Routing State`.codebolt/channels.json` stores channel config and status`.codebolt/gateway-thread-map.json` stores lookup-key to thread mappingsthe real conversation history remains in the thread systemThread Contexthistory, queued steps, and conversation memoryAgent Processspawn or reuse based on thread stateplatform events arriverouteMessagegateway.replyregisterChanneloperator choices stay separate from server routing filesresolve threadspawn or queueagent replies flow back upResult: the plugin handles platform IO while the server owns persistence, routing, and the return path.

What This Gateway Actually Does

A chat gateway plugin does not talk to agents directly. It connects to the server over the plugin WebSocket, and the server handles the heavy routing work:

  1. the plugin registers a channel entry so it appears in routing rules
  2. the plugin forwards external messages with plugin.gateway.routeMessage(...)
  3. the server resolves a thread using the configured thread strategy
  4. the server either spawns the target agent or queues work on an existing thread
  5. the response router intercepts agent replies and returns them to the plugin
  6. the plugin delivers the reply back to the external system

This gives you persistent conversations without reimplementing thread resolution, agent process management, or reply dispatch in every plugin.

Gateway Versus Channel Plugin

These terms are related but not identical:

  • Chat Gateway: the server routing system in packages/server/src/gateway and packages/server/src/pluginLib/gatewayHandler.ts
  • Channel plugin: the plugin authoring pattern that uses plugin.gateway and declares "type": "channel" in package.json

The manifest type remains channel. The docs use Chat Gateway because the system is broader than just "bot connectors". The same routing model can support persistent AI characters and other long-lived conversational surfaces.

What Makes It Persistent

Persistence comes from server-owned state, not from the plugin process alone:

  • .codebolt/channels.json stores the registered channel configuration
  • .codebolt/gateway-thread-map.json stores lookup-key to thread mappings
  • the normal thread store keeps the actual conversation history and queued work

That means a plugin can disconnect and reconnect while the conversation identity still survives, as long as you keep the same routing inputs such as sourceId, threadStrategy, userId, or externalThreadId.

Main Plugin SDK Surface

The plugin-side API is intentionally small:

await plugin.gateway.registerChannel({
name: 'Telegram Support',
platform: 'telegram',
agentId: 'support-agent',
threadStrategy: 'per-conversation',
});

await plugin.gateway.routeMessage({
source: 'channel',
sourceId: 'plugin-telegram-support',
threadStrategy: 'per-conversation',
agentId: 'support-agent',
text: incoming.text,
userId: incoming.userId,
externalThreadId: incoming.chatId,
replyTo: {
channelId: 'telegram',
externalThreadId: incoming.chatId,
userId: incoming.userId,
},
});

plugin.gateway.onReply(async (reply) => {
await sendToPlatform(reply.externalThreadId, reply.text);
});

plugin.gateway.onMessageToChannel(async (message) => {
await sendToPlatform(message.targetId, message.text);
});

Good Fits

The chat gateway pattern is the right choice when you need:

  • inbound messages from an external messaging system
  • stable mapping from external identity to Codebolt thread identity
  • agent replies returned over the same external channel
  • proactive outbound messages from Codebolt to that channel
  • long-lived personas or support agents that must stay coherent over time

Page Guide

See Also