Overview

The chat/ai subpath contains the AI utilities that ship with Chat SDK. Bots built on the AI SDK import from chat/ai; bots built on TanStack AI import the equivalent helpers from chat/ai/tanstack.

import { createChatTools, toAiMessages } from "chat/ai";
import { createTanStackTools, toTanStackMessages } from "chat/ai/tanstack";

Add the optional peers if you don't already have them:

pnpm add ai zod

What's included

PageWhat it gives you
AI SDK ToolscreateChatTools and standalone tool factories that let an agent post messages, send DMs, react, edit, delete, and manage subscriptions across every adapter your Chat instance has registered. Write tools and getUser require approval by default, and presets limit which tools the agent gets.
toAiMessagesConvert Chat SDK Message[] into the { role, content }[] shape expected by AI SDK calls. Handles role mapping, attachments, links, sorting, and optional per-message transforms.
TanStack AItoTanStackMessages and createTanStackTools from chat/ai/tanstack: the same history conversion and tools, shaped for chat() from @tanstack/ai. No runtime dependency on @tanstack/ai.
TypesReference for the types exported from chat/ai: agent message shapes, tool option contracts, presets, approval config, and the binding type that ties tools to your Chat instance.

Typical flow

A Chat SDK bot wired to a tool-calling agent usually looks like this:

lib/agent.ts
import { Chat } from "chat";
import { createChatTools, toAiMessages } from "chat/ai";
import { ToolLoopAgent } from "ai";

const chat = new Chat({ /* adapters, state, ... */ });

const agent = new ToolLoopAgent({
  model: "xai/grok-4.5",
  instructions: "You operate inside a chat workspace via Chat SDK tools.",
  tools: createChatTools({ chat, preset: "messenger", requireApproval: true }),
});

chat.onSubscribedMessage(async (thread) => {
  const { messages } = await thread.adapter.fetchMessages(thread.id, {
    limit: 20,
  });
  const history = await toAiMessages(messages);
  const result = await agent.stream({ prompt: history });
  await thread.post(result.fullStream);
});
  1. toAiMessages converts messages into an output compatible with AI SDK's ModelMessage[].
  2. createChatTools gives the agent AI SDK tools for acting in chat, which you can narrow with presets and customize per tool.
  3. thread.post(stream) renders the streamed response back into the thread.

Using TanStack AI instead? The same flow works with toTanStackMessages and createTanStackTools; see TanStack AI for the chat() version of this example.

Backwards compatibility

toAiMessages and the related Ai* types are still re-exported from the top-level chat package so older bots keep working. Those re-exports are marked @deprecated in JSDoc, so your editor shows a hint pointing at chat/ai. To migrate, change the import:

- import { toAiMessages } from "chat";
+ import { toAiMessages } from "chat/ai";

Resources

  • Human-in-the-Loop with Chat SDK and Workflow SDK: pause durable workflows on Slack approval cards using Chat SDK and Workflow SDK. The guide uses createWebhook to suspend a workflow until a button click, with patterns for multi-stage approvals, timeouts via durable sleep, and approver validation.

See all guides and templates on the resources page.

Read more