Skip to main content
In this guide you make your agent stop and ask a person before any payment above a threshold, and carry on only if they say yes.
Everything on this page uses testnet (chain 968). Get free test tokens from the faucet.

How it works

AI SDK 7 lets you set an approval rule per tool with the toolApproval option of generateText. The rule runs in your code, before the tool runs, and returns one of these: When a call pauses, you ask a person, then send their answer back as a tool-approval-response message and call generateText again. The model never sees the threshold and can’t answer the approval itself.

What you’ll build

An updated agent.ts that pays small amounts on its own and asks in the terminal before anything above 0.5 USDT.

Prerequisites

  • The bot-agent project, .env and tools.ts from Tool calling.

Steps

1

Replace agent.ts

agent.ts
What changed from the tool calling version:
  • toolApproval.sendUsdt receives the tool’s input and decides. Payments of 0.5 USDT or less return "not-applicable" and run at once.
  • The script keeps a messages array. Each round adds the model’s messages with result.responseMessages, so the next call picks up where the last one stopped.
  • Parts with isAutomatic set were decided by your rule, not a person, so the script only asks about the others.
  • A refusal includes a reason. The model receives it and can tell the user why the payment didn’t happen.
2

Run a small payment

It runs without asking.
3

Run a large payment

The script stops and asks. Type n to refuse or y to let the tool run. Even after you approve, sendUsdt still applies its own checks.

Verify it worked

In a test run, a 0.001 USDT payment went through with no prompt (transaction on BOTScan). A 0.8 USDT payment stopped at the prompt. With n, the tool didn’t run and the model received:
Output
With y, the tool ran and its own balance check refused, because the wallet held only 0.020366 USDT:
Output
The tool-result lines come from extra logging in the test. Your script prints the model’s reply after them.

Approvals outside a terminal

A real agent usually can’t wait at a terminal prompt. The same flow works across time:
  1. When generateText returns approval requests, save the messages array and each approvalId.
  2. Send the request to a person through a channel you control, such as a dashboard, chat message or email, with the tool name and input.
  3. When they answer, load the messages, add the tool-approval-response, and call generateText again.
Check who answered before you accept it. An approval link that anyone can open is no approval at all.
Approval in your app protects you only while your server and the agent’s key are safe. Keep the funds in an agent vault so the daily limit and allowlist still hold if they aren’t. For the largest payments, keep them out of the agent’s reach entirely: the vault owner, ideally a multisig, makes them directly.

Troubleshooting

The rule compares Number(amount) with APPROVAL_ABOVE_USDT. Check the threshold, and check the tool name in toolApproval matches the key in tools exactly.
The system prompt asks it not to retry. If it still does, each new call goes through the same rule and asks again, so nothing is paid without approval.
That’s the older way to require approval. AI SDK 7 deprecates it in favor of toolApproval on generateText, which also lets the decision depend on the input.

Next steps

Identity hooks

Check counterparties on chain.

Security checklist

Review your setup before real funds.
Last modified on October 3, 2026