Back to roadmaps vercel-ai-sdk Course

Declaring and Executing Server-Side Tools

In vanilla OpenAI APIs, handling function calls requires writing loops to catch model parameters, invoke local functions, push messages, and make subsequent API requests. The Vercel AI SDK simplifies this workflow using the tool wrapper.


1. Defining Tools with Automatic Execution

By adding an execute callback to your tool definition, the SDK will automatically trigger the local code whenever the model requests it:

// src/services/agentService.ts
import { generateText, tool } from "ai";
import { z } from "zod";
import { defaultModel } from "../lib/models";
import { prisma } from "../lib/prisma";

export async function runShoppingAgent(userQuestion: string) {
  const result = await generateText({
    model: defaultModel,
    prompt: userQuestion,
    // Register tools
    tools: {
      checkProductStock: tool({
        description: "Lookup current database stock count for a physical product name.",
        parameters: z.object({
          productName: z.string().describe("The item name to look up in the catalog."),
        }),
        // 1. Declare automatic execution logic
        execute: async (argumentsObj) => {
          const product = await prisma.product.findFirst({
            where: { name: argumentsObj.productName },
          });
          
          return {
            inStock: !!product && product.stockCount > 0,
            remainingCount: product?.stockCount || 0,
          };
        },
      }),
    },
  });

  // The SDK automatically calls execute(), sends results back, and returns final text
  return result.text;
}

2. Tool Calls in Streams

If you stream the completion using streamText, the execution result is accessible via the onToolCall event:

const result = await streamText({
  model: defaultModel,
  prompt: userQuestion,
  tools: {
    checkStock: tool({
      description: "Check product availability.",
      parameters: z.object({ productName: z.string() }),
      execute: async ({ productName }) => {
        return { count: 12 };
      },
    }),
  },
});

3. Best Practices

  • Use Descriptive Zod Fields: Call .describe("...") on schema keys. The model parses these comments to understand arguments parameters.
  • Timeout Protections: Inside execute, wrap third-party API calls in database timeouts to prevent blocking connection streams.
  • Type-Safety: Parameters passed to execute are automatically typed matching the validated Zod schema layout.
Published on Last updated: