Deploy to Production?
This will push the latest changes to all users.
This will push the latest changes to all users.
import { ApprovalCard } from "@/components/tool-ui/approval-card";export function Example() { return ( <ApprovalCard id="approval-card-example" title="Deploy to Production?" description="This will push the latest changes to all users." icon="rocket" confirmLabel="Deploy" onConfirm={() => console.log("Approved")} onCancel={() => console.log("Denied")} /> );}Note: Buttons use a responsive layout—they appear as compact pills at wider widths and stack full-width on narrow containers.
Gate agent actions with explicit user approval
Warning styling for dangerous operations
Show key-value details about what's being approved
Display the decision outcome in conversation history
When decision is set, the component renders in a compact receipt state showing the approval decision. Use this to display the outcome in conversation history.
The receipt state:
Use variant="destructive" for dangerous or irreversible actions. This changes the icon background and confirm button to destructive styling.
This action cannot be undone. All data will be permanently removed.
<ApprovalCard id="destructive-example" title="Delete Project?" description="This action cannot be undone." icon="trash-2" variant="destructive" confirmLabel="Delete" cancelLabel="Keep" onConfirm={() => deleteProject()} onCancel={() => console.log("Kept")}/>Copy components/tool-ui/approval-card and the shared directory into your project. The shared folder contains utilities used by all Tool UI components. The tool-ui directory should sit alongside your shadcn ui directory.
This component requires the following shadcn/ui components:
pnpm dlx shadcn@latest add button"use client";import { makeAssistantTool } from "@assistant-ui/react";import { ApprovalCard, ApprovalCardErrorBoundary, parseSerializableApprovalCard, SerializableApprovalCardSchema, type SerializableApprovalCard, type ApprovalDecision,} from "@/components/tool-ui/approval-card";export const ApprovalTool = makeAssistantTool< SerializableApprovalCard, ApprovalDecision>({ toolName: "requestApproval", description: "Request user approval before performing an action.", parameters: SerializableApprovalCardSchema, render: ({ args, result, addResult, toolCallId }) => { if (!(args as any)?.title) return null; const approvalCard = parseSerializableApprovalCard({ ...args, id: (args as any)?.id ?? `approval-${toolCallId}`, }); return ( <ApprovalCardErrorBoundary> {result !== undefined ? ( <ApprovalCard {...approvalCard} choice={result} /> ) : ( <ApprovalCard {...approvalCard} onConfirm={() => addResult("approved")} onCancel={() => addResult("denied")} /> )} </ApprovalCardErrorBoundary> ); },});Mount <ApprovalTool /> under <AssistantRuntimeProvider> to register the tool and its UI.
Prop
Type
Prop
Type
Long metadata values are automatically truncated with an ellipsis. Keep values concise for best results.
role="dialog" with aria-labelledby and aria-describedbyTab to move between buttonsEnter or Space to activate focused buttonEscape triggers the cancel actionrole="status" for screen reader announcementsprefers-reduced-motionimport { ApprovalCard } from "@/components/tool-ui/approval-card";
export function Example() {
return (
<ApprovalCard
id="approval-card-example"
title="Deploy to Production?"
description="This will push the latest changes to all users."
icon="rocket"
confirmLabel="Deploy"
onConfirm={() => console.log("Approved")}
onCancel={() => console.log("Denied")}
/>
);
}<ApprovalCard
id="destructive-example"
title="Delete Project?"
description="This action cannot be undone."
icon="trash-2"
variant="destructive"
confirmLabel="Delete"
cancelLabel="Keep"
onConfirm={() => deleteProject()}
onCancel={() => console.log("Kept")}
/>pnpm dlx shadcn@latest add button"use client";
import { makeAssistantTool } from "@assistant-ui/react";
import {
ApprovalCard,
ApprovalCardErrorBoundary,
parseSerializableApprovalCard,
SerializableApprovalCardSchema,
type SerializableApprovalCard,
type ApprovalDecision,
} from "@/components/tool-ui/approval-card";
export const ApprovalTool = makeAssistantTool<
SerializableApprovalCard,
ApprovalDecision
>({
toolName: "requestApproval",
description: "Request user approval before performing an action.",
parameters: SerializableApprovalCardSchema,
render: ({ args, result, addResult, toolCallId }) => {
if (!(args as any)?.title) return null;
const approvalCard = parseSerializableApprovalCard({
...args,
id: (args as any)?.id ?? `approval-${toolCallId}`,
});
return (
<ApprovalCardErrorBoundary>
{result !== undefined ? (
<ApprovalCard {...approvalCard} choice={result} />
) : (
<ApprovalCard
{...approvalCard}
onConfirm={() => addResult("approved")}
onCancel={() => addResult("denied")}
/>
)}
</ApprovalCardErrorBoundary>
);
},
});