AI SDK Tools

Give an AI agent the ability to operate inside your workspace. Post messages, send DMs, react, edit, delete; all with built-in approval gates.

createChatTools exposes Chat SDK operations as ready-to-use AI SDK tools so an agent can act inside the same workspaces your bot is connected to: read messages, post replies, send DMs, react, edit, delete, and manage thread subscriptions across every adapter you've registered.

Write operations require user approval out of the box, toggle them globally or per-tool when you want unattended execution.

Installation

The tools live in the chat/ai subpath of the core chat package:

import { createChatTools } from "chat/ai";

ai and zod are optional peer dependencies — install them if you haven't already:

pnpm add ai zod

Pair createChatTools with toAiMessages to feed prior thread history into the agent before it picks a tool. Both ship from the same chat/ai subpath, which keeps the optional ai / zod peer deps out of bundles that don't import them.

Quick start

Pass your Chat instance and the tools you want into any AI SDK call:

lib/agent.ts
import { Chat } from "chat";
import { createChatTools } from "chat/ai";
import { createSlackAdapter } from "@chat-adapter/slack";
import { createMemoryState } from "@chat-adapter/state-memory";
import { generateText } from "ai";

const chat = new Chat({
  userName: "mybot",
  adapters: { slack: createSlackAdapter() },
  state: createMemoryState(),
});

const result = await generateText({
  model: "anthropic/claude-sonnet-4.6",
  tools: createChatTools({
    chat,
    preset: "messenger",
    requireApproval: false, // unattended script, no human-in-the-loop needed
  }),
  prompt:
    "Post a friendly hello in slack:C0123ABC and react to it with a thumbs up.",
});

Each tool resolves the right adapter from the id prefix you give it (slack:..., discord:..., gchat:...), so the same agent can drive any platform your Chat instance is wired up to.

Presets

Pass preset to scope the toolset down to what an agent actually needs.

// Read-only — fetch messages, threads, channel info, users
createChatTools({ chat, preset: "reader" });

// Basic posting — read + post + DM + react + typing indicator
createChatTools({ chat, preset: "messenger" });

// Full management — everything including edit, delete, subscriptions
createChatTools({ chat, preset: "moderator" });

Presets compose — pass an array to combine them:

createChatTools({ chat, preset: ["reader", "messenger"] });

Omit preset entirely to get every tool (same as 'moderator').

PresetTools included
readerfetchMessages, fetchChannelMessages, fetchThread, listThreads, getThreadParticipants, getChannelInfo, getUser
messengerfetchMessages, fetchThread, getChannelInfo, getUser, postMessage, postChannelMessage, sendDirectMessage, addReaction, removeReaction, startTyping
moderatorAll read tools plus postMessage, postChannelMessage, sendDirectMessage, editMessage, deleteMessage, addReaction, removeReaction, subscribeThread, unsubscribeThread, startTyping

Approval control

Write operations (posting, editing, deleting, reacting, subscribing) default to needsApproval: true. The AI SDK pauses execution and surfaces an approval request that your application is expected to confirm before the tool runs. This keeps a human in the loop for anything visible to the workspace.

// All writes need approval (default)
createChatTools({ chat });

// No approval needed
createChatTools({ chat, requireApproval: false });

// Per-tool — only destructive actions need approval
createChatTools({
  chat,
  requireApproval: {
    deleteMessage: true,
    editMessage: true,
    sendDirectMessage: false,
    postMessage: false,
    addReaction: false,
  },
});

Read tools (fetchMessages, fetchThread, getChannelInfo, …) and the startTyping indicator never require approval.

Cherry-picking tools

Each tool is also exported as a standalone factory you can hand to tools directly:

lib/agent.ts
import { fetchMessages, postMessage, addReaction } from "chat/ai";

const tools = {
  fetchMessages: fetchMessages(chat),
  postMessage: postMessage(chat, { needsApproval: false }),
  addReaction: addReaction(chat, { needsApproval: false }),
};

Useful when you want a small, targeted toolset without going through createChatTools.

Tool overrides

Customize any AI SDK tool() property per tool, keyed by tool name:

import type { ChatToolName, ToolOverrides } from "chat/ai";

createChatTools({
  chat,
  overrides: {
    postMessage: {
      description: "Reply in the active customer support thread.",
      needsApproval: false,
    },
    deleteMessage: { needsApproval: true },
  },
});
PropertyTypeDescription
descriptionstringCustom tool description shown to the model
titlestringHuman-readable title
strictbooleanStrict mode for input generation
inputExamplesarrayExamples that show the model what tool input should look like
metadataobjectTool metadata propagated to tool call and result parts
needsApprovalboolean | functionGate execution behind an approval request
providerOptionsProviderOptionsProvider-specific metadata
onInputStartfunctionCallback when argument streaming starts
onInputDeltafunctionCallback on each streaming delta
onInputAvailablefunctionCallback when full input is available
toModelOutputfunctionCustom mapping of tool result to model output

Core properties (execute, inputSchema, outputSchema, and tool-kind fields like type, id, args) cannot be overridden so tool semantics stay stable.

Available tools

All ids accept the full Chat SDK form: slack:C123ABC:1234567890.123456 for a thread, slack:C123ABC for a channel, and the platform-native user id (e.g. U123456 on Slack, users/123 on Google Chat). The tools auto-detect the adapter from the prefix.

Reading

ToolDescription
fetchMessagesFetch recent messages from a thread (paginated)
fetchChannelMessagesFetch top-level messages in a channel (not thread replies)
fetchThreadFetch metadata for a thread (channel id, visibility, DM status)
listThreadsList recent threads in a channel with their root message
getThreadParticipantsReturn the unique non-bot participants in a thread
getChannelInfoFetch channel metadata (name, member count, visibility)
getUserLook up a user's profile by id

Writing

ToolDescriptionDefault approval
postMessagePost a reply in an existing threadrequired
postChannelMessagePost a top-level message in a channelrequired
sendDirectMessageOpen a DM with a user and post in itrequired
editMessageEdit a message the bot previously postedrequired
deleteMessageDelete a message the bot previously postedrequired
addReactionAdd an emoji reaction to a messagerequired
removeReactionRemove a previously-added reactionrequired
subscribeThreadSubscribe the bot to all future messages in a threadrequired
unsubscribeThreadStop receiving non-mention messages in a threadrequired
startTypingShow a typing indicator in a threadnot gated

API

createChatTools(options)

Returns an object of tools, ready to spread into tools of any AI SDK call.

type ChatToolsOptions = {
  chat: Chat;
  requireApproval?: boolean | Partial<Record<ChatWriteToolName, boolean>>;
  preset?: ChatToolPreset | ChatToolPreset[];
  overrides?: Partial<Record<ChatToolName, ToolOverrides>>;
};

type ChatToolPreset = "reader" | "messenger" | "moderator";
OptionDescription
chatThe Chat instance the tools dispatch operations against. Required.
presetPreset (or array of presets) restricting which tools are returned. Omit to get every tool.
requireApprovaltrue (default), false, or per-tool overrides. Read tools and startTyping are never gated.
overridesPer-tool customization of any AI SDK tool() property except execute, inputSchema, and outputSchema.