Tool Approval

Require user approval before executing sensitive tool operations

Tool Approval is a feature that allows you to require explicit user confirmation before a tool executes. This is useful for tools that perform sensitive operations like making purchases, sending emails, or accessing private data.

How It Works

When a tool has needsApproval: true, the AI will pause execution and display an approval UI to the user. The user can then choose to approve or deny the tool execution. If approved, the tool runs and returns results. If denied, the model receives feedback that the user declined.

Enabling Tool Approval

To enable tool approval for a tool, add the needsApproval property to your tool definition:

lib/ai/tools/get-weather.ts
import { tool } from "ai";
import { z } from "zod";

export const getWeather = tool({
  description: "Get the current weather at a location",
  inputSchema: z.object({
    city: z.string().describe("City name"),
  }),
  needsApproval: true,
  execute: async ({ city }) => {
    // Fetch weather data...
    return { temperature: 72, condition: "sunny" };
  },
});

Handling Approval in the UI

The Chat SDK automatically handles tool approval states in the message component. When a tool requests approval, it renders with "Deny" and "Allow" buttons:

components/message.tsx
if (state === "approval-requested" && approvalId) {
  return (
    <div className="flex gap-2">
      <button
        onClick={() => {
          addToolApprovalResponse({
            id: approvalId,
            approved: false,
            reason: "User denied",
          });
        }}
      >
        Deny
      </button>
      <button
        onClick={() => {
          addToolApprovalResponse({
            id: approvalId,
            approved: true,
          });
        }}
      >
        Allow
      </button>
    </div>
  );
}

Tool States

Tools with approval go through the following states:

StateDescription
input-streamingTool input is being streamed
input-availableTool input is ready
approval-requestedWaiting for user approval
approval-respondedUser has approved/denied
output-availableTool executed successfully
output-deniedUser denied the tool
output-errorTool execution failed

Automatic Continuation

The Chat SDK uses sendAutomaticallyWhen to automatically continue the conversation after approval:

components/chat.tsx
const { addToolApprovalResponse } = useChat({
  sendAutomaticallyWhen: ({ messages }) => {
    const lastMessage = messages.at(-1);
    return lastMessage?.parts?.some(
      (part) =>
        "state" in part &&
        part.state === "approval-responded" &&
        "approval" in part &&
        part.approval?.approved === true
    ) ?? false;
  },
});

Best Practices

  • Only require approval for tools that perform sensitive operations
  • Provide clear descriptions so users understand what they're approving
  • Handle denied tools gracefully in your UI
  • Consider logging approval decisions for audit purposes