Skip to main content

Command Palette

Search for a command to run...

Vercel AI SDK Tool Calling Cheat Sheet

Updated
3 min read
Vercel AI SDK Tool Calling Cheat Sheet

1. Basic Tool Definition

import { z } from "zod";
import { tool, generateText } from "ai";

// Define a tool
const weatherTool = tool({
  description: "Get weather for a location",
  parameters: z.object({
    location: z.string().describe("City name"),
    unit: z.enum(["celsius", "fahrenheit"]).optional(),
  }),
  execute: async ({ location, unit = "celsius" }) => {
    // Implement weather lookup
    return { temperature: 22, conditions: "Sunny" };
  },
});

// Use the tool
const result = await generateText({
  model: yourModel,
  tools: { weather: weatherTool },
  prompt: "What's the weather in Paris?",
});

2. Tool Control Options

// Default -> model chooses whether to use tools
toolChoice: 'auto'

// Force the model to use a tool
toolChoice: 'required'

// Prevent tool usage
toolChoice: 'none'

// Force specific tool
toolChoice: { type: 'tool', toolName: 'weather' }

3. Multi-Step Tool Interactions

const { text, steps } = await generateText({
  model: yourModel,
  tools: { weather: weatherTool },
  maxSteps: 3, // Allow up to 3 steps (tool call → result → text)
  prompt: "Weather in Paris?",

  // Optional callback for each step
  onStepFinish({ text, toolCalls, toolResults }) {
    console.log(`Step completed with ${toolCalls.length} tool calls`);
  },
});

// Access all tool calls/results
const allToolCalls = steps.flatMap((step) => step.toolCalls);

4. Error Handling

try {
  const result = await generateText({
    model: yourModel,
    tools: { weather: weatherTool },
    prompt: "Weather forecast?",
  });
} catch (error) {
  // Tool doesn't exist
  if (NoSuchToolError.isInstance(error)) {
  }

  // Invalid arguments
  if (InvalidToolArgumentsError.isInstance(error)) {
  }

  // Error during execution
  if (ToolExecutionError.isInstance(error)) {
  }
}

// With streaming
return result.toDataStreamResponse({
  getErrorMessage: (error) => {
    if (NoSuchToolError.isInstance(error)) return "Unknown tool requested";
    // Handle other error types...
  },
});

5. Type Safety

import { ToolCallUnion, ToolResultUnion } from "ai";

// Create a tool set
const myTools = {
  weather: weatherTool,
  calculator: calculatorTool,
};

// Type helpers
type MyToolCall = ToolCallUnion<typeof myTools>;
type MyToolResult = ToolResultUnion<typeof myTools>;

// Type-safe function for processing results
function processToolResult(result: MyToolResult) {
  if (result.toolName === "weather") {
    // TypeScript knows the shape of weather results
    return `It's ${result.result.temperature}° and ${result.result.conditions}`;
  }
}

6. Tool Context & Execution Options

const contextTool = tool({
  description: "Sample tool with context",
  parameters: z.object({ query: z.string() }),
  execute: async (args, context) => {
    // Tool call ID
    const id = context.toolCallId;

    // Conversation history
    const history = context.messages;

    // Handle cancellation
    context.abortSignal.addEventListener("abort", () => {
      // Clean up resources
    });

    return { result: "Done" };
  },
});

7. Repairing Tool Calls

const result = await generateText({
  model: yourModel,
  tools: myTools,
  prompt: "Calculate 5+7",

  experimental_repairToolCall: async ({ toolCall, tools, error }) => {
    if (error.name === "InvalidToolArgumentsError") {
      // Fix invalid arguments and return new tool call
      return {
        ...toolCall,
        args: JSON.stringify({ a: 5, b: 7 }),
      };
    }
    return null; // Can't repair
  },
});

8. Conversation Management

// Initial conversation
const messages = [{ role: "user", content: "What's the weather?" }];

// Generate with tools
const { response } = await generateText({
  model: yourModel,
  tools: { weather: weatherTool },
  messages,
});

// Update conversation history with all messages (text, tool calls, results)
// needed for memory
messages.push(...response.messages);