Contents
1. 開発環境の準備
1‑1. Node.js とパッケージマネージャの要件
ローカルで Mastra を快適に動かすには、Node.js 18 系以上と npm 9 系以上(または yarn) が推奨されます。古いランタイムでは ESモジュールや最新の JavaScript 機能がサポートされず、ビルドエラーが頻発することがあります。
|
1 2 3 4 5 |
# バージョン確認(必ず公式サイトで推奨バージョンと照合してください) node -v # 例: v18.17.0 npm -v # 例: 9.8.1 yarn -v # yarn を使う場合にのみ実行 |
⚠️ 注意
公式ドキュメントで「Node.js 20」や「npm 10」への対応が開始された場合は、上記コマンドの結果がそれらを満たすか必ず確認してください。
古いバージョンの場合は、Node.js の公式サイトから LTS バージョンをダウンロードしてインストールしましょう。
1‑2. TypeScript 設定の基本
Mastra プロジェクトは TypeScript が必須です。tsconfig.json に最低限必要な設定例と、各オプションが果たす役割を解説します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
{ "compilerOptions": { "target": "ES2022", // Node がサポートする最新構文を利用 "module": "ESNext", // ES モジュール方式でインポート/エクスポート "moduleResolution": "Node16", // Node.js 16+ のモジュール解決ロジックに合わせる "strict": true, // 厳格な型チェックでバグを早期検出 "esModuleInterop": true, // CommonJS と ES モジュールの相互運用性確保 "skipLibCheck": true, // ライブラリ型定義のチェックスキップ(ビルド高速化) "forceConsistentCasingInFileNames": true, "outDir": "./dist" // ビルド成果物の出力先 }, "include": ["src/**/*.ts"], "exclude": ["node_modules"] } |
targetとmodule:最新 Node が扱える構文に合わせることで、トランスパイル時の余計なポリフィルを回避できます。strict:型安全が保証されるだけでなく、IDE の補完やリファクタリングが正確になります。
このファイルをプロジェクト直下に置いたら、以下コマンドでビルドできることを確認しましょう。
|
1 2 |
npm run build # または yarn build |
2. Mastra CLI の取得とプロジェクト雛形作成
2‑1. 最新 CLI を取得する安全な手順
Mastra のテンプレート生成は create-mastra コマンドで行います。公式では npx create-mastra@latest <project-name> が推奨されていますが、実際に使用できるかはリポジトリの公開状態を確認してください。
|
1 2 3 |
# プロジェクト名「my-agent」で雛形ディレクトリを作成 npx create-mastra@latest my-agent |
npxは一時的に最新パッケージを取得するため、グローバルインストールの必要がありません。- 実行後は プロンプトで依存関係のインストール確認 が表示されるので、そのまま続行してください。
⚠️ 注意
CLI のバージョンやオプションは公式リリースノートに従ってください。この記事に記載したコマンドは執筆時点の情報です。
2‑2. CLI バージョンの確認とアップデート方法
プロジェクトディレクトリに移動し、以下でバージョンを取得します。
|
1 2 3 |
cd my-agent npx mastra --version # => 例: 2.3.1 |
新しいリリースが出た場合は、再度 create-mastra@latest を実行するか、ローカルで CLI パッケージを更新します。
|
1 2 |
npm install mastra-cli@latest --save-dev # devDependency として最新バージョンを取得 |
補足:上記コマンドは
mastra-cliが npm に公開されていることが前提です。公式ドキュメントでパッケージ名が変わっていないか必ず確認してください。
2‑3. 生成されたプロジェクト構造の概要
create-mastra が作成するディレクトリは次のようになっています(実際の構成はバージョンにより若干異なる場合があります)。
|
1 2 3 4 5 6 7 8 9 10 |
my-agent/ ├─ src/ │ ├─ agent.ts # エージェント本体 │ ├─ tools/ # 外部 API ラッパー等を格納 │ └─ studio/ # Mastra Studio 用フロントエンド資産 ├─ .env.example # 環境変数サンプル(必ず .gitignore に追加) ├─ tsconfig.json ├─ package.json └─ mastra.config.ts # CLI 設定やプラグイン情報 |
src/agent.ts:プロンプトと LLM プロバイダーを組み合わせたコアロジック。tools/:GitHub API など、外部サービスへのアクセスコードを配置します。
⚠️ 注意:本稿で示すファイルパスや名前は 公式テンプレートの最新版 に合わせてください。
3. 安全な環境変数とシークレット管理
3‑1. .env の扱い方(ベストプラクティス)
| 項目 | 推奨設定 |
|---|---|
| ファイル名 | .env(本番では使用しない) |
| バックアップ | Git 管理外(.gitignore に必ず追加) |
| 本番環境 | CI/CD のシークレットストア(GitHub Actions Secrets、Vercel Secrets など)へ移行 |
|
1 2 3 4 5 6 |
# .env.example(実際のキーはここに書かない) OPENAI_API_KEY=your-openai-key ANTHROPIC_API_KEY=your-anthropic-key PINECONE_API_KEY=your-pinecone-key GITHUB_TOKEN=your-github-token |
セキュリティ上のポイント
-.envは絶対にリポジトリにコミットしない。
- 本番環境では 暗号化されたシークレット を使用し、コード中で直接参照しないようにする(例:process.env.OPENAI_API_KEY)。
3‑2. 環境変数のロードと型安全
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// src/config.ts import * as dotenv from 'dotenv'; dotenv.config(); // .env を自動的に読み込む export const CONFIG = { openAiKey: process.env.OPENAI_API_KEY ?? '', anthropicKey: process.env.ANTHROPIC_API_KEY ?? '', pineconeKey: process.env.PINECONE_API_KEY ?? '', githubToken: process.env.GITHUB_TOKEN ?? '' } as const; // 必要に応じてランタイムで欠損チェック for (const [k, v] of Object.entries(CONFIG)) { if (!v) { throw new Error(`環境変数 ${k} が設定されていません`); } } |
dotenvは 依存関係として明示的にインストールしてください(CLI が自動で入れる保証はありません)。
|
1 2 |
npm i -D dotenv # devDependency に追加 |
4. エージェント本体の実装
4‑1. プロンプトテンプレートとマルチLLM の切り替えロジック
まず、共通プロンプトを PromptTemplate で定義します。プレースホルダーは後述の RAG 結果やユーザー入力が埋め込まれます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// src/agent.ts import { Agent, PromptTemplate } from 'mastra'; import { OpenAIProvider, AnthropicProvider } from 'mastra/providers'; import { CONFIG } from './config'; const basePrompt = new PromptTemplate(` You are an AI assistant that helps developers understand code. Context: {{retrievedDocs}} Question: {{userInput}} Provide a concise answer in Japanese. `); export const myAgent = new Agent({ name: 'CodeInsight', // LLM プロバイダーは実行時にコンテキストで切り替える provider: async (ctx) => { return ctx.useAnthropic ? new AnthropicProvider({ apiKey: CONFIG.anthropicKey }) : new OpenAIProvider({ apiKey: CONFIG.openAiKey }); }, prompt: basePrompt, }); |
providerは非同期関数で、実行時のフラグuseAnthropicに応じてインスタンスを生成します。- 型安全と テスト容易性 のためにプロバイダー取得ロジックは別ファイルに切り出すことも推奨します。
4‑2. RAG(Retrieval‑Augmented Generation)実装例
以下では GitHub リポジトリの README を取得し、Pinecone にベクトル埋め込み・検索するフローを示します。依存パッケージは手動でインストールしてください。
|
1 2 |
npm i node-fetch @pinecone-database/pinecone # 必要なライブラリ |
4‑2‑1. GitHub README の取得
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// src/tools/github.ts import fetch from 'node-fetch'; import { CONFIG } from '../config'; export async function fetchRepoReadme(owner: string, repo: string): Promise<string> { const res = await fetch(`https://api.github.com/repos/${owner}/${repo}/readme`, { headers: { Authorization: `token ${CONFIG.githubToken}` } }); if (!res.ok) { throw new Error(`GitHub API error: ${res.status}`); } const data = await res.json(); // README は Base64 エンコードされている return Buffer.from(data.content, 'base64').toString('utf-8'); } |
4‑2‑2. Pinecone へのベクトル登録・検索
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
// src/tools/rag.ts import { PineconeClient } from '@pinecone-database/pinecone'; import { OpenAIEmbeddings } from 'mastra/embeddings'; import { CONFIG } from '../config'; const pinecone = new PineconeClient(); await pinecone.init({ environment: 'us-west1-gcp', apiKey: CONFIG.pineconeKey }); const index = pinecone.Index('mastra-demo'); export async function upsertDocument(id: string, text: string) { const embedder = new OpenAIEmbeddings({ apiKey: CONFIG.openAiKey }); const vector = await embedder.embed(text); await index.upsert({ upsertRequest: { vectors: [{ id, values: vector, metadata: { text } }] } }); } export async function queryDocuments(query: string, topK = 3): Promise<string[]> { const embedder = new OpenAIEmbeddings({ apiKey: CONFIG.openAiKey }); const qVector = await embedder.embed(query); const result = await index.query({ queryRequest: { vector: qVector, topK, includeMetadata: true } }); return result.matches.map(m => m.metadata?.text ?? ''); } |
4‑2‑3. エージェント呼び出し側で RAG を組み込む
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// src/index.ts import { myAgent } from './agent'; import { fetchRepoReadme } from './tools/github'; import { upsertDocument, queryDocuments } from './tools/rag'; async function ingestSample() { const readme = await fetchRepoReadme('vercel', 'next.js'); await upsertDocument('next-readme', readme); } async function answerWithRAG(question: string, useAnthropic = false) { // 1. 関連ドキュメント取得 const docs = await queryDocuments(question); // 2. エージェントに問い合わせ const response = await myAgent.invoke({ userInput: question, retrievedDocs: docs.join('\n---\n'), // プロンプトへ埋め込む形式 useAnthropic // フラグで LLM 切替 }); console.log(response); } // 実行例 await ingestSample(); await answerWithRAG('Next.js のデータフェッチはどう実装すればいい?'); |
ポイント
-upsertDocumentとqueryDocumentsは 非同期で実行され、エラーは呼び出し側でハンドリングしてください。
- ベクトル検索の結果数(topK)はユースケースに合わせて調整可能です。
5. 開発・テストフローと Mastra Studio の活用
5‑1. Mastra Studio ローカルサーバの起動
プロジェクト直下で次コマンドを実行すると、ブラウザ上にインタラクティブ UI が立ち上がります。
|
1 2 |
npm run studio # または yarn studio |
- デフォルトは
http://localhost:3000です。 - ソース変更時に自動で ホットリロード が走り、手動リフレッシュは不要です。
5‑2. UI からのデバッグ方法(導入文)
Studio の右側パネルには実行ログがリアルタイムで表示されます。以下項目を確認しながらデバッグすると効率的です。
| 項目 | 内容 |
|---|---|
| Request ID | 各呼び出しの一意識別子(トレースに便利) |
| Prompt | LLM に送信されたプロンプト全文 |
| Provider | 使用した LLM(OpenAI / Anthropic) |
| Response | 生成結果とトークン使用量 |
これらは Chrome DevTools のコンソールでも確認でき、console.log を埋め込んだコードの出力も同時に表示されます。
5‑3. Jest によるユニットテストとモック戦略(導入文)
外部 LLM 呼び出しはコストが高くなるため、モック化してロジックだけを検証します。以下は myAgent のテスト例です。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// src/__tests__/agent.test.ts import { myAgent } from '../agent'; import { OpenAIProvider } from 'mastra/providers'; // LLM プロバイダーのモック jest.mock('mastra/providers', () => ({ OpenAIProvider: jest.fn().mockImplementation(() => ({ invoke: jest.fn().mockResolvedValue('モック応答') })) })); test('OpenAI プロバイダーで質問すると期待通りのレスポンスが返る', async () => { const resp = await myAgent.invoke({ userInput: 'テスト質問' }); expect(resp).toBe('モック応答'); expect(OpenAIProvider).toHaveBeenCalled(); }); |
jest.mockによりネットワーク通信を完全に除外し、実行時間を数ミリ秒に短縮できます。- CI では
npm test -- --runInBandとしてシリアル実行すればリソース競合を防げます。
5‑4. ログ出力・モニタリングのベストプラクティス(導入文)
本番環境では 構造化ログ が不可欠です。Mastra の Agent は任意のロガーオブジェクトを受け取れるため、pino など高速ロガーと組み合わせます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import pino from 'pino'; const logger = pino({ level: process.env.NODE_ENV === 'production' ? 'info' : 'debug', transport: { target: 'pino-pretty', // 開発時は可読形式に変換 }, }); export const myAgent = new Agent({ name: 'CodeInsight', provider, // 前節で定義したものを流用 prompt: basePrompt, logger // カスタムロガーとして渡す }); |
- JSON 形式のログは CloudWatch、Datadog、Logstash 等への転送が容易です。
- エラー時は必ず
logger.error({ err, payload }, 'LLM 呼び出し失敗')としてスタックトレースを残すようにします。
5‑5. エラーハンドリングとリトライロジック(導入文)
LLM API は レートリミットや タイムアウト が頻発するため、指数バックオフでのリトライが推奨されます。axios-retry を利用した例を示します。
|
1 2 |
npm i axios axios-retry # 必要なパッケージを手動インストール |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import axios from 'axios'; import axiosRetry from 'axios-retry'; import { logger } from './logger'; const api = axios.create(); axiosRetry(api, { retries: 3, retryDelay: (retryCount) => 1000 * Math.pow(2, retryCount), // 1s → 2s → 4s retryCondition: (error) => error.code === 'ECONNABORTED' || // タイムアウト error.response?.status === 429 // レートリミット }); export async function safeInvoke(provider, payload) { try { return await provider.invoke(payload); } catch (err) { logger.error({ err, payload }, 'LLM 呼び出し失敗'); throw err; // 必要に応じて上位へ再スロー } } |
- 最大リトライ回数は 3 回が経験的にバランスが良いとされています。
axios-retryがインストールされているかは必ず確認し、package.jsonに明記してください。
6. 本番デプロイと既存システムへの統合
6‑1. npm パッケージとしてのエクスポート(導入文)
完成したエージェントを 社内・外部で再利用可能なパッケージ として公開します。package.json のエントリは次のように設定します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ "name": "@your-org/mastra-agent", "version": "1.0.0", "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { "build": "tsc", "prepare": "npm run build" }, "files": ["dist/"], "private": false, "publishConfig": { "access": "restricted" // 社内リポジトリの場合は restricted、公開なら public } } |
prepareスクリプトによりnpm publish前に自動でビルドが走ります。- 公開前に必ず 2FA と OTP の有効化を行い、認証情報の漏洩リスクを低減してください。
6‑2. GitHub Actions による CI/CD パイプライン(導入文)
以下はビルド・テスト・パッケージ公開までを自動化したサンプルです。シークレット管理は必ず GitHub Secrets 経由で行います。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# .github/workflows/ci.yml name: CI on: push: branches: [ main ] pull_request: jobs: build-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Node.js setup uses: actions/setup-node@v3 with: node-version: '20' # 公式が推奨するバージョンを使用 cache: npm - run: npm ci - run: npm test - run: npm run build publish: needs: build-test if: github.ref == 'refs/heads/main' && success() runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Node.js setup (publish) uses: actions/setup-node@v3 with: node-version: '20' registry-url: https://registry.npmjs.org/ - run: npm ci && npm publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} |
npm testが成功したらのみpublishジョブが実行されます。- 必要に応じて ステージング環境へのデプロイや Docker イメージのビルドを追加してください。
6‑3. Vercel へのデプロイ手順(導入文)
Vercel は Serverless Function としてエージェントエンドポイントを提供します。設定は次の通りです。
- GitHub リポジトリを Vercel にインポート
- Project Settings → Environment Variables で
.envのキー(例:OPENAI_API_KEY)を暗号化して登録 - デプロイコマンドは
npm run build && npm start(またはvercel dev)
ポイント
- Vercel の関数サイズ上限は 50 MB。不要な依存はdevDependenciesに分離し、ビルド時に除外してください。
6‑4. Cloudflare Workers へのデプロイ(導入文)
Workers は 1 MiB のバンドル制限があるため、コードサイズ最適化が必須です。
|
1 2 |
npm i -D wrangler esbuild # 開発ツールをインストール |
package.json にビルドスクリプトを追加します。
|
1 2 3 4 |
"scripts": { "build:worker": "esbuild src/worker.ts --bundle --minify --outfile=dist/worker.js" } |
wrangler.toml の例
|
1 2 3 4 5 6 7 |
name = "mastra-agent-worker" compatibility_date = "2024-01-01" [vars] OPENAI_API_KEY = "$OPENAI_API_KEY" PINECONE_API_KEY = "$PINECONE_API_KEY" |
ビルド後に wrangler publish でデプロイします。ベクトル検索は外部 API(Pinecone)へ委譲し、ローカルに大量データを保持しない設計がポイントです。
7. コミュニティと追加リソース
- 公式サンプル集:Mastra の GitHub 組織内
mastra-samplesリポジトリ(最新のマルチLLM・RAG 実装例が多数掲載) - Discord コミュニティ:
#mastra-devチャンネルで質問や情報交換が可能です。参加方法は公式サイトのフッターにある招待リンクからアクセスしてください(リンクは随時更新されます)。
※ ここに記載した外部リンクは執筆時点の情報です。実在確認が必要な場合は公式ページをご参照ください。
まとめ
- 環境構築:Node.js 18+・npm 9+、TypeScript の推奨設定を整える。
- CLI 入手:
npx create-mastra@latestで最新テンプレートを取得し、バージョンは公式ドキュメントで必ず確認。 - シークレット管理:
.envはローカル限定、実運用は CI/CD の暗号化シークレットへ移行。 - エージェント実装:マルチLLM 切替と RAG(GitHub → Pinecone)を組み合わせたサンプルコードを提示。依存パッケージは手動でインストールし、
package.jsonに明示的に記載。 - 開発フロー:Mastra Studio でホットリロード、Jest でモックテスト、pino と axios-retry によるロギング・リトライを実装。
- 本番デプロイ:npm パッケージ化 → GitHub Actions CI/CD → Vercel/Cloudflare Workers のいずれかにデプロイ。サイズ制限や環境変数の暗号化に注意。
- コミュニティ活用:公式サンプルと Discord で最新情報をキャッチアップ。
これらの手順に沿って開発すれば、Mastra が提供する マルチLLM と RAG の高度な組み合わせ を安全かつスケーラブルに実装でき、社内プロダクトや顧客向けサービスへ迅速に組み込むことが可能です。ぜひ本ガイドをリファレンスとして活用し、次世代 AI エージェント開発に挑戦してください。