| title |
createBot |
| description |
Create a bot: wire platform adapters to an AG-UI agent, register tools, context, and slash commands, and get the handler surface. |
createBot is the entry point of @copilotkit/bot. It wires one or more platform adapters to an AG-UI agent and returns a Bot — the surface for registering turn handlers, interaction handlers, interrupt handlers, slash commands, and tools, plus start() / stop() lifecycle control.
For a complete walkthrough, see the Slack quickstart.
import { createBot } from "@copilotkit/bot";
function createBot(opts: CreateBotOptions): Bot;
Bot configuration.
The platform adapters to run, e.g. [`slack(...)`](/reference/bot/slack). `start()` brings every adapter up; `stop()` brings them down.
The AG-UI agent behind [`thread.runAgent()`](/reference/bot/classes/Thread) — a single instance or a per-conversation factory receiving the conversation's thread id. Optional: when omitted, calling `thread.runAgent()` throws.
Where snapshots of inline JSX handlers are persisted. The in-memory default loses actions on restart — see [ActionStore](/reference/bot/types/ActionStore) for the contract and durability tiers.
Tools forwarded to the agent as frontend tools on every run. See [defineBotTool](/reference/bot/functions/defineBotTool).
Knowledge folded into the agent's context on each run. A `ContextEntry` is `{ description: string; value: string }`.
Slash commands to register up front — equivalent to calling `bot.onCommand` per command. See [defineBotCommand](/reference/bot/functions/defineBotCommand).
The bot's registration and lifecycle surface.
Register a turn handler. `BotHandler` receives `{ thread, message }` — a [`Thread`](/reference/bot/classes/Thread) and the incoming message (`{ text, user, ref, platform }`). On Slack one mention handler covers @-mentions, replies in threads the bot owns, and DMs.
Register a turn handler that fires only when **no** mention handler is registered — routing is mention-preferred (see Behavior).
Escape-hatch handler for a known action `id`, bypassing the action registry. `ctx.action.value` is typed as `TValue`. Most bots don't need this — inline `onClick` handlers on [`Button`](/reference/bot/components/Button) are bound automatically.
Handle a captured agent interrupt (a LangGraph-style `on_interrupt` custom event). The handler typically posts a picker and resumes the run with [`thread.resume(value)`](/reference/bot/classes/Thread) when the user answers.
Register a slash command — a full [`BotCommand`](/reference/bot/functions/defineBotCommand), or the shorthand overload `onCommand(name, handler)` for a free-text command. Commands delivered by the platform but not registered here are ignored.
Register a tool (alternative to `opts.tools`). Must be called before `start()` — the tool descriptors handed to the agent are computed at startup.
Bring all adapters up. Also forwards declared commands to adapters that implement `registerCommands` (e.g. a Discord-style application-command API); adapters without it — including Slack — are skipped.
Bring all adapters down.
import { createBot } from "@copilotkit/bot";
import { slack, defaultSlackTools, defaultSlackContext } from "@copilotkit/bot-slack";
const bot = createBot({
adapters: [
slack({
botToken: process.env.SLACK_BOT_TOKEN!,
appToken: process.env.SLACK_APP_TOKEN!,
}),
],
agent: (threadId) => makeAgent(threadId),
tools: [...defaultSlackTools, ...appTools],
context: [...defaultSlackContext, ...appContext],
});
bot.onMention(async ({ thread }) => {
await thread.runAgent();
});
await bot.start();
- Mention-preferred routing — there is no per-turn "kind": when any
onMention handler is registered, all turns route to the mention handlers; otherwise onMessage handlers fire. Registering identical handlers on both never double-fires.
- Expired actions are swallowed — a click whose snapshot is gone (e.g. after a restart with the in-memory store) raises
ActionExpiredError internally; createBot swallows it, so the click is acked but ignored and no message is posted.
- Commands are matched case-insensitively and without the leading slash.
- No agent, no
runAgent — omitting agent is fine for bots that only post UI, but thread.runAgent() will throw.