📄 ai-sdk/elements/components/confirmation

File: confirmation.md | Updated: 11/15/2025

Source: https://ai-sdk.dev/elements/components/confirmation

Vercel

Slash Forward

Sparkles

AI SDK

Docs Cookbook Providers Playground AI ElementsAI ElementsLeft sparkleRight sparkle AI GatewayGateway

Search...⌘KFeedback GitHub Vercel LogoSign in with Vercel

Chatbot

Confirmation

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

Installation


AI Elements

shadcn CLI

Manual

npx ai-elements@latest add confirmation

Usage with AI SDK


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();
}

Features


  • Context-based state management for approval workflow
  • Conditional rendering based on approval state
  • Support for approval-requested, approval-responded, output-denied, and output-available states
  • Built on shadcn/ui Alert and Button components
  • TypeScript support with comprehensive type definitions
  • Customizable styling with Tailwind CSS
  • Keyboard navigation and accessibility support
  • Theme-aware with automatic dark mode support

Examples


Approval Request State

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

Approved State

Shows the accepted status when user approves and state is approval-responded or output-available.

Preview

Code

You approved this tool execution

Rejected State

Shows the rejected status when user rejects and state is output-denied.

Preview

Code

You rejected this tool execution

Props


<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