Channel API

createChannel options, properties, event handlers, and lifecycle methods.


createChannel(options) returns a Channel. This page lists every option it takes and every method it exposes.

import { createChannel } from "@copilotkit/channels";

const channel = createChannel({ name, agent, adapters });

createChannel options#

OptionTypeDescription
namestringProject-unique channel name. Required: the runtime keys the channel's lifecycle by it (and, for a managed channel, ties it to the dashboard setup).
agentAbstractAgent | (threadId: string) => AbstractAgentThe agent, or a per-thread factory.
adaptersPlatformAdapter[]Direct platform adapters attached at construction. The runtime starts them when it activates the channel.
provider"slack" | "teams"Managed delivery provider for a no-adapter (Intelligence) channel. Defaults to "slack". "teams" is SDK-ready but gated.
toolsChannelTool[]Tools exposed to the agent. See commands and the agent's own tools.
contextContextEntry[]{ description, value } entries forwarded to the agent each turn.
componentsChannelComponent[]Named JSX components. Register them so their handlers survive a restart. See the UI library.
commandsChannelCommand[]Slash commands. Forwarded to adapters that support them.
storeStoreConfigPersistence, per-thread state, and cross-platform history (see below).

store options#

OptionTypeDescription
stateStandardSchemaSchema for per-thread state. Types thread.state()/setState() and validates on write. See configuration.
adapterStateStoreDurable persistence backend. See Persistence.
identity, transcriptsCross-platform history keyed by a stable identity. See Transcripts.

Properties#

PropertyTypeDescription
namestring | undefinedThe name from createChannel({ name }).
adaptersreadonly PlatformAdapter[]Attached adapters (read-only snapshot).
provider"slack" | "teams" | undefinedManaged provider; undefined means the default ("slack").
commandNamesstring[]Declared slash-command names, normalized.

Event handlers#

Register these before the runtime activates the channel (before handler.channels.ready()).

onMessage / onMention / onThreadStarted#

channel.onMessage((ctx) => {});      // every delivered message
channel.onMention((ctx) => {});      // messages that @mention the bot
channel.onThreadStarted((ctx) => {}); // a conversation surface opened (e.g. Slack assistant pane)

onMessage and onMention hand you { thread, message }. message is an IncomingMessage (text, user, ref, platform, contentParts?). See the Thread API. onThreadStarted gives { thread, user? }.

onReaction#

channel.onReaction((evt) => {});                // any reaction, any message
channel.onReaction("refresh", (evt) => {});     // only this emoji
channel.onReaction(["fire", "tada"], (evt) => {}); // any of these

The ReactionEvent passed in:

FieldTypeDescription
emojiEmojiValueCanonical name when recognized, else the raw token.
rawEmojistringPlatform-native token.
addedbooleantrue = added, false = removed.
userPlatformUser?The reacting user, when reported.
messageIdstringId of the reacted message.
messageRefMessageRefPass to thread.update(messageRef, ui) to redraw it.
threadThreadPost back, run the agent, and so on.
adapterPlatformAdapterThe adapter that delivered it.
rawunknownThe raw platform payload.

See global reactions.

onCommand#

channel.onCommand(defineChannelCommand({ name, handler })); // full command
channel.onCommand("ask", (ctx) => {});                      // free-text by name

Passing commands to createChannel does the same registration. See commands.

onInteraction#

channel.onInteraction<{ id: string }>("approve", (ctx) => {
  ctx.action.value; // typed as { id: string }
});

Handle clicks on a specific action id. The context is the same InteractionContext a JSX onClick receives. Most of the time you use an inline onClick on the component instead.

onInterrupt#

channel.onInterrupt<{ question: string }>("ask", ({ payload, thread }) => {});

Handle an agent interrupt (an on_interrupt custom event). payload is the event's value, typed by the type argument.

onModalSubmit / onModalClose#

channel.onModalSubmit("file-issue", (evt) => {
  evt.values;   // submitted field values
  // return { errors } to keep the modal open
});
channel.onModalClose("file-issue", (evt) => {});

For platforms with modal/dialog support. Open a modal from an interaction with ctx.openModal(view).

Registration and lifecycle#

A channel has no public start()/stop(). Lifecycle is owned by the runtime: declare the channel on new CopilotRuntime({ channels: [channel] }), then drive it through the handler's channels control — handler.channels.ready() to activate and handler.channels.stop() to tear down. See the Quickstart for the full run pattern.

MethodSignatureDescription
tooltool(t: ChannelTool): voidRegister one tool (same as an entry in tools).
transcriptsTranscriptsCross-platform transcript store. See Transcripts.