Give tools a schema

A Zod inputSchema rejects bad model input before execute.

AI SDK docsai-sdk.dev
The schema is consumed by the LLM, and also used to validate the LLM tool calls.
AI SDK Core · Tool CallingRead docs ↗

From ai-sdk and the Tool Calling docs.

The model sends odd input

Pick what the model passes to weather.

No schemaBad
execute on bad input 0Answer –
execute: async (input: any) => …
Zod inputSchemaGood
execute on bad input 0Answer –
inputSchema: z.object({ city: z.string() })

import { streamText, tool, isStepCount } from 'ai';
import { z } from 'zod';

const result = streamText({
  model: 'anthropic/claude-sonnet-5',
  messages: await convertToModelMessages(messages),
  stopWhen: isStepCount(5), // lets the model retry after a tool error
  tools: {
    weather: tool({
      description: 'Get the weather in a city (fahrenheit)',
      inputSchema: z.object({
        city: z.string().describe('City name, e.g. "Paris"'),
      }),
      // input is typed { city: string } and already validated
      execute: async ({ city }) => getWeather(city),
    }),
  },
});

Why it matters, pros and cons

Why it matters

Models guess argument names and types. A schema tells the model the shape, then checks what it sent.

Pros

  • execute never sees malformed input.
  • The error goes back to the model, which can fix the call.
  • execute's input is typed from the schema.

Cons

  • Schemas cost prompt tokens; keep them small.
  • Strict mode support varies by provider.
  • Valid shape is not valid data; check values too.