Skip to Content
ExamplesAgentsAI SDK v5 Integration

Example: AI SDK v5 Integration

This example demonstrates how to integrate Mastra agents with AI SDK v5  to build modern streaming chat interfaces. It showcases a complete Next.js application with real-time conversation capabilities, persistent memory, and tool integration.

Key Features

  • Streaming Chat Interface: Uses AI SDK v5’s useChat hook for real-time conversations
  • Mastra Agent Integration: Weather agent with custom tools and OpenAI GPT-4o
  • Persistent Memory: Conversation history stored with LibSQL
  • Compatibility Layer: Seamless integration between Mastra and AI SDK v5 streams
  • Tool Integration: Custom weather tool for real-time data fetching

Mastra Configuration

First, set up your Mastra agent with memory and tools:

src/mastra/index.ts
import { ConsoleLogger } from "@mastra/core/logger"; import { Mastra } from "@mastra/core/mastra"; import { weatherAgent } from "./agents"; export const mastra = new Mastra({ agents: { weatherAgent }, logger: new ConsoleLogger(), // aiSdkCompat: "v4", // Optional: for additional compatibility });
src/mastra/agents/index.ts
import { Agent } from "@mastra/core/agent"; import { openai } from "@ai-sdk/openai"; import { Memory } from "@mastra/memory"; import { LibSQLStore } from "@mastra/libsql"; import { weatherTool } from "../tools"; export const memory = new Memory({ storage: new LibSQLStore({ url: `file:./mastra.db`, }), options: { semanticRecall: false, workingMemory: { enabled: false, }, lastMessages: 5 }, }); export const weatherAgent = new Agent({ name: "Weather Agent", instructions: ` You are a helpful weather assistant that provides accurate weather information. Your primary function is to help users get weather details for specific locations. When responding: - Always ask for a location if none is provided - Include relevant details like humidity, wind conditions, and precipitation - Keep responses concise but informative Use the weatherTool to fetch current weather data. `, model: openai("gpt-4o"), tools: { weatherTool, }, memory, });

Custom Weather Tool

Create a tool that fetches real-time weather data:

src/mastra/tools/index.ts
import { createTool } from '@mastra/core/tools'; import { z } from 'zod'; export const weatherTool = createTool({ id: 'get-weather', description: 'Get current weather for a location', inputSchema: z.object({ location: z.string().describe('City name'), }), outputSchema: z.object({ temperature: z.number(), feelsLike: z.number(), humidity: z.number(), windSpeed: z.number(), windGust: z.number(), conditions: z.string(), location: z.string(), }), execute: async ({ context }) => { return await getWeather(context.location); }, }); const getWeather = async (location: string) => { // Geocoding API call const geocodingUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(location)}&count=1`; const geocodingResponse = await fetch(geocodingUrl); const geocodingData = await geocodingResponse.json(); if (!geocodingData.results?.[0]) { throw new Error(`Location '${location}' not found`); } const { latitude, longitude, name } = geocodingData.results[0]; // Weather API call const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current=temperature_2m,apparent_temperature,relative_humidity_2m,wind_speed_10m,wind_gusts_10m,weather_code`; const response = await fetch(weatherUrl); const data = await response.json(); return { temperature: data.current.temperature_2m, feelsLike: data.current.apparent_temperature, humidity: data.current.relative_humidity_2m, windSpeed: data.current.wind_speed_10m, windGust: data.current.wind_gusts_10m, conditions: getWeatherCondition(data.current.weather_code), location: name, }; };

Next.js API Routes

Streaming Chat Endpoint

Create an API route that streams responses from your Mastra agent:

app/api/chat/route.ts
import { mastra } from "@/src/mastra"; import { createV4CompatibleResponse } from "@mastra/core/agent"; const myAgent = mastra.getAgent("weatherAgent"); export async function POST(req: Request) { const { messages } = await req.json(); const stream = await myAgent.stream(messages, { threadId: "user-session", // Use actual user/session ID resourceId: "weather-chat", }); // Convert Mastra stream to AI SDK v5 compatible format return createV4CompatibleResponse(stream.toUIMessageStreamResponse().body!); }

Initial Chat History

Load conversation history from Mastra Memory:

app/api/initial-chat/route.ts
import { mastra } from "@/src/mastra"; import { NextResponse } from "next/server"; const myAgent = mastra.getAgent("weatherAgent"); export async function GET() { const result = await myAgent.getMemory()?.query({ threadId: "user-session", }); return NextResponse.json(result?.uiMessages || []); }

React Chat Interface

Build the frontend using AI SDK v5’s useChat hook:

app/page.tsx
"use client"; import { Message, useChat } from "@ai-sdk/react"; import useSWR from "swr"; const fetcher = (url: string) => fetch(url).then((res) => res.json()); export default function Chat() { // Load initial conversation history const { data: initialMessages = [] } = useSWR<Message[]>( "/api/initial-chat", fetcher, ); // Set up streaming chat with AI SDK v5 const { messages, input, handleInputChange, handleSubmit } = useChat({ initialMessages, }); return ( <div className="flex flex-col w-full max-w-md py-24 mx-auto stretch"> {messages.map((m) => ( <div key={m.id} className="whitespace-pre-wrap" style={{ marginTop: "1em" }} > <h3 style={{ fontWeight: "bold", color: m.role === "user" ? "green" : "yellow", }} > {m.role === "user" ? "User: " : "AI: "} </h3> {m.parts.map((p) => p.type === "text" && p.text).join("\n")} </div> ))} <form onSubmit={handleSubmit}> <input className="fixed dark:bg-zinc-900 bottom-0 w-full max-w-md p-2 mb-8 border border-zinc-300 dark:border-zinc-800 rounded shadow-xl" value={input} placeholder="Ask about the weather..." onChange={handleInputChange} /> </form> </div> ); }

Package Configuration

Install the required dependencies:

NOTE: ai-sdk v5 is still in beta, while it is in beta you’ll have to install the beta ai-sdk versions and the beta mastra versions. See here  for more information

package.json
{ "dependencies": { "@ai-sdk/openai": "2.0.0-beta.1", "@ai-sdk/react": "2.0.0-beta.1", "@mastra/core": "0.0.0-ai-v5-20250625173645", "@mastra/libsql": "0.0.0-ai-v5-20250625173645", "@mastra/memory": "0.0.0-ai-v5-20250625173645", "next": "15.1.7", "react": "^19.0.0", "react-dom": "^19.0.0", "swr": "^2.3.3", "zod": "^3.25.67" } }

Key Integration Points

Compatibility Layer

The createV4CompatibleResponse function bridges Mastra’s streaming format with AI SDK v5:

// Converts Mastra stream to AI SDK v5 compatible format return createV4CompatibleResponse(stream.toUIMessageStreamResponse().body!);

Memory Persistence

Conversations are automatically persisted using Mastra Memory:

  • Each conversation uses a unique threadId
  • History is loaded on page refresh via /api/initial-chat
  • New messages are automatically stored by the agent

Tool Integration

The weather tool is seamlessly integrated:

  • Agent automatically calls the tool when weather information is needed
  • Real-time data is fetched from external APIs
  • Structured output ensures consistent responses

Running the Example

  1. Set your OpenAI API key:
echo "OPENAI_API_KEY=your_key_here" > .env.local
  1. Start the development server:
pnpm dev
  1. Visit http://localhost:3000 and ask about weather in different cities!





View Example on GitHub