File: prompt-engineering.md | Updated: 11/15/2025
Menu
v5 (Latest)
AI SDK 5.x
Model Context Protocol (MCP) Tools
Copy markdown
================================================================================================
When you create prompts that include tools, getting good results can be tricky as the number and complexity of your tools increases.
Here are a few tips to help you get the best results:
gpt-5 or gpt-4.1. Weaker models will often struggle to call tools effectively and flawlessly..describe("...") to your Zod schema properties to give the model hints about what a particular property is for.description field of a tool to provide information about the output of the tool execution.In general, the goal should be to give the model all information it needs in a clear way.
The mapping from Zod schemas to LLM inputs (typically JSON schema) is not always straightforward, since the mapping is not one-to-one.
Zod expects JavaScript Date objects, but models return dates as strings. You can specify and validate the date format using z.string().datetime() or z.string().date(), and then use a Zod transformer to convert the string to a Date object.
const result = await generateObject({ model: openai('gpt-4.1'), schema: z.object({ events: z.array( z.object({ event: z.string(), date: z .string() .date() .transform(value => new Date(value)), }), ), }), prompt: 'List 5 important events from the year 2000.',});
When working with tools that have optional parameters, you may encounter compatibility issues with certain providers that use strict schema validation.
This is particularly relevant for OpenAI models with structured outputs (strict mode).
For maximum compatibility, optional parameters should use .nullable() instead of .optional():
// This may fail with strict schema validationconst failingTool = tool({ description: 'Execute a command', inputSchema: z.object({ command: z.string(), workdir: z.string().optional(), // This can cause errors timeout: z.string().optional(), }),});
// This works with strict schema validationconst workingTool = tool({ description: 'Execute a command', inputSchema: z.object({ command: z.string(), workdir: z.string().nullable(), // Use nullable instead timeout: z.string().nullable(), }),});
For tool calls and object generation, it's recommended to use temperature: 0 to ensure deterministic and consistent results:
const result = await generateText({ model: openai('gpt-4o'), temperature: 0, // Recommended for tool calls tools: { myTool: tool({ description: 'Execute a command', inputSchema: z.object({ command: z.string(), }), }), }, prompt: 'Execute the ls command',});
Lower temperature values reduce randomness in model outputs, which is particularly important when the model needs to:
Not all providers support all AI SDK features. Providers either throw exceptions or return warnings when they do not support a feature. To check if your prompt, tools, and settings are handled correctly by the provider, you can check the call warnings:
const result = await generateText({ model: openai('gpt-4o'), prompt: 'Hello, world!',});
console.log(result.warnings);
You can inspect the raw HTTP request bodies for models that expose them, e.g. OpenAI . This allows you to inspect the exact payload that is sent to the model provider in the provider-specific way.
Request bodies are available via the request.body property of the response:
const result = await generateText({ model: openai('gpt-4o'), prompt: 'Hello, world!',});
console.log(result.request.body);
On this page
Tool & Structured Data Schemas
Deploy and Scale AI Apps with Vercel.
Vercel delivers the infrastructure and developer experience you need to ship reliable AI-powered applications at scale.
Trusted by industry leaders: