Skip to content
unseen.uiby Stack Unseen
Get started
All patterns

Chat on the Vercel AI SDK

A chat whose tools ask before they run. The demo below answers with a simulated useChat; the code is what you write against a real one.

Assistant

Archive the accounts with no activity for 90 days.

I found 2 accounts with no activity for 90 days. Archiving needs your approval.

Review required

Run archive_accounts

Pending

archive_accounts

Both accounts become read-only. An administrator can restore them.

Response complete
Shift + Enter for a new line

Approve or reject the archive request to see what happens next.

tsx
'use client';
import { useChat } from '@ai-sdk/react';
import { DefaultChatTransport, lastAssistantMessageIsCompleteWithApprovalResponses } from 'ai';
import { Chat, useAiSdkChat } from '@stackunseen/ui/chat';
import { renderMarkdownPart } from '@stackunseen/ui/markdown';
import '@stackunseen/ui/styles.css';
import '@stackunseen/ui/chat.css';

export function Assistant() {
  const chat = useChat({
    transport: new DefaultChatTransport({ api: '/api/chat' }),
    // Send the conversation back once every pending approval has an answer.
    sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithApprovalResponses,
  });
  return <Chat {...useAiSdkChat(chat)} title="Assistant" renderTextPart={renderMarkdownPart} />;
}
  1. The model calls a tool marked needsApproval; the SDK streams an approval request.
  2. Chat shows the tool card and an approval card with the server's reason.
  3. Approve or Reject calls addToolApprovalResponse with the approval id.
  4. The card stays locked until the tool runs or is denied, then reads acknowledged.

Start from these two files in your project: npx shadcn@latest add https://unseenui.com/r/chat-ai-sdk.json, or npx @stackunseen/ui init --ai-sdk.

Full mapping table and what is and is not verified: the Chat page. Components used: Chat, ToolCall, ApprovalCard, MarkdownResponse.