Mastraの基本機能と何ができるか
はじめに
TypeScriptでAIエージェントの開発ができると噂のMastraを試してみたくなり、主要機能をざっと調べてみました。
この記事では、エージェントやワークフロー、RAGなどMastraの基本機能を一通り紹介し、「どんなことができるのか」をざっくり掴めるようまとめてみました。より高度な機能や環境構築、デプロイ方法など詳しい設定方法を知りたい方は、公式ドキュメントを参照してみてください。
Mastraとは
Mastraは、AIエージェント、ワークフロー、RAGなどの機能を統合的に提供するTypeScriptフレームワークです。VercelのAI SDKをベースにしており、OpenAI、Anthropic、Google Geminiなど様々なAIプロバイダーとシームレスに連携できます。オープンソースであるため、カスタマイズ性が高く、コミュニティによる継続的な改善が期待できます。
Mastraの主要コンポーネントと機能
以下の主要コンポーネントで構成されています。
エージェント
エージェントは、LLMを活用して特定のタスクを実行する、会話型AIの中核となるコンポーネントです。エージェントは以下の特徴を持ちます。
- メモリ機能: 会話の文脈を保持し、過去のやり取りを踏まえた応答を生成できます。
- ツール利用: 外部API(天気情報、検索エンジンなど)を呼び出し、LLMの応答を補完できます。
- LLMプロバイダー連携: OpenAI、Anthropic、Google Geminiなど、様々なLLMプロバイダーに対応しています。
ユースケース例:
- カスタマーサポートチャットボット
- パーソナルアシスタント
- Eコマースの商品レコメンダー
コード例:
import { Agent } from "@mastra/core/agent";
import { openai } from "@ai-sdk/openai";
import { weatherTool } from "../tools/weather-tool"; // 天気情報取得ツール
export const weatherAgent = new Agent({
name: "Weather Agent",
instructions: `あなたは天気情報を提供するアシスタントです。
ユーザーの質問に対して、正確な天気情報を提供してください。
場所が指定されていない場合は、場所を尋ねてください。`,
model: openai("gpt-4o"), // OpenAIのGPT-4oモデルを使用
tools: {
weatherTool, // 天気情報取得ツールを追加
},
});
ワークフロー
ワークフローは、LLM呼び出しやその他の処理を組み合わせ、複雑なタスクを自動化するための機能です。
- ステップ定義: 個別の処理(LLM呼び出し、関数実行など)をステップとして定義します。
- 制御フロー: ステップ間の依存関係、条件分岐、並列処理などを定義できます。
- 状態管理: 各ステップの入出力を記録し、ワークフロー全体の実行状態を追跡できます。
ユースケース例:
- コンテンツ生成(アイデア出し、記事作成、フォーマット)
- データ分析(データ収集、前処理、分析、レポート作成)
- ビジネスプロセス自動化(承認フロー、顧客対応)
コード例:
import { Workflow, step } from "@mastra/core/workflow";
import { openai } from "@ai-sdk/openai";
export const contentCreationWorkflow = new Workflow({
name: "Content Creation",
steps: {
generateIdeas: step({ // アイデア生成ステップ
execute: async ({ input }) => {
const response = await openai("gpt-4").generate({
prompt: `以下のトピックに関するコンテンツのアイデアを5つ生成してください: ${input.topic}`,
});
return { ideas: response.text.split("\n") };
},
}),
expandIdea: step({ // アイデア詳細化ステップ
execute: async ({ input, context }) => {
const selectedIdea = context.ideas[input.selectedIndex];
const response = await openai("gpt-4").generate({
prompt: `以下のアイデアを詳細に展開してください: ${selectedIdea}`,
});
return { expandedContent: response.text };
},
}).after("generateIdeas"), // generateIdeasステップの後に実行
formatContent: step({ // コンテンツフォーマットステップ
execute: async ({ context }) => {
const response = await openai("gpt-4").generate({
prompt: `以下の内容をブログ記事形式にフォーマットしてください: ${context.expandedContent}`,
});
return { formattedContent: response.text };
},
}).after("expandIdea"), // expandIdeaステップの後に実行
},
});
RAG
RAG(Retrieval-Augmented Generation)機能は、独自のデータソース(ドキュメント、データベースなど)を活用して、LLMの応答をより正確で信頼性の高いものにします。
- データ処理: ドキュメントをチャンクに分割し、埋め込みベクトルを生成します。
- ベクトルデータベース: 埋め込みベクトルを保存し、高速な検索を可能にします。
- LLM連携: 検索結果をLLMの入力として与え、応答を生成します。
ユースケース例:
- 社内ドキュメント検索
- 製品FAQシステム
- 研究論文の要約
コード例:
import { chunk } from "@mastra/core/rag";
import { embed } from "@mastra/core/embeddings";
import { pgvector } from "@mastra/core/vector-stores"; // PostgreSQL + pgvectorを使用
// 文書をチャンクに分割
const chunks = await chunk({
text: documentText, // ドキュメントのテキスト
chunkSize: 1000, // チャンクサイズ
chunkOverlap: 200, // チャンクオーバーラップ
});
// チャンクを埋め込みベクトルに変換
const embeddings = await embed({
chunks,
provider: "openai", // OpenAIの埋め込みモデルを使用
});
// ベクトルデータベースに保存
await pgvector.insert({
embeddings,
collection: "company_docs", // コレクション名
metadata: {
source: "product_manual", // メタデータ
date: new Date().toISOString(),
},
});
Voice(音声機能)
ElevenLabs、OpenAI、Google Cloud Text-to-Speechなど、様々な音声プロバイダーをサポートしており、AIエージェントに音声対話機能を追加できます。
ユースケース例:
- 音声アシスタント
- 音声対応チャットボット
- オーディオブック生成
コード例:
import { Agent } from "@mastra/core/agent";
import { openai } from "@ai-sdk/openai";
import { MastraVoice } from "@mastra/core/voice";
import { elevenlabs } from "@mastra/core/voice/providers"; // ElevenLabsを使用
export const voiceAssistant = new Agent({
name: "Voice Assistant",
instructions: `あなたは音声アシスタントです。簡潔に回答してください。`,
model: openai("gpt-4"),
voice: new MastraVoice({
provider: elevenlabs({
apiKey: process.env.ELEVENLABS_API_KEY, // APIキー
}),
voiceId: "voice-id-here", // 音声ID
settings: {
stability: 0.5,
similarity_boost: 0.8,
},
}),
});
Evals(評価機能)
Mastraの評価機能は、AIモデルの出力(応答)の品質を自動的に評価するためのツールです。毒性、バイアス、関連性、事実の正確性など、様々な観点から評価できます。
ユースケース例:
- AIモデルの品質管理
- A/Bテスト
- 継続的な改善
組み込みの評価指標:
- 毒性 (Toxicity)
- バイアス (Bias)
- 関連性 (Relevance)
- 事実の正確性 (Factual Accuracy)
コード例:
import { answerRelevancy, toxicity, bias } from "@mastra/core/evals";
// AI応答の品質を評価
const evalResults = await Promise.all([
// 回答の関連性を評価
answerRelevancy.evaluate({
question: "気候変動の主な原因は何ですか?",
answer: aiResponse,
context: referenceText,
}),
// 毒性を評価
toxicity.evaluate({
text: aiResponse,
}),
// バイアスを評価
bias.evaluate({
text: aiResponse,
}),
]);
console.log("評価結果:", evalResults);
ストレージ
PostgreSQL、LibSQL、Upstashなど、様々なストレージオプションをサポートしており、エージェントのメモリやワークフローの状態を永続化できます。
ユースケース例:
- 会話履歴の保存
- ワークフローの状態保持
- ユーザー設定の保存
コード例:
import { libsql } from "@mastra/core/storage";
// LibSQLストレージプロバイダーの設定
export const storage = libsql({
url: process.env.DATABASE_URL,
authToken: process.env.DATABASE_AUTH_TOKEN,
});
// メモリの保存
export async function saveConversation(threadId: string, messages: any[]) {
await storage.set(`conversation:${threadId}`, {
messages,
updatedAt: new Date().toISOString(),
});
}
// メモリの取得
export async function getConversation(threadId: string) {
return await storage.get(`conversation:${threadId}`);
}
// メモリの削除
export async function deleteConversation(threadId: string) {
await storage.delete(`conversation:${threadId}`);
}
エージェントネットワーク(Experimental)
エージェントネットワーク機能は、複数のエージェントを連携させ、より複雑なタスクを解決できます。エージェント間のメッセージルーティング、階層構造、協調作業などが可能です。
ただし、実験的機能なので今後変更していく可能性も高いです。
ユースケース例:
- マルチステップの顧客サポート(一般→専門)
- 異なる専門知識を持つAIの連携
- 複雑なタスクの分担と統合
コード例:
import { AgentNetwork } from "@mastra/core/networks";
import { customerAgent } from "../agents/customer";
import { techSupportAgent } from "../agents/tech-support";
import { salesAgent } from "../agents/sales";
export const customerServiceNetwork = new AgentNetwork({
name: "Customer Service Network",
agents: {
customer: customerAgent,
techSupport: techSupportAgent,
sales: salesAgent,
},
routing: {
// エージェント間のルーティング設定
default: "customer", // デフォルトはカスタマーエージェントが対応
rules: [
{
// 技術的な質問は技術サポートエージェントに転送
condition: (message) => message.text.includes("technical") ||
message.text.includes("error") ||
message.text.includes("problem"),
target: "techSupport"
},
{
// 購入や価格に関する質問は営業エージェントに転送
condition: (message) => message.text.includes("purchase") ||
message.text.includes("price") ||
message.text.includes("subscription"),
target: "sales"
}
]
}
});
// ネットワークの使用例
const response = await customerServiceNetwork.generate({
messages: [
{ role: "user", content: "製品の価格を教えてください" }
]
});
// → 自動的に営業エージェントに転送され、回答が生成される
ロギングとトレーシング
MastraはOpenTelemetryと統合されており、AIアプリケーションの実行状況を詳細に追跡できます。これにより、問題の特定、パフォーマンスの改善、デバッグが容易になります。
ユースケース例:
- エラーの特定と修正
- パフォーマンスボトルネックの特定
- ユーザー行動の分析
サポートされている観測性プロバイダー:
- Signoz
- Braintrust
- Langsmith
- Langfuse
- Langwatch
コード例:
import { createLogger } from "@mastra/core/observability";
import { braintrust } from "@mastra/core/observability/providers";
// ロガーの作成
export const logger = createLogger({
providers: [
braintrust({
apiKey: process.env.BRAINTRUST_API_KEY,
projectId: "my-ai-project",
}),
],
});
// AIエージェントでのロギング
export const myAgent = new Agent({
// エージェント設定
logger, // ロガーを設定
});
// 手動でのログ記録
logger.info("ユーザーリクエスト受信", { userId: "123", query: "天気について教えて" });
logger.debug("コンテキスト情報", { retrievedDocs: [...] });
フレームワーク統合
Next.js、React、Node.jsなどの既存のプロジェクトに簡単に組み込むことができます。特にNext.jsとの統合が強力で、APIルートとクライアントコンポーネントを使用したAIアプリケーションの構築が容易です。
ユースケース例:
- Webアプリケーションにチャットボットを追加
- 既存のCMSにコンテンツ生成機能を追加
- バックエンドAPIにAI機能を追加
Next.jsとの統合例:
import { weatherAgent } from "@/mastra/agents/weather";
import { NextRequest } from "next/server";
export async function POST(req: NextRequest) {
const { messages } = await req.json();
// エージェントを使用して応答を生成
const response = await weatherAgent.generate({
messages,
});
return Response.json(response);
}
"use client";
import { useState } from "react";
import { Message } from "@mastra/client-js";
export default function ChatPage() {
const [messages, setMessages] = useState<Message[]>([]);
const [input, setInput] = useState("");
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
// ユーザーメッセージを追加
const userMessage = { role: "user", content: input };
setMessages([...messages, userMessage]);
setInput("");
// AIからの応答を取得
const response = await fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ messages: [...messages, userMessage] }),
});
const data = await response.json();
// AIの応答を追加
setMessages((prev) => [...prev, data]);
};
return (
<div className="container mx-auto max-w-2xl p-4">
<div className="bg-gray-100 rounded p-4 h-96 overflow-auto mb-4">
{messages.map((msg, i) => (
<div key={i} className={`mb-2 ${msg.role === "user" ? "text-blue-600" : "text-green-600"}`}>
<strong>{msg.role === "user" ? "You:" : "AI:"}</strong> {msg.content}
</div>
))}
</div>
<form onSubmit={handleSubmit} className="flex">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
className="flex-1 border border-gray-300 rounded-l p-2"
placeholder="Message..."
/>
<button
type="submit"
className="bg-blue-500 text-white p-2 rounded-r"
>
Send
</button>
</form>
</div>
);
}
Mastraサーバー
Mastraサーバーは、AIエージェント、ワークフロー、RAG機能などをホストするためのバックエンドサービスで、Mastraアプリケーションの中核となる部分です。Honoフレームワークをベースにしており、APIエンドポイントを提供します。
Mastraサーバーの主な特徴:
- API提供: エージェント、ワークフロー、メモリなどのAPIエンドポイントを提供
- バックエンド処理: LLM呼び出し、ベクター検索、メモリ管理などの重い処理を担当
- スケーラビリティ: 水平スケーリングが可能な設計
- 安全性: APIキー管理、認証、認可機能の提供
- オブザーバビリティ: ロギング、トレーシング、メトリクス収集の統合
サーバーのセットアップと実行
import { createServer } from "@mastra/server";
import { weatherAgent } from "../agents/weather";
import { contentCreationWorkflow } from "../workflows/content-creation";
import { postgresql } from "@mastra/core/storage";
// サーバーの設定と作成
const server = createServer({
// 公開するエージェント
agents: {
weather: weatherAgent,
},
// 公開するワークフロー
workflows: {
contentCreation: contentCreationWorkflow,
},
// ストレージ設定
storage: postgresql({
connectionString: process.env.DATABASE_URL,
}),
// CORS設定
cors: {
origin: ["https://example.com", "http://localhost:3000"],
methods: ["GET", "POST"],
},
// 認証設定
auth: {
apiKey: {
header: "X-API-Key",
keys: [process.env.API_KEY],
},
},
// ロギング設定
logging: {
level: "info",
format: "json",
level: "info",
format: "json",
},
});
// サーバーの起動
server.listen({
port: process.env.PORT || 3000,
}, (err) => {
if (err) {
console.error("Failed to start server:", err);
process.exit(1);
}
console.log(`Server is running on port ${process.env.PORT || 3000}`);
});
サーバーのルート構成
Mastraサーバーは自動的に以下のようなAPIエンドポイントを提供します:
/agents/:agentId/generate # テキスト生成(非ストリーミング)
/agents/:agentId/stream # テキスト生成(ストリーミング)
/workflows/:workflowId/start # ワークフロー開始
/workflows/:workflowId/status # ワークフロー状態確認
/memory/threads # スレッド作成・取得
/memory/threads/:threadId # 特定スレッド操作
/rag/search # ベクターストア検索
/health # ヘルスチェック
MCP (Mastra Control Plane) ドキュメントサーバー
Mastraには専用のドキュメント管理サーバー(MCP)も含まれており、APIドキュメントの生成、エージェントとの対話テスト、ワークフローのモニタリングなどの機能を提供します。
import { createMCPServer } from "@mastra/mcp";
import { agents } from "./agents";
import { workflows } from "./workflows";
// MCPサーバーの作成
const mcpServer = createMCPServer({
agents,
workflows,
apiDocs: {
title: "My AI API Documentation",
description: "APIドキュメントとテストコンソール",
version: "1.0.0",
},
playground: {
enabled: true, // プレイグラウンドの有効化
},
monitoring: {
enabled: true, // モニタリングの有効化
},
});
// MCPサーバーの起動
mcpServer.listen({
port: process.env.MCP_PORT || 3001,
});
MCPサーバーは開発環境でのテストやデバッグに役立つだけでなく、内部開発者ポータルとしても利用でき、チーム内でのAPI利用を促進します。
このようにMastraサーバーコンポーネントは、AIアプリケーションのバックエンドインフラを提供し、フロントエンドとの連携を容易にします。
クライアントSDK(JavaScript/TypeScript)
Mastraはサーバーサイド機能だけでなく、ブラウザやクライアントアプリケーションで使用できるクライアントSDKも提供しています。これにより、フロントエンドから直接Mastraのエージェント、メモリ、ワークフローなどにアクセスできます。
クライアントSDKの主な機能:
- エージェント操作: クライアント側からエージェントとの対話を管理
- メモリアクセス: 会話履歴や状態の取得・保存
- ツール連携: クライアント側で使用可能なツールの提供
- ワークフロー実行: フロントエンドからワークフローを開始・監視
- ベクターストア操作: クライアント側からベクターデータへのアクセス
- ロギング: クライアント側のイベント記録
- テレメトリ: ユーザー操作の追跡
- エラーハンドリング: クライアント側でのエラー処理
コード例(React/Next.jsでの使用):
"use client";
import { useState } from "react";
import { MastraClient } from "@mastra/client-js";
import { StreamingText } from "@mastra/client-js/react";
// クライアントの初期化
const mastraClient = new MastraClient({
baseUrl: "/api/mastra", // APIエンドポイント
});
export function ChatInterface() {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState("");
const [isStreaming, setIsStreaming] = useState(false);
// エージェントとの対話を処理
const handleSubmit = async (e) => {
e.preventDefault();
if (!input.trim()) return;
// ユーザーメッセージを追加
const newUserMessage = { role: "user", content: input };
const updatedMessages = [...messages, newUserMessage];
setMessages(updatedMessages);
setInput("");
setIsStreaming(true);
try {
// エージェントからのストリーミングレスポンスを取得
const { stream } = await mastraClient.agents.stream({
agentId: "customer-support",
messages: updatedMessages,
});
// 最終的な応答が完了したら状態を更新
stream.onComplete((completeResponse) => {
setMessages([...updatedMessages, completeResponse]);
setIsStreaming(false);
});
} catch (error) {
console.error("Chat error:", error);
setIsStreaming(false);
}
};
return (
<div className="chat-container">
<div className="messages-container">
{messages.map((msg, i) => (
<div key={i} className={`message ${msg.role}`}>
{msg.content}
</div>
))}
{isStreaming && (
<div className="message assistant">
<StreamingText
stream={stream}
loadingText="思考中..."
/>
</div>
)}
</div>
<form onSubmit={handleSubmit} className="input-form">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="メッセージを入力..."
disabled={isStreaming}
/>
<button type="submit" disabled={isStreaming}>
送信
</button>
</form>
</div>
);
}
クライアントSDKを使用することで、バックエンドとフロントエンドの間でシームレスなAI機能の統合が可能になります。また、ストリーミングレスポンスのサポートにより、LLMの応答をリアルタイムでユーザーに表示できます。
まとめ
本記事では、話題のMastraがどのような機能を持ち、どんなことができるのかをざっくりと紹介しました。
実際に触ってみると、エージェントの作成やワークフローの定義、RAGのセットアップなどが思いのほか直感的に書けるので、すぐにプロトタイプを動かせるのがMastraの強みだと感じました。
次回は実際に何か簡単なものを開発してみようかと思います。
Discussion