Skip to content

Latest commit

 

History

History
126 lines (95 loc) · 5.01 KB

File metadata and controls

126 lines (95 loc) · 5.01 KB
title defineBotTool
description Define a typed BotTool — a frontend tool the agent can call whose handler runs in the bot with a Thread in scope.

Overview

defineBotTool defines a BotTool with full type inference: the handler's args are inferred from the parameters schema. A BotTool is forwarded to the agent as a frontend tool; when the agent calls it, the handler runs in the bot, with the conversation's Thread in scope — so a tool can read the thread, post JSX cards, or block on a human choice.

Signature

import { defineBotTool } from "@copilotkit/bot";

function defineBotTool<Schema extends ObjectSchema>(
  tool: BotTool<Schema>,
): BotTool<Schema>;

Parameters

The tool definition. Tool name the agent calls, e.g. `"read_thread"`. What the tool does — written for the model. This is the main lever for when the agent reaches for the tool. Any Standard Schema object schema (Zod, Valibot, ArkType, …). Converted to JSON Schema for the LLM, and used to validate the args on the way back in. Runs in the bot when the agent calls the tool. `args` is inferred from `parameters`. The return value is what the **agent (LLM) reads back** as the tool result: a `string` is sent as-is, `null`/`undefined` becomes an empty string, anything else is JSON-stringified automatically. Return something meaningful — the data itself for a data tool, a short confirmation (e.g. `"Displayed the issue card."`) for a tool that posts UI, or the actual error text on failure so the model can repair and retry.

BotToolContext

The single shared context every handler receives — there are no per-adapter generics:

The conversation the tool call belongs to. Platform power is reached only through capability-gated [`Thread`](/reference/bot/classes/Thread) methods (`getMessages`, `lookupUser`, `postFile`, `post`, …), which keeps tools portable across surfaces. The triggering message, when the adapter supplies it. The requesting user, when the adapter supplies it. Abort signal for long-running handlers, when the adapter supplies one. The active surface, e.g. `"slack"`.

Usage

A data tool

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

const readThread = defineBotTool({
  name: "read_thread",
  description: "Read the messages in the current conversation.",
  parameters: z.object({}),
  async handler(_args, { thread }) {
    return await thread.getMessages();
  },
});

A render tool (posts JSX)

A common pattern: the component's prop schema doubles as the tool's input schema, and the agent "renders" by calling the tool.

const issueCard = defineBotTool({
  name: "issue_card",
  description: "Render one issue as a rich card.",
  parameters: issueCardSchema,
  async handler(props, { thread }) {
    await thread.post(<IssueCard {...props} />);
    return "Displayed the issue card to the user.";
  },
});

A blocking human-in-the-loop tool

const confirmWrite = defineBotTool({
  name: "confirm_write",
  description: "Ask the user to approve a write before performing it.",
  parameters: z.object({ action: z.string() }),
  async handler({ action }, { thread }) {
    const choice = await thread.awaitChoice<{ confirmed: boolean }>(
      <ConfirmWrite action={action} />,
    );
    return choice ?? { confirmed: false }; // serialized for the agent automatically
  },
});

Behavior

  • Validation — args coming back from the model are validated against parameters; invalid args don't reach your handler.
  • Registration — pass tools via createBot({ tools }) or bot.tool(t); per-run extras go through thread.runAgent({ tools }). Tools must be registered before start().
  • Portability — handlers receive the same BotToolContext on every platform; a tool written against thread methods runs unchanged on any adapter that supports them.

Related