Direct provider adapters

Public Slack, Teams, Discord, Telegram, and WhatsApp adapter entry points in @copilotkit/channels.


@copilotkit/channels supports two provider-connection models:

ModelChannel declarationProvider connectionAvailable providers
Managed IntelligencecreateChannel({ name, identifyUser, agent })CopilotKit Intelligence stores provider credentials and owns ingress and egressSlack and Microsoft Teams
Direct adaptercreateChannel({ name, adapters, identifyUser, agent })Your Channels process stores provider credentials and owns the provider socket or webhookSlack, Microsoft Teams, Discord, Telegram, and WhatsApp

Managed Intelligence support for Discord and WhatsApp is coming soon. Their direct adapters already ship in @copilotkit/channels@0.6.1.

Direct does not mean standalone

A direct adapter moves the provider connection into your process. The CopilotRuntime still owns the Channel lifecycle and uses an Intelligence connection. Direct provider traffic does not traverse the managed Realtime Gateway or its canonical delivery, retry, and durability layer, so your process owns transport reliability. There is no public channel.start() method.

Declare a direct adapter

Install the umbrella package and its tested runtime version:

npm install --save-exact @copilotkit/channels@0.6.1 @copilotkit/runtime@1.65.0

The package and all provider subpaths are ESM-only public exports. Use import; CommonJS require() is not supported.

Import adapters from the package's provider subpaths:

channel.ts
import { createChannel } from "@copilotkit/channels";
import { slack } from "@copilotkit/channels/slack";
import { makeAgent } from "./agent.js";

function required(name: string): string {
  const value = process.env[name];
  if (!value) throw new Error(`Missing required environment variable: ${name}`);
  return value;
}

export const channel = createChannel({
  name: "support-direct",
  identifyUser: "platform",
  adapters: [
    slack({
      botToken: required("SLACK_BOT_TOKEN"),
      appToken: required("SLACK_APP_TOKEN"),
      replyContinuation: {
        maxMessages: 8,
      },
    }),
  ],
  agent: makeAgent,
});

channel.onMessage(async ({ thread }) => {
  await thread.runAgent();
});

Pass this Channel to new CopilotRuntime({ channels: [channel], ... }) and start it through the runtime's Channels control, just as in the managed quickstarts. Intelligence-attached Slack and Teams connections select the managed provider; there is no provider option on createChannel. Direct adapters may coexist on the same Channel and keep their own provider traffic.

One direct Channel may contain multiple direct adapters. Its name must still be present and unique among the Channels declared on that CopilotRuntime.

Provider entry points

Slack

import {
  slack,
  SlackAdapter,
  type SlackAdapterOptions,
} from "@copilotkit/channels/slack";

SlackAdapterOptions requires botToken and appToken. Socket Mode is on by default. HTTP mode requires socketMode: false and a signingSecret. replyContinuation accepts messageByteLimit, maxMessages, and truncationMarker for long replies; the defaults are 11,000 UTF-8 bytes and 20 messages with a visible truncation notice.

The Slack entry point also exports its listener, renderers, codec, streaming helpers, conversation store, built-in context and tools, file helpers, and SLACK_LIMITS. Lower-level render and codec entry points are available from @copilotkit/channels/slack/render and @copilotkit/channels/slack/codec.

Microsoft Teams

import {
  teams,
  TeamsAdapter,
  type TeamsAdapterOptions,
} from "@copilotkit/channels/teams";

TeamsAdapterOptions accepts clientId, clientSecret, tenantId, and port. clientId and clientSecret are required for real Teams; tenantId may be omitted for a multi-tenant deployment. These values fall back to the lowercase clientId, clientSecret, and tenantId environment variables. All three may be omitted only for anonymous local development with the Microsoft 365 Agents Playground. The adapter serves POST /api/messages on port 3978 by default.

The Teams entry point also exports its server, Adaptive Card renderer, conversation store, message stream, interaction helpers, file helpers, and TEAMS_LIMITS. Renderer exports are also available from @copilotkit/channels/teams/render.

Discord

import {
  discord,
  DiscordAdapter,
  type DiscordAdapterOptions,
} from "@copilotkit/channels/discord";

DiscordAdapterOptions requires botToken and appId; set guildId to register slash commands immediately in one development guild. The entry point also exports its listener, renderer, command registration, conversation store, streaming helpers, built-in context and tools, file helpers, and DISCORD_LIMITS.

Enable the privileged Message Content Intent and Server Members Intent for the bot in the Discord Developer Portal. The adapter requests MessageContent and GuildMembers on every connection.

Telegram

import {
  telegram,
  TelegramAdapter,
  type TelegramAdapterOptions,
} from "@copilotkit/channels/telegram";

TelegramAdapterOptions requires a bot token. Ingress defaults to long-polling. Set mode: "webhook" and provide webhook configuration for a public webhook deployment. The entry point also exports its listener, renderer, conversation store, streaming helper, built-in context and tools, file helpers, and TELEGRAM_LIMITS.

WhatsApp

import {
  whatsapp,
  WhatsAppAdapter,
  type WhatsAppAdapterOptions,
} from "@copilotkit/channels/whatsapp";

WhatsAppAdapterOptions requires accessToken, phoneNumberId, appSecret, and verifyToken. The webhook server uses port 3000 and path /webhook by default. The entry point also exports its client, renderer, conversation and history stores, built-in context and tools, file helpers, and WA_LIMITS.

Capability boundaries

Direct and managed adapters do not have identical capabilities. For example, the direct Slack adapter supports modals, reactions, incremental streaming, and ephemeral messages. Managed Slack accepts the streaming API but buffers the stream and posts it once instead of updating incrementally; it does not support the other three capabilities. Check the direct adapter instance's read-only capabilities property when you own the adapter. Capability-result Thread methods can also return { ok: false }; handle that result instead of assuming a provider name guarantees one behavior.

The provider guides document the managed contract and each provider's release status. Use this page when your deployment intentionally owns provider credentials, sockets, webhooks, and provider-specific operations.