diff --git a/ai-sdk.md b/ai-sdk.md
index 70cd2a8ee3..04d2887172 100644
--- a/ai-sdk.md
+++ b/ai-sdk.md
@@ -1,44 +1,58 @@
# Laravel AI SDK
-- [Introduction](#introduction)
-- [Installation](#installation)
+- [Laravel AI SDK](#laravel-ai-sdk)
+ - [Introduction](#introduction)
+ - [Installation](#installation)
- [Configuration](#configuration)
- [Custom Base URLs](#custom-base-urls)
- [Provider Support](#provider-support)
-- [Agents](#agents)
+ - [Agents](#agents)
- [Prompting](#prompting)
- [Conversation Context](#conversation-context)
+ - [Remembering Conversations](#remembering-conversations)
- [Structured Output](#structured-output)
- [Attachments](#attachments)
- [Streaming](#streaming)
+ - [Streaming Using the Vercel AI SDK Protocol](#streaming-using-the-vercel-ai-sdk-protocol)
- [Broadcasting](#broadcasting)
- [Queueing](#queueing)
- [Tools](#tools)
+ - [Similarity Search](#similarity-search)
+ - [Tool Approval](#tool-approval)
+ - [Conditional Approval](#conditional-approval)
+ - [Handling Pending Approval Responses](#handling-pending-approval-responses)
+ - [Approving and Rejecting Tool Calls](#approving-and-rejecting-tool-calls)
+ - [Events](#events)
- [Provider Tools](#provider-tools)
+ - [Web Search](#web-search)
+ - [Web Fetch](#web-fetch)
+ - [File Search](#file-search)
- [Middleware](#middleware)
- [Anonymous Agents](#anonymous-agents)
- [Agent Configuration](#agent-configuration)
-- [Images](#images)
-- [Audio (TTS)](#audio)
-- [Transcription (STT)](#transcription)
-- [Embeddings](#embeddings)
+ - [Images](#images)
+ - [Audio](#audio)
+ - [Transcriptions](#transcriptions)
+ - [Embeddings](#embeddings)
- [Querying Embeddings](#querying-embeddings)
- [Caching Embeddings](#caching-embeddings)
-- [Reranking](#reranking)
-- [Files](#files)
-- [Vector Stores](#vector-stores)
+ - [Reranking](#reranking)
+ - [Reranking Collections](#reranking-collections)
+ - [Files](#files)
+ - [Using Stored Files in Conversations](#using-stored-files-in-conversations)
+ - [Vector Stores](#vector-stores)
- [Adding Files to Stores](#adding-files-to-stores)
-- [Failover](#failover)
-- [Testing](#testing)
- - [Agents](#testing-agents)
- - [Images](#testing-images)
- - [Audio](#testing-audio)
- - [Transcriptions](#testing-transcriptions)
- - [Embeddings](#testing-embeddings)
- - [Reranking](#testing-reranking)
- - [Files](#testing-files)
- - [Vector Stores](#testing-vector-stores)
-- [Events](#events)
+ - [Failover](#failover)
+ - [Testing](#testing)
+ - [Agents](#agents-1)
+ - [Images](#images-1)
+ - [Audio](#audio-1)
+ - [Transcriptions](#transcriptions-1)
+ - [Embeddings](#embeddings-1)
+ - [Reranking](#reranking-1)
+ - [Files](#files-1)
+ - [Vector Stores](#vector-stores-1)
+ - [Events](#events-1)
## Introduction
@@ -641,6 +655,169 @@ SimilaritySearch::usingModel(Document::class, 'embedding')
->withDescription('Search the knowledge base for relevant articles.'),
```
+
+#### Tool Approval
+
+Sometimes tools perform actions with real-world consequences — deleting files, processing payments, or sending messages on behalf of a user. In these cases, you may want to require human approval before a tool is executed. To indicate that a tool requires approval, define a `requiresApproval` method on the tool that returns `true`:
+
+```php
+ $schema->integer()->description('The user ID')->required(),
+ ];
+ }
+}
+```
+
+When the AI model calls a tool that requires approval, the agent will not execute the tool. Instead, the `prompt` method will return a `PendingApprovalResponse` instance containing the pending tool call details.
+
+
+##### Conditional Approval
+
+The `requiresApproval` method receives no arguments, but since it is a regular method on your tool class, you may use any application logic to determine whether approval is necessary:
+
+```php
+/**
+ * Determine if the tool requires approval before execution.
+ */
+public function requiresApproval(): bool
+{
+ return ! auth()->user()->isAdmin();
+}
+```
+
+
+##### Handling Pending Approval Responses
+
+To handle approval responses, your agent should use the `HasApprovalFlow` trait, which provides `approve` and `reject` methods:
+
+```php
+prompt('Delete all files for user 42');
+
+if ($response instanceof PendingApprovalResponse) {
+ $pendingToolCall = $response->pendingToolCalls->first();
+
+ // Store the pending tool call for later (session, cache, etc.)...
+ session(['pending_tool' => $pendingToolCall]);
+
+ // Present the pending tool call to the user for approval...
+ return response()->json([
+ 'status' => 'pending_approval',
+ 'tool' => $pendingToolCall->toolName(),
+ 'arguments' => $pendingToolCall->arguments,
+ ]);
+}
+
+return response()->json(['message' => $response->text]);
+```
+
+
+##### Approving and Rejecting Tool Calls
+
+Once the user has made a decision, you may approve or reject the pending tool call. The `approve` method will execute the tool and re-prompt the agent with the tool's result:
+
+```php
+$pendingToolCall = session()->pull('pending_tool');
+
+$response = (new FileManager)->approve($pendingToolCall);
+
+return response()->json(['message' => $response->text]);
+```
+
+The `reject` method accepts an optional reason that will be communicated to the agent:
+
+```php
+$response = (new FileManager)->reject($pendingToolCall, 'User declined the operation');
+```
+
+> **Note:** Both `approve` and `reject` re-prompt the agent, which results in an additional API call to the AI provider. The tool's result (or rejection reason) is provided as context in the new prompt.
+
+
+##### Events
+
+The following events are dispatched during the tool approval lifecycle:
+
+- `ToolApprovalRequested`: Dispatched when a tool requiring approval is intercepted at prompt time.
+- `ToolApproved`: Dispatched when a pending tool call is approved, before the tool is executed.
+- `ToolRejected`: Dispatched when a pending tool call is rejected.
+
+These events may be used to log approval decisions, send notifications, or implement audit trails:
+
+```php
+use Laravel\Ai\Events\ToolApprovalRequested;
+
+Event::listen(ToolApprovalRequested::class, function ($event) {
+ Log::info('Tool approval requested', [
+ 'tool' => $event->pendingToolCall->toolName(),
+ 'arguments' => $event->arguments,
+ ]);
+});
+```
+
### Provider Tools
@@ -1995,7 +2172,10 @@ The Laravel AI SDK dispatches a variety of [events](/docs/{{version}}/events), i
- `StoreCreated`
- `StoringFile`
- `StreamingAgent`
+- `ToolApprovalRequested`
+- `ToolApproved`
- `ToolInvoked`
+- `ToolRejected`
- `TranscriptionGenerated`
You can listen to any of these events to log or store AI SDK usage information.