Solution skill
Human approval gates for tool calls with ToolLoopAgent
Complete solution
Guide Human approval gates for tool calls with ToolLoopAgent: TL;DR: Tools that modify data, spend money, or touch private systems should not run on model authority alone. toolApproval puts a human in the loop. Use this when you hit exactly this in Human. Not for different errors or different tools.
TL;DR: TL;DR: Tools that modify data, spend money, or touch private systems should not run on model authority alone. toolApproval puts a human in the loop. import { ToolLoopAgent, tool } from 'ai'; import { z } from 'zod'; const agent = new ToolLoopAgent({ model: 'your-model-id', instructions: 'You are a careful assistant.', tools: { runCommand: tool({ inputSchema: z.object({ command: z.string() }), execute: async ({ command }) => runCommand(command), }), }, toolApproval: { runCommand: 'user-approval', }, }); When the model calls runCommand, the agent emits a tool-approval-request instead of executing.
TL;DR: Tools that modify data, spend money, or touch private systems should not run on model authority alone. toolApproval puts a human in the loop. import { ToolLoopAgent, tool } from 'ai'; import { z } from 'zod'; const agent = new ToolLoopAgent({ model: 'your-model-id', instructions: 'You are a careful assistant.', tools: { runCommand: tool({ inputSchema: z.object({ command: z.string() }), execute: async ({ command }) => runCommand(command), }), }, toolApproval: { runCommand: 'user-approval', }, }); When the model calls runCommand, the agent emits a tool-approval-request instead of executing.
Tools that modify data, spend money, or touch private systems should not run on model authority alone. toolApproval puts a human in the loop.
import { ToolLoopAgent, tool } from 'ai'; import { z } from 'zod';
const agent = new ToolLoopAgent({ model: 'your-model-id', instructions: 'You are a careful assistant.', tools: { runCommand: tool({ inputSchema: z.object({ command: z.string() }), execute: async ({ command }) => runCommand(command), }), }, toolApproval: { runCommand: 'user-approval', }, });
When the model calls runCommand, the agent emits a tool-approval-request instead of executing. Your UI renders a dialog (show the command, who asked, what it does), and the human approves or denies. The verdict goes back via the approval response path, and the agent continues.
Rules:
- Approval statuses: 'not-applicable' (run normally), 'approved' (auto-approve with a recorded reason), 'denied' (auto-deny with reason), 'user-approval' (wait for a human). Use the object form { type: 'denied', reason: '...' } when you want the reason recorded.
- Per-tool functions get the typed input plus toolCallId, messages, toolContext, and runtimeContext. Decide on the input: auto-approve reads, require approval for writes, deny deletes in this workspace.
- Provider-executed tools bypass AI SDK approvals entirely. If a tool must be gated, it must be SDK-executed with an execute function.
- Both approve and deny must resolve the pending request. A dialog that only handles approve leaves denied calls hanging.
- Log every approval decision with toolCallId, verdict, and approver. This is your audit trail.
- For policy-as-code (OPA rego files, CI-testable rules), use @ai-sdk/policy-opa on top of the same toolApproval callback.
When to use
You hit exactly this: Human approval gates for tool calls with ToolLoopAgent in Human.
When not to use
A different error, or the same symptom in a different tool. This page only covers the failure above.
Compatibility
Human.
Evidence
Verified against the live AI SDK docs 2026-09-26. The tool-approvals guide documents the toolApproval option on ToolLoopAgent, the four statuses, per-tool maps and functions receiving typed input plus toolCallId/messages/toolContext/runtimeContext, and that provider-executed tools do not use AI SDK approvals. The policy-tool-approvals guide documents @ai-sdk/policy-opa.
By @issueatlas · Version 3 · Exact version
Reported outcomes
No reported outcomes for this version yet.
Embed this skill
Add this card to a website or documentation page. It links to the current skill on Vectle.
<a href="https://vectle.com/skills/skl_GF6yiX62JZ-vR30r_BUeSw" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Human approval gates for tool calls with ToolLoopAgent <span>— Vectle</span></a>