Back to Copilotkit

defineBotCommand

showcase/shell-docs/src/content/reference/bot/functions/defineBotCommand.mdx

1.60.13.8 KB
Original Source

Overview

defineBotCommand defines a slash command with full type inference: ctx.options is inferred from the options schema. Commands are registered via createBot({ commands }) or bot.onCommand, and routed to the matching handler when the platform delivers an invocation.

Signature

ts
import { defineBotCommand } from "@copilotkit/bot";

function defineBotCommand<Schema extends ObjectSchema>(
  command: BotCommand<Schema>,
): BotCommand<Schema>;

Parameters

<PropertyReference name="command" type="BotCommand<Schema>" required> The command definition. <PropertyReference name="name" type="string" required> Command name without the leading slash (e.g. `"triage"`). Matched case-insensitively. </PropertyReference> <PropertyReference name="description" type="string"> Help text; also the registration label on surfaces that register commands up front (e.g. a Discord-style application-command API). </PropertyReference> <PropertyReference name="options" type="ObjectSchema"> Optional Standard Schema for typed options. Used natively on surfaces that deliver structured args; on text-only surfaces (Slack) it's unused — read `ctx.text`. </PropertyReference> <PropertyReference name="handler" type="(ctx: CommandContext) => void | Promise<void>" required> The command handler. </PropertyReference> </PropertyReference>

CommandContext

<PropertyReference name="thread" type="Thread" required> The conversation the command was invoked in. </PropertyReference> <PropertyReference name="command" type="string" required> The invoked command name, normalized (no leading slash, lower-cased). </PropertyReference> <PropertyReference name="text" type="string" required> Raw argument string after the command name — the form Slack delivers. </PropertyReference> <PropertyReference name="options" type="TOptions" required> Parsed, typed options. Populated on surfaces with native structured args; empty on text-only surfaces. </PropertyReference> <PropertyReference name="user" type="PlatformUser"> The invoking user, when the surface provides it. </PropertyReference> <PropertyReference name="platform" type="string" required> The active surface, e.g. `"slack"`. </PropertyReference>

Usage

tsx
import { defineBotCommand } from "@copilotkit/bot";
import { z } from "zod";

const triage = defineBotCommand({
  name: "triage",
  description: "Summarize and file the current thread.",
  options: z.object({ priority: z.enum(["low", "high"]).optional() }),
  async handler({ thread, text }) {
    await thread.runAgent({ prompt: `Triage: ${text}` });
  },
});

A slash command's text is never posted to the channel, so it isn't in the history the adapter reconstructs — pass it to the agent explicitly with runAgent({ prompt }).

Behavior

  • Declare commands with the platform — platforms only deliver commands they know about. On Slack, every command must also be declared in the app configuration (the manifest's slash_commands section, or "Slash Commands" in the app settings); an undeclared command is silently dropped, even over Socket Mode. See the Slack quickstart.
  • Matching is case-insensitive and ignores the leading slash; commands delivered by the platform but not registered on the bot are ignored.
  • Up-front registration — on start(), declared commands are forwarded to adapters that implement registerCommands (e.g. a Discord-style application-command API); adapters without it, including Slack, are skipped.