Direct provider adapters
Public Slack, Teams, Discord, Telegram, and WhatsApp adapter entry points in @copilotkit/channels.
@copilotkit/channels supports two provider-connection models:
| Model | Channel declaration | Provider connection | Available providers |
|---|---|---|---|
| Managed Intelligence | createChannel({ name, identifyUser, agent }) | CopilotKit Intelligence stores provider credentials and owns ingress and egress | Slack and Microsoft Teams |
| Direct adapter | createChannel({ name, adapters, identifyUser, agent }) | Your Channels process stores provider credentials and owns the provider socket or webhook | Slack, 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.0The 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:
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.
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.