- A tool is a description, an input schema and an execute function; the schema serves the model and validates calls.
- Treat arguments from a model like data from an unknown user: validate, narrow the scope and check permissions.
- Tools with side effects need human approval.
A chat that only answers with text is safe in a simple way: at worst it writes something inaccurate. When you give a model tools, the scale of responsibility changes, because the model starts calling your code. That is why the way of defining tools and validating their arguments is one of the most important topics in working with the AI SDK. This article assumes you already have a working chat, as in the text Vercel AI SDK: your first chat.
The anatomy of a tool
According to the documentation, a tool is an object that the model can call to perform a specific task. It has three properties. The description (description) influences when the model picks the tool. The input schema (inputSchema) is a zod schema or JSON Schema defining the data the tool needs; according to the documentation the model reads it, and the library also uses it to validate calls. The execute function is an asynchronous function called with the arguments from the call. Tools with an execute function run automatically, and the result returns to the model in multi-step calls.
An example from the documentation, extended with a limit on the argument length:
import { tool } from 'ai';
import { z } from 'zod';
const weatherTool = tool({
description: 'Get the weather in a location',
inputSchema: z.object({
location: z.string().min(1).max(100).describe('The location to get the weather for'),
}),
execute: async ({ location }) => {
// your implementation: check permissions and data scope here
return { temperature: 72, conditions: 'sunny' };
},
});
Zod is a schema validation library for TypeScript. The schema does two things here at once: it describes the arguments to the model and rejects calls that do not match it. It is worth tightening: length limits, lists of allowed values (z.enum), number ranges and formats reduce the space in which the model can go wrong.
Validation is more than types
Matching a type does not mean safety. A location argument of 100 characters can contain anything. In the execute function take care of further layers. Check permissions: may this user perform this operation on this data? Narrow the scope: a read tool should not have write permissions to the database. Do not insert arguments into queries or shell commands without parameterization. In describing excessive agency OWASP names three sources of the problem: too many functions, permissions and too much autonomy, and you can limit each of them in code here.
| What it does | Where you write it | |
|---|---|---|
| Input schema | Rejects non-matching arguments | inputSchema in zod |
| Authorization | Checks who asks for what | Inside execute and the session layer |
| Permission scope | The tool has only the rights it needs | A service account with minimal rights |
| Approval | A human confirms side effects | A step in the interface before execution |
| Log | A trace of every call | Logs with arguments and result |
Dynamic tools and MCP
The documentation also describes dynamic tools (dynamicTool), that is, ones whose input and output types are not known at the time of writing the code, for example loaded from MCP servers. The input is then of unknown type, so run-time validation is not an option but a necessity. Assessing trust in the server that supplies the tools is just as important: I describe it in the article on adding MCP servers.
- 01DescriptionShort, unambiguous, when to use the tool.
- 02SchemaZod with limits and value lists.
- 03AuthorizationWho, what and on which data.
- 04ExecutionMinimal permissions, parameterization.
- 05ApprovalFor side effects and irreversible actions.
- 06LogA trace for review after the fact.
Testing tools
Test a tool like any function that takes data from outside. Write tests for valid arguments, for arguments outside the schema, for permissions (a user without the right to the data) and for edge cases. Only then check how the model picks them, on your own set of requests, which I describe in the article How to evaluate an agent before you trust it. When a model picks the wrong tool, it is most often the description that gets fixed, not the code. OpenAI’s guide to function calling describes the same pattern in another API, which confirms that the principles are independent of the library. The whole topic: JavaScript and Vercel AI SDK.
Last checked: 20 October 2026. The library’s interface changes between versions; compare the code with the current documentation.

