JavaScriptで始めるAIエージェント開発入門
背景
AIエージェントが自律的に複数のタスクを行う際、エージェントを呼び出すエージェント(オーケストレーター)が連携を管理する必要があります。また、最近では様々なエージェントフレームワークが登場しています。複数のAIエージェント同士が連携をとるAgent to Agent(A2A)の時代において、オーケストレーターの存在はますます大きくなり、今後のAIエージェント開発の鍵を握る存在になると考えられます。そこで今回はオーケストレーターの構築に役立つエージェントフレームワークについて調べ、いくつかのサンプル実装を試しました。
なお、今回はTeamsアプリにおけるAIエージェントを作るため、扱うプログラミング言語はMicrosoft 365 Agents Toolkitに合わせてJavaScript/TypeScriptであることを前提に話を進めます。
対象読者
- JavaScript/TypeScriptでオーケストレーターを開発したい人
- エージェントフレームワークを知りたい人
エージェントフレームワークとは
オーケストレーターはエージェントを呼び出すエージェントで、全体の統合を担うような存在です。エージェントフレームワークはオーケストレーターの構築をより簡単に実現できます。たとえば対話型エージェントが検索拡張生成(RAG)を行ったり、ツール連携を行ったりするといったことが、より抽象的な実装で簡単に実現することができます。
ここではMicrosoft 365 Agents Toolkitで作成するアプリに組込みを行う想定のため、JavaScript/TypeScriptで扱えるエージェントフレームワークを調べました。以下のようなエージェントフレームワークがあったため、それぞれ試しにサンプルの実装をしました。
- Mastra
- LangChainJS
- VoltAgent
サンプル実装内容
-
以前の記事で作成した、足し算をするMCPサーバーである
addツール
をエージェントから呼び出すような実装を行いました。 -
「10たす10たす20はいくつ?」
というプロンプトを入力すると、addツール
が呼び出され、計算結果40
が返ってくることを期待します。
Mastra実装
import { Agent } from '@mastra/core/agent';
import { createAzure } from "@ai-sdk/azure"
import { config } from "./config.js"
import { MCPClient } from "@mastra/mcp";
// Azure 接続情報 設定
const azure = createAzure({
apiKey: config.apiKey,
resourceName: config.resourceName,
})
// MCPクライアント 作成
const mcp = new MCPClient({
servers: {
add: {
url: new URL("http://localhost:8080/stream"),
},
},
});
// エージェント 作成
export const agent = new Agent({
name: "AI Agent",
instructions: "You are a helpful agent.",
model: azure(config.deploymentName),
tools: await mcp.getTools(),
});
// プロンプトをエージェントに送信
const result = await agent.generate("10たす10たす20はいくつ?")
// 回答表示
console.log(result.text)
// プロセス終了
process.exit(0);
LangChainJS実装
import { AzureChatOpenAI } from "@langchain/openai";
import { config } from "./config.js"
import { HumanMessage } from "@langchain/core/messages";
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
// Azure 接続情報 設定
const agent = new AzureChatOpenAI({
azureOpenAIApiKey: config.apiKey,
azureOpenAIApiVersion: config.apiVersion,
azureOpenAIApiDeploymentName: config.deploymentName,
azureOpenAIApiInstanceName: config.resourceName,
});
// MCPクライアント 作成
const client = new MultiServerMCPClient({
mcpServers: {
add: {
url: "http://localhost:8080/stream"
}
}
});
// MCPツールの取得
const tools = await client.getTools();
// ツールをチャットモデルにバインド
agent.bindTools(tools);
// プロンプトをチャットモデルに送信
const response = await agent.invoke([new HumanMessage("10たす10たす20はいくつ?")]);
// 回答表示
console.log("Bot:", response.content);
// プロセス終了
process.exit(0);
VoltAgent実装
import { Agent, MCPConfiguration } from "@voltagent/core";
import { VercelAIProvider } from "@voltagent/vercel-ai";
import { createAzure } from "@ai-sdk/azure"
import { config } from "./config.js"
// Azure 接続情報 設定
const azure = createAzure({
apiKey: config.apiKey,
resourceName: config.resourceName,
})
const mcpConfig = new MCPConfiguration({
servers: {
add: {
type: "http",
url: "http://localhost:8080/stream",
}
}
})
// エージェント 作成
const chatAgent = new Agent({
name: "ChatAgent",
description: "You are a helpful agent.",
llm: new VercelAIProvider(),
model: azure(config.deploymentName),
tools: await mcpConfig.getTools(),
});
// プロンプトをエージェントに送信
const response = await chatAgent.generateText("10たす10たす20はいくつ?");
// プロセス終了
process.exit(0);
実行結果
以下のような回答が返ってくるかと思います。
考察
実行結果より、足し算の結果として40
という答えが得られたかと思います。
しかし、皆さんの中にはaddツール
の連携でこの結果が得られたことに少し疑問を感じた方もいるのではないでしょうか。
なぜなら、addツール
は2つの値を入力としているため、10・10・20
の3入力をサポートしていないからです。
ここで、もう少し詳しく実行結果を調べるため、mastra.js
に以下のログ出力を加えて動作を確認してみましょう。
// ステップ1の実行結果
console.log(result.steps[0].toolCalls);
// ステップ2の実行結果
console.log(result.steps[1].toolCalls);
追加したログ出力の結果は以下となります。
どうやらツール連携は2段階のステップで実行されているようです。
1段階目では10+10
、20+0
の計算をaddツール
の呼び出しにより実行しています。
2段階目では1段階目の結果である20
と20
を足して最終的な結果である40
を得ています。
このようにエージェントフレームワークを使うことにより、プロンプトからエージェント自身がどのようにツール連携をステップ実行していけば求める結果が得られるかを判断し、自律的にツール連携の実行までしてくれることがわかりました。
まとめ & 次のステップ
- JavaScript/TypeScriptのエージェントフレームワークとしてMastra、LangChainJS、VoltAgentなどがあります
- エージェントフレームワークはどのようにツール連携をすれば求める結果が得られるのかを判断し、自律的にツール連携を実行します
- 今後、どのエージェントフレームワークを採用して開発するか検討したいです
Discussion