Vercel AI SDK の使用
Mastra は、モデルのルーティング、React Hooks、データストリーミングに対応するために、Vercel の AI SDK と統合されています。
AI SDK v5
Mastra は AI SDK v5 にも対応しています。v5 固有のメソッドについては、次のセクションをご覧ください: Vercel AI SDK v5
このページのコード例は、プロジェクトのルートで Next.js の App Router を使用していることを前提としています。
例: src/app
ではなく app
を使用します。
モデルのルーティング
Mastra でエージェントを作成する際は、AI SDK がサポートする任意のモデルを指定できます。
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
export const weatherAgent = new Agent({
name: "Weather Agent",
instructions: "Instructions for the agent...",
model: openai("gpt-4-turbo"),
});
詳細は Model Providers と Model Capabilities をご覧ください。
React Hooks
Mastra は、HTTP ストリームを用いてフロントエンドコンポーネントをエージェントに直接接続するための AI SDK のフックをサポートしています。
必要な AI SDK React パッケージをインストールします:
npm
npm install @ai-sdk/react
useChat()
フックの使用
useChat
フックは、フロントエンドと Mastra エージェント間のリアルタイムなチャット対話を処理し、プロンプトの送信と HTTP 経由でのストリーミング応答の受信を可能にします。
"use client";
import { useChat } from "@ai-sdk/react";
export function Chat() {
const { messages, input, handleInputChange, handleSubmit } = useChat({
api: "/api/chat"
});
return (
<div>
<pre>{JSON.stringify(messages, null, 2)}</pre>
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} placeholder="Name of city" />
</form>
</div>
);
}
useChat
フックで送信されたリクエストは、標準的なサーバールートで処理されます。次の例は、Next.js の Route Handler を使って POST ルートを定義する方法を示しています。
import { mastra } from "../../mastra";
export async function POST(req: Request) {
const { messages } = await req.json();
const myAgent = mastra.getAgent("weatherAgent");
const stream = await myAgent.stream(messages);
return stream.toDataStreamResponse();
}
エージェントメモリと併用して
useChat
を使う場合は、重要な実装上のポイントについて Agent Memory セクション を参照してください。
useCompletion()
フックの使用
useCompletion
フックは、フロントエンドと Mastra エージェント間の単発の補完処理を行い、プロンプトを送信して HTTP 経由でストリーミング応答を受け取れます。
"use client";
import { useCompletion } from "@ai-sdk/react";
export function Completion() {
const { completion, input, handleInputChange, handleSubmit } = useCompletion({
api: "api/completion"
});
return (
<div>
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} placeholder="Name of city" />
</form>
<p>Completion result: {completion}</p>
</div>
);
}
useCompletion
フックで送信されたリクエストは、標準的なサーバールートで処理されます。次の例は、Next.js の Route Handler を使って POST ルートを定義する方法を示しています。
import { mastra } from "../../../mastra";
export async function POST(req: Request) {
const { prompt } = await req.json();
const myAgent = mastra.getAgent("weatherAgent");
const stream = await myAgent.stream([{ role: "user", content: prompt }]);
return stream.toDataStreamResponse();
}
useObject()
フックの使用
useObject
フックは、Mastra エージェントからのストリーミングテキストを受け取り、定義したスキーマに基づいて構造化された JSON オブジェクトへとパースします。
"use client";
import { experimental_useObject as useObject } from "@ai-sdk/react";
import { z } from "zod";
export function Object() {
const { object, submit } = useObject({
api: "api/object",
schema: z.object({
weather: z.string()
})
});
return (
<div>
<button onClick={() => submit("London")}>Generate</button>
{object ? <pre>{JSON.stringify(object, null, 2)}</pre> : null}
</div>
);
}
useObject
フックで送信されたリクエストは、標準的なサーバールートで処理されます。次の例は、Next.js の Route Handler を使って POST ルートを定義する方法を示しています。
import { mastra } from "../../../mastra";
import { z } from "zod";
export async function POST(req: Request) {
const body = await req.json();
const myAgent = mastra.getAgent("weatherAgent");
const stream = await myAgent.stream(body, {
output: z.object({
weather: z.string()
})
});
return stream.toTextStreamResponse();
}
sendExtraMessageFields
で追加データを渡す
sendExtraMessageFields
オプションを使うと、フロントエンドから Mastra に追加データを渡せます。このデータはサーバー側で RuntimeContext
として利用できます。
"use client";
import { useChat } from "@ai-sdk/react";
export function ChatExtra() {
const { messages, input, handleInputChange, handleSubmit } = useChat({
api: "/api/chat-extra",
sendExtraMessageFields: true
});
const handleFormSubmit = (e: React.FormEvent) => {
e.preventDefault();
handleSubmit(e, {
data: {
userId: "user123",
preferences: {
language: "en",
temperature: "celsius"
}
}
});
};
return (
<div>
<pre>{JSON.stringify(messages, null, 2)}</pre>
<form onSubmit={handleFormSubmit}>
<input value={input} onChange={handleInputChange} placeholder="Name of city" />
</form>
</div>
);
}
sendExtraMessageFields
を使って送信されたリクエストは、通常のサーバールートで処理されます。次の例では、カスタムデータを取り出して RuntimeContext
インスタンスに設定する方法を示します。
import { mastra } from "../../../mastra";
import { RuntimeContext } from "@mastra/core/runtime-context";
export async function POST(req: Request) {
const { messages, data } = await req.json();
const myAgent = mastra.getAgent("weatherAgent");
const runtimeContext = new RuntimeContext();
if (data) {
for (const [key, value] of Object.entries(data)) {
runtimeContext.set(key, value);
}
}
const stream = await myAgent.stream(messages, { runtimeContext });
return stream.toDataStreamResponse();
}
server.middleware
による runtimeContext
の取り扱い
サーバーのミドルウェアでカスタムデータを読み取り、RuntimeContext
に設定することもできます:
import { Mastra } from "@mastra/core/mastra";
export const mastra = new Mastra({
agents: { weatherAgent },
server: {
middleware: [
async (c, next) => {
const runtimeContext = c.get("runtimeContext");
if (c.req.method === "POST") {
try {
const clonedReq = c.req.raw.clone();
const body = await clonedReq.json();
if (body?.data) {
for (const [key, value] of Object.entries(body.data)) {
runtimeContext.set(key, value);
}
}
} catch {
}
}
await next();
},
],
},
});
その後、このデータには
runtimeContext
パラメータ経由でツールからアクセスできます。詳しくは Runtime Context のドキュメント を参照してください。
ストリーミングデータ
ai
パッケージは、カスタムデータストリームを管理するためのユーティリティを提供します。場合によっては、エージェントの dataStream
を使って、構造化された更新や注釈(アノテーション)をクライアントへ送信したいことがあります。
必要なパッケージをインストールします:
npm
npm install ai
createDataStream()
の使用
createDataStream
関数を使うと、クライアントへ追加のデータをストリーミングできます。
import { createDataStream } from "ai";
import { Agent } from "@mastra/core/agent";
export const weatherAgent = new Agent({...});
createDataStream({
async execute(dataStream) {
dataStream.writeData({ value: "Hello" });
dataStream.writeMessageAnnotation({ type: "status", value: "processing" });
const agentStream = await weatherAgent.stream("What is the weather");
agentStream.mergeIntoDataStream(dataStream);
},
onError: (error) => `Custom error: ${error}`
});
createDataStreamResponse()
の使用
createDataStreamResponse
関数は、クライアントにデータをストリーミングするレスポンスオブジェクトを作成します。
import { mastra } from "../../../mastra";
import { createDataStreamResponse } from "ai";
export async function POST(req: Request) {
const { messages } = await req.json();
const myAgent = mastra.getAgent("weatherAgent");
const agentStream = await myAgent.stream(messages);
const response = createDataStreamResponse({
status: 200,
statusText: "OK",
headers: {
"Custom-Header": "value"
},
async execute(dataStream) {
dataStream.writeData({ value: "Hello" });
dataStream.writeMessageAnnotation({
type: "status",
value: "processing"
});
agentStream.mergeIntoDataStream(dataStream);
},
onError: (error) => `Custom error: ${error}`
});
return response;
}
Vercel AI SDK v5
このガイドでは、AI SDK v4 から v5 への移行における Mastra 固有の考慮事項を説明します。
フィードバックやバグ報告は、GitHub の AI SDK v5 メガイシュー にお寄せください。
実験的な streamVNext サポート
Mastra の実験的な streamVNext
メソッドは、format
パラメータにより AI SDK v5 をネイティブにサポートします。これにより、互換レイヤーを用意しなくても、AI SDK v5 のストリーミングインターフェースとシームレスに連携できます。
// Use streamVNext with AI SDK v5 format
const stream = await agent.streamVNext(messages, {
format: 'aisdk' // Enable AI SDK v5 compatibility
});
// The stream is now compatible with AI SDK v5 interfaces
return stream.toUIMessageStreamResponse();
公式移行ガイド
AI SDK のコアにおける破壊的変更、パッケージ更新、API 変更については、公式の AI SDK v5 Migration Guide に従ってください。
このガイドでは、移行のうち Mastra 固有の内容のみを扱います。
- データ互換性: v5 形式で保存された新しいデータは、v5 から v4 へダウングレードすると動作しません
- バックアップの推奨: v5 へアップグレードする前の DB バックアップを保存してください
メモリとストレージ
Mastra は内部の MessageList
クラスにより AI SDK v4 のデータを自動的に処理します。このクラスが形式変換(v4 から v5 を含む)を管理します。データベースのマイグレーションは不要で、既存のメッセージはオンザフライで変換され、アップグレード後もそのまま動作します。
メッセージ形式の変換
AI SDK と Mastra の形式間でメッセージを手動で変換する必要がある場合は、convertMessages
ユーティリティを使用してください。
import { convertMessages } from '@mastra/core/agent';
// Convert AI SDK v4 messages to v5
const aiv5Messages = convertMessages(aiv4Messages).to('AIV5.UI');
// Convert Mastra messages to AI SDK v5
const aiv5Messages = convertMessages(mastraMessages).to('AIV5.Core');
// Supported output formats:
// 'Mastra.V2', 'AIV4.UI', 'AIV5.UI', 'AIV5.Core', 'AIV5.Model'
このユーティリティは、ストレージ DB からメッセージを直接取得し、AI SDK で利用できる形式に変換したい場合に役立ちます。
ストリーム互換性の有効化
AI SDK v5 互換性を有効化するには、@mastra/ai-sdk
パッケージを使用します。
npm
npm install @mastra/ai-sdk
import { Mastra } from '@mastra/core/mastra';
import { chatRoute } from '@mastra/ai-sdk';
export const mastra = new Mastra({
server: {
apiRoutes: [
chatRoute({
path: '/chat',
agent: 'weatherAgent',
}),
],
},
});
アプリケーション内で useChat()
フックを呼び出してください。
const { error, status, sendMessage, messages, regenerate, stop } =
useChat({
transport: new DefaultChatTransport({
api: 'http://localhost:4111/chat',
}),
});
Note: フォーマット対応のある streamVNext
メソッドは実験的であり、フィードバックに基づいて機能を改善する過程で変更される可能性があります。詳細は Agent Streaming のドキュメントをご覧ください。
ツールの型推論
AI SDK v5 で TypeScript とツールを併用する場合、Mastra はツールの入力・出力に対する型安全性を確保するための型推論ヘルパーを提供します。
InferUITool
InferUITool
型ヘルパーは、単一の Mastra ツールの入出力型を推論します。
import { InferUITool, createTool } from "@mastra/core/tools";
import { z } from "zod";
const weatherTool = createTool({
id: "get-weather",
description: "現在の天気を取得",
inputSchema: z.object({
location: z.string().describe("市区町村と州(または都道府県)"),
}),
outputSchema: z.object({
temperature: z.number(),
conditions: z.string(),
}),
execute: async ({ context }) => {
return {
temperature: 72,
conditions: "sunny",
};
},
});
// ツールから型を推論
type WeatherUITool = InferUITool<typeof weatherTool>;
// これにより次の型が生成されます:
// {
// input: { location: string };
// output: { temperature: number; conditions: string };
// }
InferUITools
InferUITools
型ヘルパーは、複数ツールの入力型と出力型を推論します。
import { InferUITools, createTool } from "@mastra/core/tools";
import { z } from "zod";
// 前の例の weatherTool を使用
const tools = {
weather: weatherTool,
calculator: createTool({
id: "calculator",
description: "基本的な四則演算を実行",
inputSchema: z.object({
operation: z.enum(["add", "subtract", "multiply", "divide"]),
a: z.number(),
b: z.number(),
}),
outputSchema: z.object({
result: z.number(),
}),
execute: async ({ context }) => {
// 実装...
return { result: 0 };
},
}),
};
// ツールセットから型を推論
export type MyUITools = InferUITools<typeof tools>;
// これにより次の型が生成されます:
// {
// weather: { input: { location: string }; output: { temperature: number; conditions: string } };
// calculator: { input: { operation: "add" | "subtract" | "multiply" | "divide"; a: number; b: number }; output: { result: number } };
// }
これらの型ヘルパーは、Mastra のツールを AI SDK v5 の UI コンポーネントと組み合わせて使用する際に TypeScript を完全にサポートし、アプリケーション全体の型安全性を確保します。