Build radar
Sources 33Updates always the freshest
0 Newsletter
Animated illustration for: Tools and validation in JavaScript: zod, schemas and safe tool calls
Create · JavaScript & Vercel AI SDK · Guide · 9 min read

Tools and validation in JavaScript: zod, schemas and safe tool calls

How to give a model a tool in the AI SDK: a description, a zod input schema and an execute function. Why to validate calls and limit damage.

In short
  • 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.

Layers of protection for a tool call
What it doesWhere you write it
Input schemaRejects non-matching argumentsinputSchema in zod
AuthorizationChecks who asks for whatInside execute and the session layer
Permission scopeThe tool has only the rights it needsA service account with minimal rights
ApprovalA human confirms side effectsA step in the interface before execution
LogA trace of every callLogs 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.

  1. 01
    DescriptionShort, unambiguous, when to use the tool.
  2. 02
    SchemaZod with limits and value lists.
  3. 03
    AuthorizationWho, what and on which data.
  4. 04
    ExecutionMinimal permissions, parameterization.
  5. 05
    ApprovalFor side effects and irreversible actions.
  6. 06
    LogA 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.

Frequently asked questions

What is a tool's input schema?
A description of the arguments the tool accepts, written in zod or as JSON Schema. According to the AI SDK documentation it is read by the model and also used to validate tool calls.
Can a model call a tool with bad data?
Yes. The model generates arguments and can make mistakes or be manipulated. Schema validation is the first line of defence and a permission check in the execute function the second.
When should a tool run automatically?
Tools with an execute function run automatically after being called. For actions with side effects, add a human approval step.
What are dynamic tools?
Tools whose input and output types are not known at the time of writing the code, for example loaded from MCP servers. They need run-time validation even more.

Sources

JavaScript & Vercel AI SDK

Related