File: confirmation.md | Updated: 11/15/2025
Slash Forward
Docs Cookbook Providers Playground AI ElementsAI ElementsLeft sparkleRight sparkle AI GatewayGateway
Search...⌘KFeedback GitHub Vercel LogoSign in with Vercel
Chatbot
An alert-based component for managing tool execution approval workflows with request, accept, and reject states.
The Confirmation component provides a flexible system for displaying tool approval requests and their outcomes. Perfect for showing users when AI tools require approval before execution, and displaying the approval status afterward.
Preview
Code
This tool wants to delete the file /tmp/example.txt. Do you approve this action?
RejectApprove
AI Elements
shadcn CLI
Manual
npx ai-elements@latest add confirmation
Build a chat UI with tool approval workflow where dangerous tools require user confirmation before execution.
Add the following component to your frontend:
app/page.tsx
'use client';
import { useChat } from '@ai-sdk/react';
import { DefaultChatTransport, type ToolUIPart } from 'ai';
import { useState } from 'react';
import { CheckIcon, XIcon } from 'lucide-react';
import { Button } from '@/components/ui/button';
import {
Confirmation,
ConfirmationContent,
ConfirmationRequest,
ConfirmationAccepted,
ConfirmationRejected,
ConfirmationActions,
ConfirmationAction,
} from '@/components/ai-elements/confirmation';
import { MessageResponse } from '@/components/ai-elements/message';
type DeleteFileInput = {
filePath: string;
confirm: boolean;
};
type DeleteFileToolUIPart = ToolUIPart<{
delete_file: {
input: DeleteFileInput;
output: { success: boolean; message: string };
};
}>;
const Example = () => {
const { messages, sendMessage, status, respondToConfirmationRequest } = useChat({
transport: new DefaultChatTransport({
api: '/api/chat',
}),
});
const handleDeleteFile = () => {
sendMessage({ text: 'Delete the file at /tmp/example.txt' });
};
const latestMessage = messages[messages.length - 1];
const deleteTool = latestMessage?.parts?.find(
(part) => part.type === 'tool-delete_file'
) as DeleteFileToolUIPart | undefined;
return (
<div className="max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]">
<div className="flex flex-col h-full space-y-4">
<Button onClick={handleDeleteFile} disabled={status !== 'ready'}>
Delete Example File
</Button>
{deleteTool?.approval && (
<Confirmation approval={deleteTool.approval} state={deleteTool.state}>
<ConfirmationContent>
<ConfirmationRequest>
This tool wants to delete: <code>{deleteTool.input?.filePath}</code>
<br />
Do you approve this action?
</ConfirmationRequest>
<ConfirmationAccepted>
<CheckIcon className="size-4" />
<span>You approved this tool execution</span>
</ConfirmationAccepted>
<ConfirmationRejected>
<XIcon className="size-4" />
<span>You rejected this tool execution</span>
</ConfirmationRejected>
</ConfirmationContent>
<ConfirmationActions>
<ConfirmationAction
variant="outline"
onClick={() =>
respondToConfirmationRequest({
approvalId: deleteTool.approval!.id,
approved: false,
})
}
>
Reject
</ConfirmationAction>
<ConfirmationAction
variant="default"
onClick={() =>
respondToConfirmationRequest({
approvalId: deleteTool.approval!.id,
approved: true,
})
}
>
Approve
</ConfirmationAction>
</ConfirmationActions>
</Confirmation>
)}
{deleteTool?.output && (
<MessageResponse>
{deleteTool.output.success
? deleteTool.output.message
: `Error: ${deleteTool.output.message}`}
</MessageResponse>
)}
</div>
</div>
);
};
export default Example;
Add the following route to your backend:
app/api/chat/route.tsx
import { streamText, UIMessage, convertToModelMessages } from 'ai';
import { z } from 'zod';
// Allow streaming responses up to 30 seconds
export const maxDuration = 30;
export async function POST(req: Request) {
const { messages }: { messages: UIMessage[] } = await req.json();
const result = streamText({
model: 'openai/gpt-4o',
messages: convertToModelMessages(messages),
tools: {
delete_file: {
description: 'Delete a file from the file system',
parameters: z.object({
filePath: z.string().describe('The path to the file to delete'),
confirm: z
.boolean()
.default(false)
.describe('Confirmation that the user wants to delete the file'),
}),
requireApproval: true, // Enable approval workflow
execute: async ({ filePath, confirm }) => {
if (!confirm) {
return {
success: false,
message: 'Deletion not confirmed',
};
}
// Simulate file deletion
await new Promise((resolve) => setTimeout(resolve, 500));
return {
success: true,
message: `Successfully deleted ${filePath}`,
};
},
},
},
});
return result.toUIMessageStreamResponse();
}
Shows the approval request with action buttons when state is approval-requested.
Preview
Code
This tool wants to execute a query on the production database:SELECT * FROM users WHERE role = 'admin'
RejectApprove
Shows the accepted status when user approves and state is approval-responded or output-available.
Preview
Code
You approved this tool execution
Shows the rejected status when user rejects and state is output-denied.
Preview
Code
You rejected this tool execution
<Confirmation />Prop
Type
approval?ToolUIPart["approval"]
state?ToolUIPart["state"]
className?string
...props?React.ComponentProps<typeof Alert>
<ConfirmationContent />Prop
Type
className?string
...props?React.ComponentProps<typeof AlertDescription>
<ConfirmationRequest />Prop
Type
children?React.ReactNode
<ConfirmationAccepted />Prop
Type
children?React.ReactNode
<ConfirmationRejected />Prop
Type
children?React.ReactNode
<ConfirmationActions />Prop
Type
className?string
...props?React.ComponentProps<"div">
<ConfirmationAction />Prop
Type
...props?React.ComponentProps<typeof Button>
Checkpoint
A simple component for marking conversation history points and restoring the chat to a previous state.
Context
A compound component system for displaying AI model context window usage, token consumption, and cost estimation.
On this page
Installation
Usage with AI SDK
Features
Examples
Approval Request State
Approved State
Rejected State
Props
<Confirmation />
<ConfirmationContent />
<ConfirmationRequest />
<ConfirmationAccepted />
<ConfirmationRejected />
<ConfirmationActions />
<ConfirmationAction />
GitHubEdit this page on GitHub Scroll to topCopy pageOpen in chat