本記事では、Microsoft Agent Framework を利用して AI エージェントを作成する方法を紹介します。
Microsoft Agent Framework の概要
Microsoft Agent Framework は、.NET および Python 用の AI エージェント と マルチエージェント ワークフロー を構築するためのオープンソース開発キットです。
Semantic Kernel と AutoGen プロジェクトからアイデアをまとめ、拡張し、その長所を組み合わせて新しい機能を追加します。
実行環境
- Python 3.12
- agent-framework 1.0.0b251114
環境変数の設定
今回の記事では、Azure OpenAIのリソースを利用します。以下の環境変数を利用します。
AZURE_OPENAI_ENDPOINT="https://<Azure OpenAIのリソース>.openai.azure.com/" AZURE_OPENAI_CHAT_DEPLOYMENT_NAME="<デプロイメント名>" AZURE_OPENAI_API_KEY="<Azure OpenAI API Key>"
MCPツールを利用するAIエージェントの構築
以下のコードでは、Microsoft Learn の MCP サーバーを利用します。
参考:MCP ツールの使用 | Microsoft Learn
コード
import asyncio from agent_framework import ChatAgent, MCPStreamableHTTPTool from agent_framework.azure import AzureOpenAIChatClient from azure.identity import AzureCliCredential async def http_mcp_example(): """Example using an HTTP-based MCP server.""" credential = AzureCliCredential() #DefaultAzureCredential() async with ( MCPStreamableHTTPTool( name="Microsoft Learn MCP", url="https://learn.microsoft.com/api/mcp", headers={"Authorization": "Bearer your-token"}, ) as mcp_server, ChatAgent( #chat_client=AzureAIAgentClient(async_credential=credential), chat_client=AzureOpenAIChatClient(async_credential=credential), name="DocsAgent", instructions="You help with Microsoft documentation questions.", ) as agent, ): async for update in agent.run_stream("最新のAgent FrameworkでのChatClientの種類を教えてください。引用元も教えてください。", tools=mcp_server): if update.text: print(update.text, end="", flush=True) print() # New line after streaming is complete if __name__ == "__main__": asyncio.run(http_mcp_example())
実行結果
「最新のAgent FrameworkでのChatClientの種類を教えてください。引用元も教えてください。」に対して、Microsoft Agent Framework Agent Types - Azure AI Foundry | Microsoft LearnなどのMicrosoft Learnの内容を元に期待通りの回答が生成されました。引用元も適切でした。
マルチエージェントのオーケストレーション
以下のコードでは、エージェントの並列処理(Concurrent)の例を記載します。
参考:Microsoft Agent Framework ワークフローオーケストレーション | Microsoft Learn
コード
import os import asyncio from typing import Any from azure.identity import AzureCliCredential from agent_framework.azure import AzureOpenAIChatClient from agent_framework import ConcurrentBuilder, ChatMessage async def main() -> None: """Run a concurrent workflow with three domain agents using AzureOpenAIChatClient.""" credential = AzureCliCredential() # 1) Create a shared chat client and three domain agents chat_client = AzureOpenAIChatClient( credential=credential ) researcher = chat_client.create_agent( instructions=( "You're an expert market and product researcher. Given a prompt, provide concise, factual insights," " opportunities, and risks." ), name="researcher", ) marketer = chat_client.create_agent( instructions=( "You're a creative marketing strategist. Craft compelling value propositions and target messaging" " aligned to the prompt." ), name="marketer", ) legal = chat_client.create_agent( instructions=( "You're a cautious legal/compliance reviewer. Highlight constraints, disclaimers, and policy concerns" " based on the prompt." ), name="legal", ) # 2) Build a concurrent workflow # Participants are either Agents (type of AgentProtocol) or Executors workflow = ConcurrentBuilder().participants([researcher, marketer, legal]).build() # 完了まで実行し、出力だけ取得 result = await workflow.run("私たちは都市部の通勤者向けに手頃な価格の新しい電動自転車を発売します。意見をください。") outputs = result.get_outputs() # ワークフローが生成した出力のリスト # 代表ケース:最終出力が list[ChatMessage] のものを検索(複数あれば最後を採用) final_messages: list[ChatMessage] | None = None for o in outputs: if isinstance(o, list) and (not o or isinstance(o[0], ChatMessage)): final_messages = o # 上書きしていき、最後のものを採用 if final_messages: print("===== Final Aggregated Conversation (messages) =====") for i, msg in enumerate(final_messages, start=1): name = getattr(msg, "author_name", None) or getattr(msg, "role", None) or "user" sep = "-" * 60 print(f"{sep}\n\n{i:02d} [{name}]:\n{msg.text}") else: # 型が異なる設計の場合はそのまま表示 print("Outputs:", outputs) if __name__ == "__main__": asyncio.run(main())
実行結果
以下は、「私たちは都市部の通勤者向けに手頃な価格の新しい電動自転車を発売します。意見をください。」に対して3つのエージェントが並列で回答を作成した結果です。
各エージェントはそれぞれの instructions に従い回答しています。
===== Final Aggregated Conversation (messages) ===== ------------------------------------------------------------ 01 [user]: 私たちは都市部の通勤者向けに手頃な価格の新しい電動自転車を発売します。意見をください。 ------------------------------------------------------------ 02 [researcher]: 【インサイト】 - 都市部の通勤者は、渋滞回避や環境配慮、健康志向から電動自転車の需要が増加中。 - ただし、既存市場には多くのブランドがあり、差別化が重要。 - 価格に敏感な層向けには、「コストパフォーマンス」と「メンテナンスの容易さ」が購買決定の鍵となる。 【機会】 - 短距離通勤者や公共交通機関からの乗り換え層をターゲットにできる。 - フレキシブルな価格帯設定や分割払いプランで購入者拡大可能。 - 充電時間短縮や軽量設計などの技術革新をアピールすると強みになる。 【リスク】 - 低価格帯は品質や耐久性の低下に繋がる可能性があり、ブランドイメージに影響。 - 市場の成熟により価格競争が激しく、利益率が低くなる恐れ。 - 自転車盗難や駐輪環境の問題も購入をためらう要因となる。 【提案】 - 安価でも安心感を与えるため、保証体制やアフターサービスを充実させる。 - 通勤特化の付加価値(例:充電ステーション提携、通勤ルート提案アプリ)を検討。 - 環境に配慮した素材や製造プロセスの活用で、エコ志向層を取り込む。 ------------------------------------------------------------ 03 [marketer]: 価値提案: 「都市の毎日をもっとスマートに、もっと快適に。手頃な価格で手に入る最新の電動自転車で、通勤ストレスを軽減し、時間とコストを節約。環境に優しく、健康的な通勤ライフをサポートします。」 ターゲットメッセージ: 1. 「渋滞知らず、満員電車も爽快!あなたの新しい通勤パートナー、電動自転車で自由な街乗りを。」 2. 「毎日の通勤、もっとラクに。手頃な価格の電動自転車で快適&エコな移動を始めよう。」 3. 「時間もお財布も節約!都市生活にぴったりの電動自転車で、ストレスフリーな朝を迎えよう。」 4. 「遠くても大丈夫。電動アシストで坂道もスイスイ、どんな道も自信を持って走れる。」 5. 「通勤時間を自分時間に。快適な乗り心地とスタイリッシュなデザインで毎日をもっと特別に。」 これらのメッセージは、都市部の通勤者が抱える「通勤の不便さ」「コスト」「環境意識」などのニーズに寄り添い、製品の魅力を効果的に伝えます。 ------------------------------------------------------------ 04 [legal]: 新しい電動自転車の発売に関するご相談について、以下の法的およびコンプライアンス上のポイントをご留意ください。 1. **製品安全基準の遵守** - 電動自転車は各国・地域の安全基準や規格(例:電気安全法、道路交通法規制、各国の電動自転車の定義など)を満 たす必要があります。 - バッテリーやモーターの安全性、耐久性についても適切な試験・認証を取得してください。 2. **表示義務・広告規制** - 製品の性能や価格に関する誤解を招く表現は避けること。適正な表示・広告規制(景品表示法など)を遵守してくだ さい。 - 適正な保証内容やアフターサービスについても明示し、消費者への説明責任を果たしてください。 3. **特許権や商標権の確認** - 技術やデザインに関して第三者の知的財産権を侵害していないか、事前に確認する必要があります。 4. **個人情報保護** - スマート機能やアプリ連携がある場合、収集する個人情報の取り扱いに関するプライバシーポリシーの策定と遵守が 必要です。 5. **販売後のクレーム対応・補償** - 初期不良や事故が発生した場合の対応をあらかじめ取り決めておくことを推奨します。 これらの点を専門家としっかり確認し、法令を遵守した製品開発および販売を進めてください。なお、具体的な法的助言については、専門の法律顧問にご相談ください。
最後に
今回は Microsoft Agent Framework を用いて、AI エージェントとマルチエージェントのオーケストレーションを試しました。
Semantic Kernel や AutoGen で実現していた機能を、よりシンプルな API で再現・拡張できる点が印象的です。
Semantic Kernel からの移行ガイドには、簡略化された APIによる複雑さと定型コードの削減や、オブジェクトの作成とメモリ使用量を最適化によるパフォーマンスの向上といった利点の記載があったので、既存プロジェクトの段階的な移行を検討していきたいです。