Tool approval lets you require human confirmation before a tool call is
executed. This is useful for dangerous or irreversible operations — deleting
data, spending money, sending emails — where you want a person to review the
action before it happens.
Add needsApproval to any tool created with createTool. It can be a boolean
or an async function that receives the tool context and input:
Tools without needsApproval (or with needsApproval returning false)
execute immediately as usual.
Server-side flow
The typical approval flow involves four server functions:
- Save the user’s message and schedule generation.
- Generate a response. If the model calls a tool that needs approval,
generation pauses and the
tool-approval-request is persisted in the thread.
- Submit an approval or denial for each pending tool call.
approveToolCall and denyToolCall work from both mutations and actions.
- Continue generation once all pending approvals have been resolved.
You can approve a tool call and continue generation in the same server function.
For example, an action can call approveToolCall and then immediately call
streamText to resume — no separate scheduling step needed.
When the model calls several tools in a single step, some or all of them may
require approval. Every pending approval must be resolved (approved or
denied) before you continue generation.
If a new generation starts while approvals are still unresolved, the unresolved
approvals are automatically denied with the reason
"auto-denied: new generation started". This prevents broken message histories
where tool calls lack results.
Client-side flow
On the client, use useUIMessages to detect pending approvals and show
Approve/Deny buttons. Tool parts with state === "approval-requested" are
waiting for a decision.
The ToolUIPart states relevant to approval are:
Example files
For a complete working example, see:
- Agent definition:
example/bijection/agents/approval.ts
- Server functions:
example/bijection/chat/approval.ts
- React UI:
example/ui/chat/ChatApproval.tsx