Contents
1. Mastra の概要と基本アーキテクチャ
このセクションでは、Mastra が提供する主要コンポーネントとそれらがどのように連携して「メッセージ → 応答」のフローを実現するかを概観します。全体像を把握すれば、後続の実装作業で「どこにコードを書けばよいか」が自然に見えてきます。
1‑1. コアコンポーネント
Mastra の核は以下の4つです。各コンポーネントはインタフェースとして定義されており、ユーザー側で自由に実装を差し替えることができます(DI コンテナ対応)。
| コンポーネント | 役割 | 主なインターフェイス |
|---|---|---|
| Agent | LLM と対話するエントリーポイント。handleMessage() が外部から呼び出され、Tool・Memory・Router を協調させる。 |
Agent.handleMessage(msg: Message): Promise<string> |
| Tool | 外部サービス(GitHub API、データベース、社内システム等)への橋渡しを行うプラグイン。 | Tool.run(action: string, params: any): Promise<any> |
| Memory | 会話履歴や取得したデータを永続化/キャッシュする層。標準実装はインメモリ、Redis・DynamoDB などへの切り替えが可能。 | Memory.set(key:string, value:any), Memory.get(key:string) |
| Router | ユーザーの意図を解析し、適切な Tool またはサブエージェントへディスパッチする。 | Router.route(msg: Message): Promise<RouteResult> |
公式ドキュメント(README)でも同様の構成が示されています。
1‑2. データフローの流れ
- クライアント が HTTP POST/WebSocket 等で
Messageを送信 - Agent.handleMessage が呼び出され、メッセージを
Router.routeに委譲 - Router は意図判定結果(例:
{tool:"GitHubTool", action:"listFiles"})を返す - Tool.run が外部 API を叩き、取得データを Memory に保存
- 最終的に LLM へプロンプトを組み立て、生成されたテキストをクライアントへ返却
このシーケンスはすべて非同期(Promise)で処理されるため、スケールアウトやサーバーレス環境でも問題なく動作します。
2. 開発前提条件と安全な環境構築
本章では、Mastra 開発に最低限必要なツールチェーンと、セキュリティ上重要となるシークレット管理のベストプラクティスを紹介します。手順通りに実行すれば「動かない」状態に陥りにくい環境が整います。
2‑1. 推奨ランタイムとパッケージマネージャ
| ツール | 最低バージョン | インストール方法(MacOS / Linux) |
|---|---|---|
| Node.js | v20.x (LTS) | curl -fsSL https://nodejs.org/dist/v20.x/node-v20.x-linux-x64.tar.gz \| tar -xz && sudo mv node-v20.x-linux-x64 /usr/local/ |
| npm | 10.x 以上 | Node に同梱されているので別途インストール不要 |
| Git | 2.40 以上 | sudo apt-get install git(Ubuntu) |
インストール後は必ずバージョン確認:
|
1 2 3 4 |
node -v # → v20.x.x npm -v # → 10.x.x git --version # → git version 2.40.x |
2‑2. LLM API キーの取得と .env 管理
Mastra は OpenAI と Anthropic(Claude) の両方に対応しています。取得したシークレットは決してリポジトリにコミットしないよう、.gitignore に必ず追記してください。
|
1 2 3 4 |
# .env (プロジェクトルートに配置) OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxx ANTHROPIC_API_KEY=claude-xxxxxxxxxxxxxxxxxxx |
取得手順(公式ページ)
| プラットフォーム | 取得 URL |
|---|---|
| OpenAI | https://platform.openai.com/account/api-keys |
| Anthropic (Claude) | https://console.anthropic.com/settings/keys |
2‑3. VSCode の開発補助設定
| 拡張機能 | 設定例(settings.json) |
|---|---|
| ESLint | "editor.codeActionsOnSave": { "source.fixAll.eslint": true }" |
| Prettier | "prettier.singleQuote": true, "prettier.trailingComma": "all" |
| GitLens | デフォルトで有効にしておくとコミット履歴が見やすい |
VSCode の設定は公式ドキュメント(VSCode Docs)を参照してください。
3. プロジェクトの作成とシンプルな質問応答エージェント
ここでは、Mastra CLI を用いたプロジェクト雛形生成から、最小構成の質問応答エージェント実装までをステップバイステップで示します。コードはコメント付きで解説し、初心者でも理解できるよう配慮しています。
3‑1. CLI インストールとテンプレート生成
|
1 2 3 4 5 6 7 8 9 10 |
# ① グローバルに CLI をインストール npm install -g @mastra/cli # ② プロジェクト雛形を作成(my-agent ディレクトリが生成される) mastra init my-agent # ③ 作業ディレクトリへ移動し依存関係をインストール cd my-agent npm ci # package-lock に基づくクリーンインストール |
src/agent.ts がエントリーポイントとして自動生成され、以下のような雛形コードが入っています。
3‑2. 質問応答エージェントの実装例
|
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 |
// src/agents/simpleQaAgent.ts import { Agent, Message } from "@mastra/core"; /** * SimpleQAAgent は受け取ったメッセージをそのまま LLM に投げ、 * 生成されたテキストを返すだけの最小エージェントです。 */ export class SimpleQAAgent extends Agent { /** * メインロジック * @param msg ユーザーから送信された Message オブジェクト * @returns LLM が生成した文字列(Promise) */ async handleMessage(msg: Message): Promise<string> { // 1. プロンプト組み立て const prompt = `以下の質問に日本語で答えてください。\n${msg.content}`; // 2. LLM 呼び出し(OpenAI の場合は this.llm が自動的にラップされる) const llmResponse = await this.llm.generate({ prompt }); // 3. 必要ならレスポンス整形 return llmResponse.text.trim(); } } |
続いて src/index.ts でエージェントを起動します。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
// src/index.ts import { SimpleQAAgent } from "./agents/simpleQaAgent"; import { startServer } from "@mastra/server"; async function main() { const agent = new SimpleQAAgent(); // ポート3000で HTTP サーバーを立ち上げ、/message エンドポイントが Agent に委譲されます await startServer(agent, { port: 3000 }); } main().catch(console.error); |
起動手順
|
1 2 3 |
npm run build # TypeScript をコンパイル(dist ディレクトリに出力) npm start # `node dist/index.js` が実行されます |
起動後は以下のようにリクエストできます。
|
1 2 3 4 |
curl -X POST http://localhost:3000/message \ -H "Content-Type: application/json" \ -d '{"content":"Mastra の特徴を教えて"}' |
3‑3. デバッグ時に役立つ設定
| 項目 | 推奨値 |
|---|---|
| ログレベル | MASTRA_LOG_LEVEL=debug を .env に追加 |
| ソースマップ | tsconfig.json の "sourceMap": true を有効化 |
| 再起動自動化 | nodemon で npm run dev スクリプトを作成(例:nodemon --watch src -e ts --exec "npm start") |
4. 実務レベルのサンプル ― GitHub リポジトリ解析エージェント
本章では、Tool, Memory, Router を組み合わせた実践的なサンプルを構築します。GitHub のコードベースを走査し、ファイル一覧や簡易分析結果を返すフローを通じて、Mastra が提供する拡張性と可観測性を体感してください。
4‑1. GitHubTool の実装手順
4‑1‑1. 必要パッケージのインストール
|
1 2 |
npm install @octokit/rest @types/node |
4‑1‑2. Tool インターフェイスに沿ったクラス定義
|
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 38 39 40 41 |
// src/tools/githubTool.ts import { Tool } from "@mastra/core"; import { Octokit } from "@octokit/rest"; /** * GitHub API ラッパー。現在は「ファイル一覧取得」アクションのみ実装。 */ export class GitHubTool implements Tool { private octokit: Octokit; constructor() { // 環境変数からトークンを取得(.env に必ず設定) const token = process.env.GITHUB_TOKEN; if (!token) throw new Error("GITHUB_TOKEN が設定されていません"); this.octokit = new Octokit({ auth: token }); } /** * action と params に応じた GitHub API 呼び出しを実行 */ async run(action: string, params: any): Promise<any> { switch (action) { case "listFiles": return this.listFiles(params.owner, params.repo, params.path); // 将来的に「コード解析」や「プルリクエスト取得」等を追加可能 default: throw new Error(`未対応のアクション: ${action}`); } } /** リポジトリ直下または指定パス配下のファイル名配列を返す */ private async listFiles(owner: string, repo: string, path = ""): Promise<string[]> { const response = await this.octokit.repos.getContent({ owner, repo, path }); // `data` は FileContent[] または Directory[] if (!Array.isArray(response.data)) return []; return (response.data as any[]) .filter(item => item.type === "file") .map(file => file.name); } } |
4‑1‑3. .env にトークンを追加
|
1 2 |
GITHUB_TOKEN=ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXX |
注意:GitHub のパーソナルアクセストークンは最小権限(
repo:read)に絞り、漏洩防止のため必ず.gitignoreに.envを記載してください。
4‑2. Memory の活用例
|
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 |
// src/agents/githubAnalyzerAgent.ts import { Agent, Message } from "@mastra/core"; export class GitHubAnalyzerAgent extends Agent { async handleMessage(msg: Message): Promise<string> { // ユーザーが「ファイル一覧」と言ったら Memory にキャッシュ const repoInfo = this.parseRepoInfo(msg.content); if (!repoInfo) return "リポジトリ情報が取得できませんでした。owner と repo を教えてください。"; // 1. 既にキャッシュがあれば再利用 const cacheKey = `${repoInfo.owner}/${repoInfo.repo}:files`; let fileList: string[] | null = await this.memory.get(cacheKey); if (!fileList) { // 2. Tool 経由で取得し、Memory に保存 const tool = this.tools.get("GitHubTool"); fileList = await tool.run("listFiles", repoInfo); await this.memory.set(cacheKey, fileList); } return `リポジトリ ${repoInfo.owner}/${repoInfo.repo} のファイル一覧(${fileList.length} 件):\n` + fileList.join(", "); } /** メッセージ文字列から owner と repo を抽出する簡易パーサ */ private parseRepoInfo(text: string): {owner:string, repo:string, path?:string} | null { const match = /github\.com\/([^/]+)\/([^/\s]+)/i.exec(text); if (!match) return null; return { owner: match[1], repo: match[2] }; } } |
4‑3. Router による意図判定とツール選択
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// src/router/repoRouter.ts import { Router, Message } from "@mastra/core"; export class RepoRouter extends Router { /** * メッセージの内容に応じて適切な Tool とアクションを決定します。 */ async route(msg: Message) { // 簡易的に「ファイル一覧」かどうかだけ判定 if (/ファイル一覧|list files/i.test(msg.content)) { return { toolName: "GitHubTool", action: "listFiles" }; } // それ以外はデフォルトのエージェントへ委譲 return super.route(msg); } } |
ポイント:現在の Mastra 本体には「ハイパーパーソナライズ」機能は実装されていません。将来的に属性ベースのルーティングが追加された場合は、
this.context.userにユーザー情報を格納し上記routeメソッドで分岐させる設計が推奨されています。
4‑4. 完全動作サンプルのディレクトリ構成
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
my-agent/ ├─ src/ │ ├─ agents/ │ │ └─ githubAnalyzerAgent.ts │ ├─ tools/ │ │ └─ githubTool.ts │ ├─ router/ │ │ └─ repoRouter.ts │ └─ index.ts ├─ .env ← API キー・トークンを記載 ├─ package.json └─ tsconfig.json |
この構成で npm run build && npm start を実行すると、POST /message に以下のような JSON を送るだけでリポジトリ解析が可能です。
|
1 2 3 4 |
{ "content": "https://github.com/mastra-ai/mastra のファイル一覧を教えて" } |
5. テスト・デバッグ・本番デプロイ、そしてコミュニティ参加
実務での信頼性確保とスケーラビリティを考慮し、テスト戦略、ロギングベストプラクティス、主要クラウドへのデプロイ手順をまとめます。
5‑1. ユニットテストとモック
Mastra 用に提供されている @mastra/test-utils パッケージは、Tool の内部 API(例:Octokit)や Memory の永続化処理を簡単にスタブできます。
|
1 2 |
npm install -D jest @types/jest @mastra/test-utils ts-jest |
5‑1‑1. Jest 設定 (jest.config.js)
|
1 2 3 4 5 6 7 8 |
module.exports = { preset: "ts-jest", testEnvironment: "node", moduleNameMapper: { "^@mastra/(.*)$": "<rootDir>/node_modules/@mastra/$1" }, }; |
5‑1‑2. テスト例(GitHubTool のモック)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// tests/githubTool.test.ts import { GitHubTool } from "../src/tools/githubTool"; import { mockOctokit } from "@mastra/test-utils"; describe("GitHubTool", () => { const tool = new GitHubTool(); beforeAll(() => { // Octokit のレスポンスを固定値で置き換える mockOctokit(tool["octokit"], [ { name: "README.md", type: "file" }, { name: "src/index.ts", type: "file" } ]); }); test("listFiles returns file names", async () => { const files = await tool.run("listFiles", { owner: "test", repo: "demo" }); expect(files).toEqual(["README.md", "src/index.ts"]); }); }); |
テスト実行は npm test。
5‑2. Structured Logging の推奨フォーマット
| フィールド | 説明 |
|---|---|
timestamp |
ISO8601 形式(例:2026-06-27T12:34:56.789Z) |
level |
debug, info, warn, error |
requestId |
各リクエストに付与する UUID |
component |
Agent, Tool:GithHubTool など |
message |
ログ本文(JSON の文字列化は不要) |
実装例
|
1 2 3 4 5 6 7 8 9 10 |
import { Logger } from "@mastra/logger"; const logger = new Logger({ level: process.env.MASTRA_LOG_LEVEL || "info" }); logger.info("GitHubTool:listFiles called", { requestId, owner, repo, }); |
JSON 出力は CloudWatch Logs、Elastic Stack、Datadog 等の外部可観測性プラットフォームでそのまま活用できます。
5‑3. デプロイ先別手順
| 環境 | 手順概要 |
|---|---|
| Vercel | npm i -g vercel → プロジェクトルートで vercel --prod。環境変数は Vercel ダッシュボードの「Environment Variables」へ登録。 |
| Cloudflare Workers (Wrangler v3) | npm i -D wrangler → npx wrangler login → wrangler.toml に type = "javascript" とエントリーポイント (src/index.ts) を記述し、npx wrangler publish。 |
| Docker | Dockerfile(下記参照)でイメージ化し、Kubernetes の Deployment もしくは ECS/Fargate にデプロイ。 |
Dockerfile 完全例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# ビルドステージ FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY tsconfig.json . COPY src ./src RUN npx tsc # TypeScript をコンパイルして dist ディレクトリへ # 実行ステージ(軽量イメージ) FROM node:20-alpine WORKDIR /app COPY --from=builder /app/dist ./dist COPY package*.json ./ RUN npm ci --production # 本番依存だけインストール CMD ["node", "dist/index.js"] |
5‑4. コミュニティと情報入手先
| 項目 | URL |
|---|---|
| GitHub リポジトリ(コード・Issue) | https://github.com/mastra-ai/mastra |
| ドキュメント(GitHub Pages) | https://mastra-ai.github.io/docs/ |
| Discord コミュニティ | 招待リンクはリポジトリの README.md に掲載 |
| GitHub Discussions(質問・提案) | 同上 |
定期的に Release Note と Roadmap が公開されるので、機能追加や非推奨情報を見逃さないようにしましょう。
まとめ
- Mastra は TypeScript 製オープンソースフレームワークで、Agent・Tool・Memory・Router の四大コンポーネントが標準装備されている点が特徴です。
- 必要なランタイムは Node.js v20 以上、シークレットは
.envに安全に格納し、VSCode と ESLint/Prettier の設定で開発体験を向上させます。 mastra-cli initで作ったテンプレートに SimpleQAAgent を実装すれば、数分で動く質問応答エージェントが完成します。- 実務的なサンプルとして GitHub リポジトリ解析エージェントを構築し、Tool の拡張・Memory のキャッシュ・Router の意図判定を体感できます。
- テストは Jest と
@mastra/test-utilsでモック化し、structured logging によって本番環境でも可観測性を確保。Docker、Vercel、Cloudflare Workers へのデプロイ手順も揃っています。 - 最後に公式リポジトリ・Discord・Discussions を活用し、最新情報とコミュニティサポートを受け取りながら開発を進めてください。
これらのステップを踏むことで、初心者でも安全かつスケーラブルな AI エージェントをゼロから構築し、本番環境へデプロイできるようになります。ぜひ実際に手を動かして、Mastra の可能性を体感してください。