Contents
MastraでAIエージェントを構築する前に
TypeScript開発者がMastraを選択する背景と本記事の目的を説明。LLM連携型AIエージェントの概要を簡潔に提示
AIエージェントの構築は、従来Pythonベースのフレームワークが主流でしたが、TypeScript環境特化型のMastraはWeb開発者のスキルセットと統合しやすい点で注目されています。本記事では、Node.js環境でのセットアップからLLM連携、Vercel/Next.jsとの連携まで、TypeScriptエンジニアが実装時に必要とする知識を体系的に解説します。
Node.js環境でのMastraセットアップ
npmで導入する手順とTypeScriptプロジェクトのテンプレート作成方法。ESLintやTypeScriptコンパイラ設定を含む
Node.js環境にMastraを導入するには、まずプロジェクト初期化と依存関係のインストールが必須です。以下に基本的な手順を示します。
依存関係のインストール
- 新規プロジェクトディレクトリを作成し、
npm init -yでパッケージ構成ファイルを作成 npm install --save-dev mastraでMastra本体を導入- TypeScript環境用に
@types/nodeやtscもインストール
プロジェクト構成の基本設計では、以下のようなディレクトリ構造が推奨されます。
|
1 2 3 4 5 6 7 |
├── src/ # ソースコード │ ├── agents/ # エージェント実装ファイル │ ├── config/ # 設定ファイル(LLMのAPIキーなど) │ └── index.ts # メインエントリーポイント ├── tsconfig.json # TypeScript設定ファイル └── .eslintrc.js # ESLint設定ファイル |
ESLintやTypeScriptコンパイラ(tsc)の設定は、初期化時にmastra initコマンドを実行することで自動生成できます。この時点でTypeScriptの型チェックとESLintのルール適用が可能になります。
LLMとのインタフェース構築
OpenAI APIとMastraの連携方法。TypeScriptで定義するリクエスト・レスポンスインターフェースの重要性
LLMとの連携には、プロキシサーバーを介してAPI通信を行う方式が一般的です。以下に実装例を示します。
プロキシサーバーの実装例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// src/proxy.ts import { Agent } from 'mastra'; const agent = new Agent({ llm: { type: 'openai', apiKey: process.env.OPENAI_API_KEY, model: 'gpt-4-turbo' } }); export async function handleLLMRequest(input: string): Promise<string> { try { return await agent.run(input); } catch (error) { console.error('LLM通信エラー:', error); throw new Error('LLM処理に失敗しました'); } } |
型安全なAPIクライアント設計
TypeScriptでは、リクエストとレスポンスのインターフェースを明示的に定義することで型安全性を確保できます。以下に例を示します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// src/types.ts interface LLMRequest { prompt: string; temperature?: number; } interface LLMResponse { content: string; usage: { tokens: number; }; } |
このようにインターフェースを定義することで、API通信時の誤りをコンパイラレベルで検出でき、デバッグ効率が向上します。
状態管理とタスクスケジューリング
エージェント間通信の流れと、TypeScriptで実現する非同期処理のベストプラクティス
AIエージェントは複数のタスクを並行して処理することが多く、状態管理やタイムアウト処理が重要です。
データフロー設計のポイント
- エージェント間で共有するグローバルなステート管理にはRedisやIn-memory cacheを使用
- 非同期処理は
async/awaitとPromise.all()で実装し、タスク依存関係を明確化
タイムアウト処理の実装
非同期処理中にエラーが発生した場合、タイムアウトを設定してエージェントの停止を防ぎます。以下に実装例を示します。
|
1 2 3 4 5 6 7 8 9 10 11 |
import { setTimeout } from 'timers/promises'; async function withTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T> { const timeout = setTimeout(timeoutMs); try { return await Promise.race([promise, timeout]); } finally { clearTimeout(timeout); } } |
このようにして、エージェントの信頼性とスケーラビリティを確保できます。
Vercel/Next.jsとの連携方法
Next.jsアプリケーション内でのMastraエージェントの統合。SSGとSSR時の処理フロー
VercelやNext.js環境でMastraを使用するには、Server Components(SC)やAPIルート経由で統合します。
Server Componentsでの導入
Next.js 13以降では、Server Componentsを使うことでクライアントサイドにLLM処理を配置せずに実装可能です。
|
1 2 3 4 5 6 7 8 9 |
// app/page.tsx import { Agent } from 'mastra'; export default async function Home() { const agent = new Agent({ /* ... */ }); const result = await agent.run('質問内容'); return <div>{result}</div>; } |
APIルートの設計
SSG(Static Site Generation)とSSR(Server Side Rendering)に対応するAPIルートを以下のように作成します。
|
1 2 3 4 5 6 7 8 9 |
// app/api/agent/route.ts import { Agent } from 'mastra'; export async function POST(req: Request) { const agent = new Agent({ /* ... */ }); const input = await req.json(); return Response.json(await agent.run(input.prompt)); } |
このようにすることで、Next.jsのSSG/SSR機能と連携し、高速なレンダリングが可能になります。
TypeScript型定義の活用術
エージェント仕様書から導き出す型設計と、ユニットテストでの型安全性確保方法
TypeScriptの強みは型を正確に定義してデバッグ効率を高めることです。以下に実装例を示します。
カスタムタイプの設計方針
エージェント仕様書から導き出すカスタムタイプは、以下のように定義します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// src/types.ts interface AgentSpec { id: string; name: string; tasks: Task[]; } interface Task { id: number; title: string; status: 'pending' | 'running' | 'completed'; } |
動作検証に必要な型チェック
ユニットテストでは、expectTypeOfなどで型が正しいかを確認できます。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
import { expectTypeOf } from '@sinonjs/expect-type'; const agentSpec: AgentSpec = { id: 'a1', name: 'SampleAgent', tasks: [ { id: 1, title: 'Task 1', status: 'pending' } ] }; expectTypeOf(agentSpec).toMatchTypeOf<AgentSpec>(); |
このようなチェックを実施することで、型の誤りや不一致に早期に気づけるようになります。