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?
Scoped API keys, per-key recipient allowlists, approval mode and a hosted MCP server with ten tools — on the free plan, without a card.