Call Tools

Some models allow developers to provide a list of tools that can be called at any time during a generation. This is useful for extending the capabilites of a language model to either use logic or data to interact with systems external to the model.

http://localhost:3000
User: How is it going?
Assistant: All good, how may I help you?
What is the weather in Paris and New York?
Send Message

Client

Let's create a React component that imports the useChat hook from the @ai-sdk/react module. The useChat hook will call the /api/chat endpoint when the user sends a message. The endpoint will generate the assistant's response based on the conversation history and stream it to the client. If the assistant responds with a tool call, the hook will automatically display them as well.

app/page.tsx
'use client';
import { useChat } from '@ai-sdk/react';
import { DefaultChatTransport } from 'ai';
import { useState } from 'react';
import type { ChatMessage } from './api/chat/route';
export default function Page() {
const [input, setInput] = useState('');
const { messages, sendMessage } = useChat<ChatMessage>({
transport: new DefaultChatTransport({
api: '/api/chat',
}),
});
return (
<div>
<input
className="border"
value={input}
onChange={event => {
setInput(event.target.value);
}}
onKeyDown={async event => {
if (event.key === 'Enter') {
sendMessage({
text: input,
});
setInput('');
}
}}
/>
{messages.map((message, index) => (
<div key={index}>
{message.parts.map(part => {
switch (part.type) {
case 'text':
return <div key={`${message.id}-text`}>{part.text}</div>;
case 'tool-getWeather':
return (
<div key={`${message.id}-weather`}>
{JSON.stringify(part, null, 2)}
</div>
);
}
})}
</div>
))}
</div>
);
}

Server

You will create a new route at /api/chat that will use the streamText function from the ai module to generate the assistant's response based on the conversation history.

You will use the tools parameter to specify a tool called celsiusToFahrenheit that will convert a user given value in celsius to fahrenheit.

You will also use zod to specify the schema for the celsiusToFahrenheit function's parameters.

app/api/chat/route.ts
import { openai } from '@ai-sdk/openai';
import {
type InferUITools,
type ToolSet,
type UIDataTypes,
type UIMessage,
convertToModelMessages,
stepCountIs,
streamText,
tool,
} from 'ai';
import { z } from 'zod';
const tools: ToolSet = {
getWeather: tool({
description: 'Get the weather for a location',
inputSchema: z.object({
city: z.string().describe('The city to get the weather for'),
unit: z
.enum(['C', 'F'])
.describe('The unit to display the temperature in'),
}),
execute: async ({ city, unit }) => {
const weather = {
value: 24,
description: 'Sunny',
};
return `It is currently ${weather.value}°${unit} and ${weather.description} in ${city}!`;
},
}),
};
export type ChatTools = InferUITools<typeof tools>;
export type ChatMessage = UIMessage<never, UIDataTypes, ChatTools>;
export async function POST(req: Request) {
const { messages }: { messages: ChatMessage[] } = await req.json();
const result = streamText({
model: openai('gpt-4o'),
system: 'You are a helpful assistant.',
messages: convertToModelMessages(messages),
stopWhen: stepCountIs(5),
tools,
});
return result.toUIMessageStreamResponse();
}

View Example on GitHub