Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Wikedhart18/nextjs-ai-chatbot/llms.txt

Use this file to discover all available pages before exploring further.

Tools give the model the ability to take actions during a conversation — fetching data, creating documents, and more. Each tool is defined using the tool() helper from the Vercel AI SDK and registered in the chat route.

Tool structure

Every tool has three fields:
FieldPurpose
descriptionNatural language description the model uses to decide when to call the tool
parametersA Zod schema that defines and validates the tool’s input arguments
executeAsync function that receives the validated parameters and returns a result

Simple tool example: getWeather

lib/ai/tools/get-weather.ts is the simplest tool in the codebase. It fetches weather data from a public API and returns the JSON result directly to the model.
lib/ai/tools/get-weather.ts
import { tool } from 'ai';
import { z } from 'zod';

export const getWeather = tool({
  description: 'Get the current weather at a location',
  parameters: z.object({
    latitude: z.number(),
    longitude: z.number(),
  }),
  execute: async ({ latitude, longitude }) => {
    const response = await fetch(
      `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current=temperature_2m&hourly=temperature_2m&daily=sunrise,sunset&timezone=auto`,
    );

    const weatherData = await response.json();
    return weatherData;
  },
});
The return value from execute is serialized and sent back to the model as the tool result. The model can then use that data to compose its response.

Adding a custom tool

1

Create the tool file

Create a new file under lib/ai/tools/. Use get-weather.ts as a starting point.
lib/ai/tools/get-stock-price.ts
import { tool } from 'ai';
import { z } from 'zod';

export const getStockPrice = tool({
  description: 'Get the current stock price for a given ticker symbol',
  parameters: z.object({
    ticker: z.string().describe('The stock ticker symbol, e.g. AAPL'),
  }),
  execute: async ({ ticker }) => {
    const response = await fetch(
      `https://your-stock-api.example.com/quote/${ticker}`,
    );
    return response.json();
  },
});
Use .describe() on Zod fields to give the model more context about each parameter. The model reads these descriptions when deciding what values to pass.
2

Import the tool in the chat route

Open app/(chat)/api/chat/route.ts and import your tool at the top of the file alongside the existing tool imports:
app/(chat)/api/chat/route.ts
import { getWeather } from '@/lib/ai/tools/get-weather';
import { getStockPrice } from '@/lib/ai/tools/get-stock-price';
3

Register the tool in the tools object

Add your tool to the tools object passed to streamText:
app/(chat)/api/chat/route.ts
tools: {
  getWeather,
  getStockPrice,
  createDocument: createDocument({ session, dataStream }),
  updateDocument: updateDocument({ session, dataStream }),
  requestSuggestions: requestSuggestions({ session, dataStream }),
},
4

Add the tool to experimental_activeTools

The experimental_activeTools array controls which tools are offered to the model on each request. Add your tool’s key to the array:
app/(chat)/api/chat/route.ts
experimental_activeTools:
  selectedChatModel === 'chat-model-reasoning'
    ? []
    : [
        'getWeather',
        'getStockPrice',
        'createDocument',
        'updateDocument',
        'requestSuggestions',
      ],
Tools are disabled entirely for the reasoning model (chat-model-reasoning) because it does not support tool calling.

Streaming tools vs. simple tools

Not all tools work the same way. The codebase has two distinct patterns.
Simple tools like getWeather call tool() directly and return a plain value. The execute function has no side effects beyond the API call.
export const getWeather = tool({
  description: 'Get the current weather at a location',
  parameters: z.object({
    latitude: z.number(),
    longitude: z.number(),
  }),
  execute: async ({ latitude, longitude }) => {
    const response = await fetch(/* ... */);
    return response.json();
  },
});

Data stream event types

When a tool writes to dataStream, the client-side artifact components listen for specific event type values in their onStreamPart handler. The built-in event types are:
TypeEmitted byDescription
kindcreateDocumentArtifact type being created
idcreateDocumentNew document ID
titlecreateDocumentDocument title
clearcreateDocument, updateDocumentSignals the client to clear the artifact panel
text-deltatextDocumentHandlerIncremental text content chunk
code-deltacodeDocumentHandlerIncremental code content chunk
suggestionrequestSuggestionsA single inline suggestion object
finishcreateDocument, updateDocumentSignals streaming is complete
If you write a tool that streams custom UI data, define a new type string and handle it in the artifact client’s onStreamPart callback.

Build docs developers (and LLMs) love