Unified tool calling in modern Next.js applications
The Vercel AI SDK provides a standard interface for connecting LLMs to external APIs across React Server Components, Server Actions, and Route Handlers.
When giving a chat assistant the ability to send emails, using tool() with a Zod schema guarantees type safety and enables client-side tool call rendering.
Defining the email tool with Zod schema validation
In your Next.js route handler (/api/chat/route.ts), define the email tool using the tool helper from the ai package.
import { openai } from '@ai-sdk/openai';
import { streamText, tool } from 'ai';
import { z } from 'zod';
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4o'),
messages,
tools: {
sendEmail: tool({
description: 'Send a transactional email notification to a team member or customer.',
parameters: z.object({
to: z.string().email().describe('The destination email address'),
subject: z.string().min(3).describe('Subject line of the email'),
text: z.string().min(5).describe('Plain-text body content'),
}),
execute: async ({ to, subject, text }) => {
const res = await fetch('https://api.sadasend.com/v1/emails', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SADASEND_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ to, subject, text }),
});
const data = await res.json();
return { success: res.ok, messageId: data.id, status: data.status };
},
}),
},
});
return result.toDataStreamResponse();
}Handling confirmation UI on the frontend
Because sending an email is a state-changing side effect, the frontend can inspect toolInvocations to display a rich preview card with a "Confirm Send" button before triggering the API.
Building AI agents that send email?
Join the SadaSend early access waitlist to get scoped API keys, recipient allowlists, and Model Context Protocol (MCP) servers upon launch.