How Archon Implements the Platform Adapter Pattern for Slack, Telegram, and Discord

Archon abstracts every chat service behind a standardized IPlatformAdapter interface, allowing Slack, Telegram, and Discord to integrate through isolated, type-safe adapter classes that normalize payloads into a unified Message schema.

The platform adapter pattern in coleam00/Archon decouples messenger-specific SDK logic from the core conversation engine. By enforcing a strict contract via the IPlatformAdapter interface, the repository enables seamless integration of Slack, Telegram, and Discord without polluting the orchestration layer with platform-specific code.

The IPlatformAdapter Contract

The core engine communicates exclusively through the IPlatformAdapter interface defined in the core package. This contract declares lifecycle methods—including init(), start(), stop(), sendMessage(), and onMessage()—that every messenger must implement.

Each platform lives in its own directory under packages/adapters/src/, containing a concrete class such as SlackAdapter, TelegramAdapter, or DiscordAdapter. These classes handle the respective SDK initialization, webhook polling or gateway connections, and payload parsing, while exposing only the standardized methods to the rest of the system.

Anatomy of a Platform Adapter

Every adapter follows a consistent four-file structure that encapsulates platform logic and security.

Adapter Class (adapter.ts)

The adapter.ts file implements IPlatformAdapter. It imports the platform's official SDK, manages connection state, and provides methods to translate between the external API format and Archon's internal Message type. For example, packages/adapters/src/chat/slack/adapter.ts wraps the Slack Bolt SDK, while packages/adapters/src/community/chat/discord/adapter.ts manages Discord.js gateway connections.

Authentication Module (auth.ts)

Security isolation happens in auth.ts. This module reads whitelist configuration from environment variables—such as SLACK_ALLOWED_USER_IDS, TELEGRAM_ALLOWED_USER_IDS, or DISCORD_ALLOWED_USER_IDS—and validates incoming update senders. Unauthorized requests are silently dropped with masked logging, ensuring credential handling never bleeds into the core engine.

Factory Function (index.ts)

The index.ts file exposes a factory function—createSlackAdapter(), createTelegramAdapter(), or createDiscordAdapter()—that accepts configuration objects and returns an initialized adapter instance. This pattern allows the core PlatformManager to import adapters without pulling in the heavy SDK dependencies of platforms that remain unused.

Type Definitions (types.ts)

Each adapter includes a types.ts file containing TypeScript interfaces that model raw platform payloads. These types map external schemas—like Discord's gateway events or Telegram's Update objects—to Archon's normalized Message structure, providing compile-time safety during payload transformation.

Data Flow Through the Platform Adapter Pattern

Archon processes chat interactions through a five-stage pipeline that remains identical regardless of the underlying messenger:

  1. Adapter Startup: The core bootstraps each adapter via its factory function (e.g., createSlackAdapter()), injecting tokens and whitelist arrays from environment variables.
  2. Authentication: Upon receiving an update, the adapter invokes its auth.validate() helper to check sender IDs against configured whitelists before proceeding.
  3. Message Normalization: Raw payloads convert into a platform-agnostic Message object containing conversationId, authorId, and content fields.
  4. Core Handling: The normalized message passes to the ConversationHandler orchestrator, which executes slash commands or workflows without knowing the source platform.
  5. Response Dispatch: The orchestrator's reply routes back through the same adapter's sendMessage() method, which uses the platform SDK to deliver the response to the user.

Implementation Examples by Platform

The following snippets demonstrate how Archon instantiates each adapter using environment-based configuration.

Slack Adapter

import { createSlackAdapter } from '@/adapters/chat/slack';

const slack = createSlackAdapter({
  token: process.env.SLACK_BOT_TOKEN!,
  allowedUserIds: process.env.SLACK_ALLOWED_USER_IDS?.split(',') ?? [],
});

await platformManager.registerAdapter(slack);
await slack.start(); // Begins polling Slack events

Source: packages/adapters/src/chat/slack/index.ts

Telegram Adapter

import { createTelegramAdapter } from '@/adapters/chat/telegram';

const telegram = createTelegramAdapter({
  token: process.env.TELEGRAM_BOT_TOKEN!,
  whitelist: process.env.TELEGRAM_ALLOWED_USER_IDS?.split(',') ?? [],
});

await platformManager.registerAdapter(telegram);
await telegram.start(); // Starts long-polling the Telegram Bot API

Source: packages/adapters/src/chat/telegram/index.ts

Discord Adapter

import { createDiscordAdapter } from '@/adapters/community/chat/discord';

const discord = createDiscordAdapter({
  token: process.env.DISCORD_BOT_TOKEN!,
  allowedUserIds: process.env.DISCORD_ALLOWED_USER_IDS?.split(',') ?? [],
});

await platformManager.registerAdapter(discord);
await discord.start(); // Connects to Discord's gateway

Source: packages/adapters/src/community/chat/discord/index.ts

Benefits of the Platform Adapter Pattern in Archon

This architectural approach delivers specific advantages for maintaining multi-platform chatbots:

  • Single-developer focus: Adding a new messenger requires creating only a new directory with the four standard files; the core engine remains untouched.
  • Strong typing: TypeScript guarantees that every adapter supplies required methods through the IPlatformAdapter interface, catching integration errors at compile time.
  • Isolation of secrets: Authentication logic lives adjacent to the platform SDK in auth.ts, keeping credential handling auditable and confined.
  • Plug-and-play configuration: The PlatformManager can enable or disable adapters through configuration alone, instantiating only the factories referenced in environment variables.

Summary

  • Archon uses the platform adapter pattern to abstract Slack, Telegram, and Discord behind the IPlatformAdapter interface.
  • Each platform implements four standardized files: adapter.ts, auth.ts, index.ts, and types.ts.
  • Factory functions like createSlackAdapter() allow the core to register messengers without importing unused SDKs.
  • The authentication module in each adapter validates whitelisted user IDs against environment variables before normalization.
  • Incoming payloads transform into a unified Message schema, enabling the ConversationHandler to process requests platform-agnostically.

Frequently Asked Questions

What is the platform adapter pattern in Archon?

The platform adapter pattern is an architectural strategy that isolates messenger-specific implementations—such as Slack's Bolt SDK or Discord's gateway—from Archon's core conversation logic. By forcing every chat service to conform to the IPlatformAdapter interface, the system treats Slack, Telegram, and Discord as interchangeable communication endpoints.

How does Archon handle authentication across different chat platforms?

Each adapter contains an auth.ts module that reads platform-specific environment variables (e.g., SLACK_ALLOWED_USER_IDS, TELEGRAM_ALLOWED_USER_IDS) to validate incoming message senders. This design keeps security checks close to the platform SDK while ensuring unauthorized users never reach the core orchestrator.

Where are the Slack, Telegram, and Discord adapters located in the codebase?

Slack and Telegram adapters reside in packages/adapters/src/chat/slack/ and packages/adapters/src/chat/telegram/ respectively. The Discord adapter lives in packages/adapters/src/community/chat/discord/. Each directory contains adapter.ts, auth.ts, index.ts, and types.ts files implementing the platform adapter pattern.

Can I add a new messenger platform without modifying Archon's core?

Yes. Create a new directory under packages/adapters/src/ containing an adapter.ts that implements IPlatformAdapter, an auth.ts for whitelist validation, an index.ts exporting a factory function, and a types.ts for payload modeling. The core PlatformManager consumes any object matching the interface, requiring zero changes to the conversation engine or workflow handlers.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →