# Overview

> What the Channels SDK exposes: the five-piece mental model (Channel, Thread, Tools, UI, Context), the you-run vs Intelligence-manages boundary, runtime assumptions (Node.js 22+, long-running process, no serverless), and the shortest path to a first online Channel.

- Repository: CopilotKit/channels-sdk
- GitHub: https://github.com/CopilotKit/channels-sdk
- Human docs: https://grok-wiki.com/public/docs/copilotkit-channels-sdk-4c947e3e6161
- Complete Markdown: https://grok-wiki.com/public/docs/copilotkit-channels-sdk-4c947e3e6161/llms-full.txt

## Source Files

- `README.md`
- `.agents/skills/build-channels-agent/SKILL.md`
- `examples/minimal-channel/package.json`
- `AGENTS.md`

---

---
title: "Overview"
description: "What the Channels SDK exposes: the five-piece mental model (Channel, Thread, Tools, UI, Context), the you-run vs Intelligence-manages boundary, runtime assumptions (Node.js 22+, long-running process, no serverless), and the shortest path to a first online Channel."
---

The Channels SDK (`@copilotkit/channels`, MIT-licensed) connects one AG-UI-compatible agent to Slack, Microsoft Teams, Discord, Telegram, and WhatsApp with native interactive UI. You write handlers, tools, and JSX-rendered messages once; per-platform adapters translate the same message tree into Slack Block Kit, Teams Adaptive Cards, or Discord components. The agent keeps its own model, tools, and business logic — the built-in agent, LangGraph, CrewAI, Mastra, Pydantic AI, Google ADK, or any custom AG-UI agent all attach through the same `agent` factory. This repository carries the docs entry point, the `build-channels-agent` skill (the API authority under `.agents/skills/`), and runnable examples; the SDK implementation itself lives in `CopilotKit/CopilotKit` under `packages/channels`.

## The five-piece mental model

Every Channels program is built from the same five pieces:

| Piece | What it is | Primary API |
| --- | --- | --- |
| **Channel** | The unit you configure and attach handlers to | `createChannel()` returns a `Channel` |
| **Thread** | The per-conversation handle passed to every handler; you render and drive the conversation through it | `thread.post`, `thread.runAgent`, `thread.awaitChoice`, `thread.subscribe`, … |
| **Tools** | Typed functions the agent can call, validated by any Standard Schema library (Zod, Valibot, ArkType) | `defineChannelTool` |
| **UI** | JSX from `@copilotkit/channels` that renders natively per platform and degrades gracefully where a node is unsupported | `<Message>`, `<Section>`, `<Actions>`, `<Button>`, … |
| **Context** | `{ description, value }` entries injected into the agent's prompt per run | `createChannel({ context })` or `thread.runAgent({ context })` |

<Warning>
The API is `createChannel`, `defineChannelTool`, `defineChannelCommand`, and `ChannelToolContext`. An earlier pre-release used `Bot`-prefixed names (`createBot`, `defineBotTool`, `BotToolContext`); they exist nowhere in the shipped packages and importing them fails to compile.
</Warning>

## The boundary: you run vs Intelligence manages

Your agent and application logic run in your infrastructure. CopilotKit Intelligence manages the platform connection and delivers each turn to your long-running Channels process. A CopilotKit Intelligence API key is required (free tier available); there is no standalone way to run a Channel.

```mermaid
flowchart LR
    subgraph platforms["Messaging platforms"]
        slack["Slack / Teams / Discord"]
    end
    subgraph intelligence["CopilotKit Intelligence manages"]
        ingress["Platform credentials & ingress"]
        delivery["Credentialed delivery & reconnects"]
        registry["Runtime registration & health"]
    end
    subgraph yours["You run (long-running Node 22+ process)"]
        listener["createCopilotNodeListener"]
        runtime["CopilotRuntime + Channel"]
        agent["AG-UI agent + tools + state"]
    end
    slack -->|platform event| ingress
    ingress -->|gateway socket| listener
    listener --> runtime
    runtime -->|AG-UI| agent
    runtime -->|rendered JSX| delivery
    delivery -->|native platform UI| slack
```

| You run | CopilotKit Intelligence manages |
| --- | --- |
| Your agent, model credentials, tools, and business logic | Slack and Microsoft Teams platform credentials |
| The long-running Channels listener | Platform ingress and credentialed delivery |
| Application state, deployment, and logs | Runtime registration, health, and reconnects |

In the default **managed Channel** path there is no adapter in your code and no platform token in your process — Intelligence holds the credentials and you add platforms in its dashboard. Passing `adapters: [slack({ botToken, appToken })]` is the secondary, direct path for when you own the platform connection yourself.

## Runtime assumptions

- **Node.js 22 or later.** The launcher needs the global `WebSocket`.
- **A long-running process or container.** A Channel owns a persistent gateway connection to Intelligence; a serverless request handler cannot host one.
- **ESM.** The startup path uses top-level `await`, so the project needs `"type": "module"` (`npm pkg set type=module`).
- **No `channel.start()`.** The runtime owns the lifecycle: attach the Channel to a `CopilotRuntime` and create a listener with `createCopilotNodeListener` — creating the listener is what starts the Channel.
- **Paired packages.** `@copilotkit/channels` and `@copilotkit/runtime` ship as a tested pair; upgrade them together.

## Shortest path to a first online Channel

<Steps>
<Step title="Create a managed Channel in CopilotKit Intelligence">
Create a Channel and connect Slack in the Intelligence dashboard. Keep the Channel **Code** and the project-scoped API key — `createChannel({ name })` must equal that Channel Code exactly.
</Step>
<Step title="Install the SDK pair">

```sh
npm install @copilotkit/channels @copilotkit/runtime
npm install --save-dev tsx typescript @types/node
npm pkg set type=module
```

</Step>
<Step title="Write the listener">
Create the Channel, attach a handler, and start it through the runtime:

```ts
import { createChannel } from "@copilotkit/channels";
import { CopilotRuntime, CopilotKitIntelligence } from "@copilotkit/runtime/v2";
import { createCopilotNodeListener } from "@copilotkit/runtime/v2/node";

const channel = createChannel({
  name: process.env.CHANNEL_CODE!,
  identifyUser: "platform",
  agent: makeAgent, // (threadId) => any AG-UI agent
});

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

const runtime = new CopilotRuntime({
  agents: {},
  intelligence: new CopilotKitIntelligence({
    apiKey: process.env.INTELLIGENCE_API_KEY!,
  }),
  channels: [channel],
});

const listener = createCopilotNodeListener({ runtime, basePath: "/api/copilotkit" });
```

</Step>
<Step title="Start and verify">

```sh
node --env-file=.env --import tsx channel.ts
```

Gate the deploy on real status — `ready()` also resolves on `setup_required`:

```ts
await listener.channels.ready({ timeoutMs: 30_000 });
if (listener.channels.status().overall !== "online") {
  throw new Error("Channel is not online");
}
```

When Intelligence reports **Online**, invite the app to a Slack channel and mention it — the agent receives the conversation and replies in the thread.
</Step>
</Steps>

<Tip>
The fastest path is agent-driven: `npx copilotkit@latest channels setup` installs a pointer skill that fetches the current workflow from `copilotkit.ai/channels-guide.md` and walks your coding agent through the project, the managed Channel, the provider app, and the runtime.
</Tip>

## What this repository contains

:::files
```
channels-sdk/
├── README.md                          # Product overview + hand-built quickstart
├── AGENTS.md                          # Which skill owns which task
├── .agents/skills/
│   └── build-channels-agent/SKILL.md  # Canonical API authority (mirrored via .claude symlink)
└── examples/
    ├── minimal-channel/               # Smallest complete listener (4 files)
    └── OpenTag/                       # Flagship app, pinned git submodule
```
:::

The `minimal-channel` example splits the listener into `lib/channel.ts` (Channel + handlers), `lib/runtime.ts` (runtime and Intelligence wiring), `lib/env.ts` (fail-fast env loading), and `server.ts` (`ready()` gate, HTTP server, `SIGINT` teardown). OpenTag is a complete production-shaped application — a Python LangGraph agent over AG-UI with Slack and Teams surfaces — fetched with `git submodule update --init examples/OpenTag`.

## Next

<CardGroup cols={2}>
  <Card title="Installation" href="/installation">
    Install the version-locked package pair, enforce ESM, and pin @ag-ui/client to avoid the duplicate-AbstractAgent compile failure.
  </Card>
  <Card title="Quickstart" href="/quickstart">
    Build the first managed Channel end to end and verify status().overall === "online".
  </Card>
  <Card title="Architecture and the runtime boundary" href="/architecture">
    How a turn flows from platform event through Intelligence to your process and back.
  </Card>
  <Card title="Set up with a coding agent" href="/coding-agent-setup">
    The npx copilotkit@latest channels setup path and the hosted channels-guide.md workflow.
  </Card>
  <Card title="Minimal Channel example" href="/minimal-channel-example">
    The smallest complete listener, file by file, with the no-model-call verification trick.
  </Card>
  <Card title="Channel lifecycle and status" href="/channel-lifecycle">
    The six SDK status values, why ready() is not proof of life, and teardown ordering.
  </Card>
</CardGroup>
