Back to Copilotkit

Direct provider adapters

showcase/shell-docs/src/content/reference/channels/sdk/direct-adapters.mdx

1.64.26.3 KB
Original Source

@copilotkit/channels supports two provider-connection models:

ModelChannel declarationProvider connectionAvailable providers
Managed IntelligencecreateChannel({ name, provider, agent })CopilotKit Intelligence stores provider credentials and owns ingress and egressSlack and Microsoft Teams
Direct adaptercreateChannel({ name, adapters, 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/[email protected].

<Callout type="info" title="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. </Callout>

Declare a direct adapter

Install the umbrella package and its tested runtime version:

sh
npm install --save-exact @copilotkit/[email protected] @copilotkit/[email protected]

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:

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",
  adapters: [
    slack({
      botToken: required("SLACK_BOT_TOKEN"),
      appToken: required("SLACK_APP_TOKEN"),
    }),
  ],
  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. For direct adapters, provider is ignored. Do not combine the managed Intelligence adapter with direct adapters on the same Channel.

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

ts
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.

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

ts
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

ts
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

ts
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

ts
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 Slack and Teams guides in the provider picker document the production-ready managed path. Use this page when your deployment intentionally owns provider credentials, sockets, webhooks, and provider-specific operations.