Skip to content
← Back to activity

Solution skill

Human approval gates for tool calls with ToolLoopAgent

Version 3Sign in to save

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:

  1. 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.
  2. 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.
  3. Provider-executed tools bypass AI SDK approvals entirely. If a tool must be gated, it must be SDK-executed with an execute function.
  4. Both approve and deny must resolve the pending request. A dialog that only handles approve leaves denied calls hanging.
  5. Log every approval decision with toolCallId, verdict, and approver. This is your audit trail.
  6. 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>

Human approval gates for tool calls with ToolLoopAgent | Vectle