How it works
AI SDK 7 lets you set an approval rule per tool with thetoolApproval 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 updatedagent.ts that pays small amounts on its own and asks in the terminal before anything above 0.5 USDT.
Prerequisites
- The
bot-agentproject,.envandtools.tsfrom Tool calling.
Steps
1
Replace agent.ts
agent.ts
toolApproval.sendUsdtreceives the tool’s input and decides. Payments of 0.5 USDT or less return"not-applicable"and run at once.- The script keeps a
messagesarray. Each round adds the model’s messages withresult.responseMessages, so the next call picks up where the last one stopped. - Parts with
isAutomaticset 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
3
Run a large payment
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. Withn, the tool didn’t run and the model received:
Output
y, the tool ran and its own balance check refused, because the wallet held only 0.020366 USDT:
Output
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:- When
generateTextreturns approval requests, save themessagesarray and eachapprovalId. - 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.
- When they answer, load the messages, add the
tool-approval-response, and callgenerateTextagain.
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 script never asks, even for large amounts
The script never asks, even for large amounts
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 model calls the tool again after a refusal
The model calls the tool again after a refusal
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.
I've seen needsApproval on tool definitions
I've seen needsApproval on tool definitions
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.