Skip to content

Commit 7e92a02

Browse files
ericallamTrigger.dev RepoOps
authored andcommitted
docs(ai-chat): clarify user selection and tool approval
Explain when to collect a tool result with `addToolOutput` and when to combine `needsApproval` with `execute`. Cover choosing from search results in the human-in-the-loop guide, including server-side selection checks and stable operation IDs for retries. Clarify transcript restoration and the limits of tool-result filtering for external side effects. Update the frontend approval examples and link them to the selection guidance. Mono-RevId: 6c6be1ef71ea4846ba9929179edf48eee77a2af7
1 parent 5f54fb2 commit 7e92a02

3 files changed

Lines changed: 206 additions & 196 deletions

File tree

‎docs/ai-chat/frontend.mdx‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,9 @@ See [Stop generation](/ai-chat/backend#stop-generation) in the backend docs for
354354

355355
## Tool approvals
356356

357-
The AI SDK supports tools that require human approval before execution. To use this with `chat.agent`, define a tool with `needsApproval: true` on the backend, then handle the approval UI and configure `sendAutomaticallyWhen` on the frontend.
357+
AI SDK 6 and later support `needsApproval: true` on tools with an `execute` function. The approval request appears before `execute` runs. Approving the call runs it on the next turn; denying it skips execution.
358+
359+
To collect a selection from search results, use a tool without `execute` and supply its result with `addToolOutput`. See [Choose from tool results](/ai-chat/patterns/human-in-the-loop#choose-from-tool-results).
358360

359361
### Backend: define an approval-required tool
360362

@@ -377,7 +379,7 @@ const sendEmail = tool({
377379
});
378380
```
379381

380-
Pass the tool to `streamText` in your `run` function as usual. When the model calls the tool, `chat.agent` streams a `tool-approval-request` chunk. The turn completes and the run waits for the next message.
382+
Declare the tool on the agent and pass it to the `streamText` supplied to your `run` function. When the model calls the tool, `chat.agent` streams a `tool-approval-request` chunk. The turn completes and the run waits for the next message.
381383

382384
### Frontend: approval UI
383385

@@ -387,9 +389,14 @@ Destructure `addToolApprovalResponse` from `useChat` and wire it to your approva
387389

388390
```tsx
389391
import { useChat } from "@ai-sdk/react";
390-
import { lastAssistantMessageIsCompleteWithApprovalResponses } from "ai";
392+
import {
393+
isToolUIPart,
394+
lastAssistantMessageIsCompleteWithApprovalResponses,
395+
type ChatTransport,
396+
type UIMessage,
397+
} from "ai";
391398

392-
function Chat({ chatId, transport }) {
399+
function Chat({ chatId, transport }: { chatId: string; transport: ChatTransport<UIMessage> }) {
393400
const { messages, sendMessage, addToolApprovalResponse, status } = useChat({
394401
id: chatId,
395402
transport,
@@ -408,7 +415,7 @@ function Chat({ chatId, transport }) {
408415
<div>
409416
{messages.map((msg) =>
410417
msg.parts.map((part, i) => {
411-
if (part.state === "approval-requested") {
418+
if (isToolUIPart(part) && part.state === "approval-requested") {
412419
return (
413420
<div key={i}>
414421
<p>Tool "{part.type}" wants to run with input:</p>

0 commit comments

Comments
 (0)