What you’ll build
tools.tswith two AI SDK tools whose inputs are checked by zod schemas.agent.ts, a script that sends a request to Claude and lets it call those tools.
sendUsdt tool follows four rules that apply to any tool that moves funds:
- Check input in code. The schema rejects badly shaped input. The tool then applies hard rules: allowed recipients, a per-transfer cap, enough balance.
- Simulate before sending. A failed simulation costs nothing and tells you why.
- Return errors as data. The tool returns
{ ok: false, error }instead of throwing, so the model can explain the problem to the user. - Return a BOTScan link. People can check what happened without trusting the model’s summary.
Prerequisites
- Node.js 22 or later.
- An Anthropic API key. Any provider the AI SDK supports works if you change the model line.
- A testnet key for the agent, with a little tBOT for gas and some testnet USDT. Get USDT by swapping on BDEX V2.
Steps
1
Create the project
2
Add your keys and rules
AGENT_ALLOWED_RECIPIENTS is a comma separated list of addresses the agent may pay..env
3
Write the tools
tools.ts
sendUsdt won’t pay an address outside the list or more than 1 USDT at once.The zod describe text is sent to the model as part of the tool definition. Write it for the model: say what the field is and give an example.4
Write the agent
agent.ts
generateText runs a loop: the model asks for a tool, the SDK runs it and sends back the result, and the model continues. stopWhen: stepCountIs(8) ends the loop after 8 steps, so a confused model can’t call tools forever.5
Run it
Verify it worked
The script prints each tool call (>) and result (<), then the model’s reply. In a test on testnet, the tools returned:
Output
explorerUrl to see the transfer on BOTScan. Requests that break a rule come back as data, and nothing is sent:
Output
Pay from a vault instead
These tools spend from the agent’s own wallet, which keeps the example short. For real funds, keep the money in an agent vault and changesendUsdt to call the vault’s pay(to, amount) with the agent’s key, as vault-pay.ts on that page does. The tool’s checks still help: they give the model a clear answer early. The vault makes sure those rules hold even if the tool code is wrong or the agent’s key is stolen.
Troubleshooting
Recipient is not on the allowlist
Recipient is not on the allowlist
The address isn’t in
AGENT_ALLOWED_RECIPIENTS, or the variable isn’t loaded. Check that you ran with --env-file=.env, and that the addresses are separated by commas with no spaces.The model never calls a tool
The model never calls a tool
Make the request concrete, and check the tool
description says when to use it. Models choose tools from those descriptions.Simulation failed
Simulation failed
The token or chain would reject the transfer. The message says why, for example a missing balance or a paused token. Nothing was sent.
insufficient funds for gas
insufficient funds for gas
The agent’s address pays gas. Send it a little tBOT. See Get testnet tokens.
AI_APICallError or 401
AI_APICallError or 401
ANTHROPIC_API_KEY is missing or wrong. If you use another provider, install its AI SDK package and set its key instead.Next steps
Human approval
Ask a person before large payments.
Agent vaults
Hold the agent’s funds in a contract.