MastraでAgentをCloudflareにデプロイしてみる

MastraでAgentをCloudflareにデプロイしてみる

Clock Icon2025.03.21

Introduction

Mastraは、TypeScriptでAIエージェントを開発できるフレームワークです。。
モデルのルーティング機能を持っていたりRAG対応していたり各種サーバレスサービスに対応していたり、
いろいろと機能があり、最近話題になってます。
本稿では、Mastraを使って簡単なAgentを作成し、Cloudflare Workersにデプロイしてみます。

Mastraの詳細な機能については、以下の記事を参照してください。

Environment

  • MacBook Pro (14-inch, M3, 2023)
  • OS : MacOS 14.5
  • bun : 1.2.5

Node.js v20.0以降がPrerequisitesとありますが、
Bunで動いたのでそれを使います。
また、Cloudflareのアカウントは取得済みとします。

Setup

Mastraはnpm/yarn/pnpmなど各種パッケージマネージャでインストールできます。
今回はBunでやりました。

% bun add --global mastra@latest

プロジェクトの作成はnpxでもmastra createでもよいです。

% mastra create
 or 
% npx create-mastra@latest

プロジェクト作成は対話形式で実施されます。(対話形式じゃなくてもOK)
LLMのキーもここで入力できれば入力してしまってもOK。
後で.envファイルに入力してもOKです。

┌  Mastra Create
│
◇  What do you want to name your project?
│  cloudflare-demo
│
◇  Project created
│
◇  npm dependencies installed
│
◇  mastra installed
│
◇  @mastra/core installed
│
◇  .gitignore added
│
└  Project created successfully
┌  Mastra Init
│
◇  Where should we create the Mastra files? (default: src/)
│  src/
│
◇  Choose components to install:
│  Agents
│
◇  Add tools?
│  Yes
│
◇  Select default provider:
│  OpenAI
│
◇  Enter your openai API key?
│  Enter API key
│
◇  Enter your API key:
│  [あなたのAPIキーを入力]
│
◇  Add example
│  No
│
◇  Make your AI IDE into a Mastra expert?
│  Skip for now

Try

では最初に、簡単なAgentを作成しましょう。
今回はGNewsのAPIをつかってニュースを取得するAgentを作成します。
ここから登録してAPIキーを取得して使います。

プロジェクト構造

ディレクトリ構成はこんな感じで作ります。

cloudflare-demo/
├── src/
│   ├── mastra/
│   │   ├── agents/
│   │   │   └── news.ts    # ニュースエージェントの実装
│   │   ├── tools/
│   │   │   └── news.ts    # ニュースAPIツールの実装
│   │   └── index.ts       # アプリケーションのエントリーポイント
│   └── client/
│       └── example.ts     # 使用例
├── package.json
└── tsconfig.json

主なコード解説

News Agent(src/mastra/agents/news.ts):

以下がAgentの定義です。
Agentの説明、使用モデル、使用ツールを設定します。

import { Agent } from '@mastra/core/agent';
import { openai } from '@ai-sdk/openai';
import { getTopNewsTool, searchNewsTool } from '../tools/news';

export const newsAgent = new Agent({
  name: 'News Assistant',
  instructions: `あなたはニュース記事を取得・検索するアシスタントです。
以下の機能を提供します:
1. トップニュースの取得
2. キーワードによるニュース検索

記事を表示する際は以下の点に注意してください:
- 記事のタイトル、説明、URLを明確に表示
- 重要な情報は簡潔に要約
- 複数の記事がある場合は、関連性の高い順に表示
- エラーが発生した場合は、適切なエラーメッセージを表示`,
  model: openai.chat('gpt-4'),
  tools: {
    getTopNews: getTopNewsTool,
    searchNews: searchNewsTool
  }
});

toolsで↓のtool定義を指定してます。

News Tools(src/mastra/tools/news.ts):

MastraのcreateToolとzodで定義したスキーマをつかってツールを作成します。
ここでは外部(GNews)から情報を取得して返してます。


・・・

export const getTopNewsTool = createTool({
  id: 'getTopNews',
  description: 'トップニュースを取得します',
  inputSchema: TopNewsParams,
  outputSchema: <outputSchema>,
  async execute({ context }) {
    try {
      const { lang, max } = context;
      const url = `${BASE_URL}/top-headlines?token=${API_KEY}&lang=${lang}&max=${max}`;
      const response = await fetchData<NewsResponse>(url);
      
      if (!response || !response.articles) {
        throw new Error('Invalid response format');
      }
      
      return response.articles;
    } catch (error) {
      console.error('error:', error instanceof Error ? error.message : String(error));
      return [];
    }
  }
});

・・・

アプリケーション設定 (src/mastra/index.ts):

アプリのエントリーポイントでAgentをMastraインスタンスに設定します。

import { Mastra } from '@mastra/core/mastra';
import { createLogger } from '@mastra/core/logger';
import { newsAgent } from './agents/news';

export const mastra = new Mastra({
 agents: {
    default: newsAgent,
 },
 logger: createLogger({
    name: "News Assistant",
    level: "debug",
  }),
});

起動

mastra devコマンドを実行すれば起動します。
localhost:4111で起動しました。

bun run dev
$ mastra dev
INFO [2025-03-21 15:53:46.265 +0900] (BUNDLER - Dev): Starting watcher...
INFO [2025-03-21 15:53:46.495 +0900] (BUNDLER - Dev): Bundling finished, starting server...
INFO [2025-03-21 15:53:46.500 +0900] (Mastra CLI): [Mastra Dev] - Starting server...
DEBUG [2025-03-21 15:53:47.751 +0900] (News Assistant): Logger updated [component=AGENT] [name=News Assistant]
DEBUG [2025-03-21 15:53:47.753 +0900] (News Assistant): Logger updated [component=LLM] [name=aisdk]
DEBUG [2025-03-21 15:53:47.753 +0900] (News Assistant): [Agents:News Assistant] initialized.
DEBUG [2025-03-21 15:53:47.754 +0900] (News Assistant): Logger updated [component=AGENT] [name=News Assistant]
DEBUG [2025-03-21 15:53:47.754 +0900] (News Assistant): Logger updated [component=STORAGE] [name=DefaultStorage]
INFO [2025-03-21 15:53:47.757 +0900] (News Assistant): 🦄 Mastra API running on port 4111/api
INFO [2025-03-21 15:53:47.758 +0900] (News Assistant): 📚 Open API documentation available at http://localhost:4111/openapi.json
INFO [2025-03-21 15:53:47.758 +0900] (News Assistant): 🧪 Swagger UI available at http://localhost:4111/swagger-ui
INFO [2025-03-21 15:53:47.758 +0900] (News Assistant): 👨‍💻 Playground available at http://localhost:4111/

サーバーが起動すると、以下のエンドポイントが利用可能になります:

Mastraは、HTTPサーバーフレームワークとしてHonoを使用します。
Mastraアプリケーションをビルド(mastra build)すると、HonoベースのHTTPサーバーが生成されます。
Playgroundにアクセスすると、実際にAgentとの会話のやりとりができます。

mastra.gif

Client SDK (src/client/news-client.ts):

Client用のSDKもあるので、以下のようにすればプログラムからアクセスできます。

import { MastraClient } from "@mastra/client-js";

const client = new MastraClient({
  baseUrl: "http://localhost:4111",
 // Optional
  retries: 3,           // Number of retry attempts
  backoffMs: 300,       // Initial retry backoff time
  maxBackoffMs: 5000,   // Maximum retry backoff time
  headers: {            // Custom headers for development
  }
});

async function main() {
  try {
    //Agent nameを指定して取得
    const agent = client.getAgent("default");
    const response = await agent.generate({
      messages: [{ 
        role: "user",
        content: "トップニュースを取得してください。言語: ja, 件数: 5"
      }]
    });

    if (response.text) {
      console.log("Response:", response.text);
    } else {
      console.log("No response text received");
    }

    if (response.toolResults && response.toolResults.length > 0) {
      console.log("Tool Results:", response.toolResults);
    }
  } catch (error) {
    console.error("Error:", error instanceof Error ? error.message : String(error));
  }
}

main();

実行すると以下のようにAgentの実行が可能です。

% bun run src/client/example.ts
Response: 以下、日本語のトップニュース5件をご紹介します。

1. [xxxxxxx](https://xxxxxxxx)
   - ニュース内容1・・・・

2. [yyyyyy](https://yyyyyy)
   - ニュース内容2・・・・

Deploy Cloudflare

では作成したAgentをCloudflareへデプロイしましょう。

デプロイするにはMastraが提供するCloudflare用のDeployerを使います。
他にもVercelやNetlifyが指定可能です。

デプロイするには以下の情報が必要なので、ダッシュボードにログインして確認しておきましょう。

  • Cloudflareアカウント
  • CloudflareのアカウントID

デプロイ設定と実行

デプロイ設定はさきほど作成したエントリーポイントでDeployerの設定します。

import { Mastra } from '@mastra/core/mastra';
import { createLogger } from '@mastra/core/logger';
import { newsAgent } from './agents/news';
import { CloudflareDeployer } from '@mastra/deployer-cloudflare';

export const mastra = new Mastra({
  deployer: new CloudflareDeployer({
    scope: <CloudflareのアカウントID,
    projectName: <Workersの名前>,
    routes: [
    ],
    auth: {
      apiToken: <CloudflareのAPIトークン>,
      apiEmail: <Cloudflareのメールアドレス>,
    },
  }),
  agents: {
    default: newsAgent,
  },
  logger: createLogger({
    name: "News Assistant",
    level: "debug",
  }),
});

以下のコマンドでデプロイを実行します。

% NODE_ENV=production bun run deploy # mastra deploy 
NODE_ENV=production bun run deploy
$ mastra deploy
INFO [2025-03-21 16:11:16.632 +0900] (DEPLOYER - CLOUDFLARE): Start bundling Mastra
INFO [2025-03-21 16:11:16.634 +0900] (DEPLOYER - CLOUDFLARE): Analyzing dependencies...
INFO [2025-03-21 16:11:16.839 +0900] (DEPLOYER - CLOUDFLARE): Optimizing dependencies...
INFO [2025-03-21 16:11:19.873 +0900] (DEPLOYER - CLOUDFLARE): Bundling Mastra application
INFO [2025-03-21 16:11:20.231 +0900] (DEPLOYER - CLOUDFLARE): Bundling Mastra done
INFO [2025-03-21 16:11:20.231 +0900] (DEPLOYER - CLOUDFLARE): Copying public files
INFO [2025-03-21 16:11:20.231 +0900] (DEPLOYER - CLOUDFLARE): Done copying public files
INFO [2025-03-21 16:11:20.232 +0900] (DEPLOYER - CLOUDFLARE): Installing dependencies
added 67 packages, and audited 68 packages in 7s

・・・

INFO [2025-03-21 16:11:34.552 +0900] (DEPLOYER - CLOUDFLARE): https://xxxxxxxx.workers.dev
Current Version ID: xxxxxxx

デプロイのログで使用できる環境変数や発行されたURLがわかります。

Cloudflareにアクセスしてみる

デプロイが完了したら、さきほどのクライアントコードのbaseUrlを更新してアクセスできます。

//src/client/example.ts
const client = new MastraClient({
  baseUrl: "<デプロイして発行されたURL>",
  // ...
});

さきほどと同じように実行すると、今度はCloudflare Workersに
デプロイされたAgentに対してアクセスします。

Summary

今回はMastraを使用してAgentの作成とCloudflareへのデプロイをしてみました。
非常に簡単にAgentの作成からデプロイまでできることがわかります。

Mastraはまだリリースされたばかりですが、使いやすく、機能も次々に追加されてます。
今後、Typescript用AI Agent作成ツールのスタンダードになる可能性も大いにありそうです。

References

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.