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 zodPair 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:
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').
| Preset | Tools included |
|---|---|
reader | fetchMessages, fetchChannelMessages, fetchThread, listThreads, getThreadParticipants, getChannelInfo, getUser |
messenger | fetchMessages, fetchThread, getChannelInfo, getUser, postMessage, postChannelMessage, sendDirectMessage, addReaction, removeReaction, startTyping |
moderator | All 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:
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 },
},
});| Property | Type | Description |
|---|---|---|
description | string | Custom tool description shown to the model |
title | string | Human-readable title |
strict | boolean | Strict mode for input generation |
inputExamples | array | Examples that show the model what tool input should look like |
metadata | object | Tool metadata propagated to tool call and result parts |
needsApproval | boolean | function | Gate execution behind an approval request |
providerOptions | ProviderOptions | Provider-specific metadata |
onInputStart | function | Callback when argument streaming starts |
onInputDelta | function | Callback on each streaming delta |
onInputAvailable | function | Callback when full input is available |
toModelOutput | function | Custom 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
| Tool | Description |
|---|---|
fetchMessages | Fetch recent messages from a thread (paginated) |
fetchChannelMessages | Fetch top-level messages in a channel (not thread replies) |
fetchThread | Fetch metadata for a thread (channel id, visibility, DM status) |
listThreads | List recent threads in a channel with their root message |
getThreadParticipants | Return the unique non-bot participants in a thread |
getChannelInfo | Fetch channel metadata (name, member count, visibility) |
getUser | Look up a user's profile by id |
Writing
| Tool | Description | Default approval |
|---|---|---|
postMessage | Post a reply in an existing thread | required |
postChannelMessage | Post a top-level message in a channel | required |
sendDirectMessage | Open a DM with a user and post in it | required |
editMessage | Edit a message the bot previously posted | required |
deleteMessage | Delete a message the bot previously posted | required |
addReaction | Add an emoji reaction to a message | required |
removeReaction | Remove a previously-added reaction | required |
subscribeThread | Subscribe the bot to all future messages in a thread | required |
unsubscribeThread | Stop receiving non-mention messages in a thread | required |
startTyping | Show a typing indicator in a thread | not 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";| Option | Description |
|---|---|
chat | The Chat instance the tools dispatch operations against. Required. |
preset | Preset (or array of presets) restricting which tools are returned. Omit to get every tool. |
requireApproval | true (default), false, or per-tool overrides. Read tools and startTyping are never gated. |
overrides | Per-tool customization of any AI SDK tool() property except execute, inputSchema, and outputSchema. |