
AI Foundry で Microsoft 365 Copilot 向けカスタムエンジンエージェントを構築する
M365 Agents SDK を使って独自のAIアプリを Copilot エージェントとして公開したいニーズは一定あると思う!
TL;DR
すでにマルチエージェントAIアプリを持っているなら、余計なオーケストレーションレイヤーを追加することなく Microsoft 365 Copilot 内に表示できます。
Microsoft 365 Agents SDK を使って「プロキシエージェント」を作成し、Copilotのアクティビティを処理して既存のバックエンドにシンプルなリクエストを転送します。
この例では、Semantic Kernel のマルチエージェントワークフローを使い、ブログ記事の作成とSEO最適化を行います。
開発は迅速に進められ、VS Code の Microsoft 365 Agents Toolkit を使って Azure にデプロイできます。
👉 すぐにコードとステップごとのデプロイ手順を試したい方は このGitHubリポジトリ を参照してください。
カスタムエンジンエージェント(CEA)とは?
ソフトウェア企業(デジタルネイティブやISV)は、完全なマルチエージェントAIアプリケーションを構築し、複数のチャネルに展開したいと考えています。Microsoft 365 Copilot は人気のあるチャネルですが、すでに独自のオーケストレーションを持っています。
そのため、既存アプリに Copilot のオーケストレーションを重ねると、不要なレイヤーになる場合があります。
カスタムエンジンエージェント(CEA) はその余計なレイヤーを取り除き、アプリケーションを「エンジン」として保持します。Microsoft 365 Agents SDK は軽量な統合レイヤーを提供し、エージェントを Copilot 内で一級の存在にします。
リファレンスアーキテクチャ
ハイレベルな流れ:
Microsoft 365 Copilot Chat → ユーザーがエージェントを選択し、プロンプトを送信
Azure Bot Service → Copilot アクティビティ(ユーザーメッセージなど)を安全にボットエンドポイントに配送
プロキシエージェント(Microsoft 365 Agents SDK) → 認証、アクティビティ処理、バックエンドへのリクエスト転送(オーケストレーション不要)
CEA バックエンド → 独自のマルチエージェントワークフローを実行し、結果をプロキシ経由で Copilot に返す
これにより、Copilot との統合をシンプルに保ちつつ、自分のオーケストレーションを維持できます。

プロキシエージェントの実装
プロキシは Microsoft 365 Agents SDK で構築される小さなチャネル対応レイヤーです。
リクエストの検証・認証(Microsoft Entra)
アクティビティ(メッセージ、タイピング、メンバー追加など)の処理
入出力の正規化(バックエンドAPI用)
ステートレス・低複雑性を維持し、オーケストレーションはアプリに任せる
Python サンプル(/cea-proxy-py)
PyPi パッケージ: `microsoft-agents-hosting-core`
ActivityHandler をサブクラス化し、`on_message_activity` で Copilot から送られるメッセージを取得
コード例:
async def on_message_activity(self, turn_context: TurnContext):
user_text = turn_context.activity.text or ""
base_url = os.getenv("BACKEND_BASE_URL", "http://localhost:8000")
endpoint = f"{base_url.rstrip('/')}/generate-blog"
try:
timeout = aiohttp.ClientTimeout(total=120)
async with aiohttp.ClientSession(timeout=timeout) as session:
async with session.post(endpoint, json={"prompt": user_text}) as resp:
if resp.status != 200:
err_text = await resp.text()
message = f"Request failed ({resp.status}). {err_text[:300]}"
activity = MessageFactory.text(message)
return await turn_context.send_activity(activity)
data = await resp.json(content_type=None)
content = data.get("content") if isinstance(data, dict) else None
if not content:
content = "No content returned from generator."
activity = MessageFactory.text(content)
return await turn_context.send_activity(activity)
except Exception as e:
activity = MessageFactory.text(f"Error contacting generator: {e}")
return await turn_context.send_activity(activity)TypeScript サンプル(/cea-proxy-ts)
npm パッケージ: @microsoft/agents-hosting
Semantic Kernel + Azure OpenAI を用いた CEA バックエンド設計
バックエンド(backend/main.py)は FastAPI アプリで、Semantic Kernel の Azure Responses Agents を利用。プロキシが利用する統一エンドポイントを公開:
POST /generate-blog
Accepts: { topic, length } または { prompt }
Returns: { content: string }(最終Markdown)

マルチエージェントフロー
パラメータ抽出エージェント
入力: フリーフォームのプロンプト
出力: JSON(topic, length)
小型モデル・低温度で決定的な構造
ブログライターエージェント
入力: topic, length
出力: Markdown下書き
クリエイティブ設定でリッチなコンテンツ
SEO最適化エージェント
入力: 下書き
出力: JSON(タイトル、メタ、スラッグ、見出し、修正版記事、改善点、キーワード、リンク、可読性、CTA)
SEO出力をライターに戻して最終仕上げ
ベストプラクティス:
リクエスト/レスポンスロギングミドルウェア
寛容なペイロードパース(文字列・JSON両対応)
Pydantic バリデーションで堅牢な型付き出力
Microsoft 365 Agents Toolkit (VS Code) で素早く開始
VS Code 拡張を利用すると、開発とデプロイが容易になります。
スキャフォルディング
TypeScript または Python でカスタムエンジンエージェントプロジェクトを作成できます。アダプター、アクティビティハンドラー、マニフェスト、設定ファイルが含まれます。
📝 注意: 新規プロジェクト作成時、Toolkit はデフォルトで「Agent SDK 内で CEA を構築している」と仮定し、Azure OpenAI のエンドポイントとキーの入力を求めます。空欄のままでも問題ありませんが、その場合はデプロイ時にそれらの変数が参照されている yaml ファイルから削除してください。ローカルデバッグ
組み込みの Playground を使用して、トンネル不要でローカル実行・デバッグが可能です。
あるいは Debug in Copilot を選択すると、Azure Bot をエミュレートするローカルトンネルが設定され、Copilot からローカルで稼働中のプロキシにリクエストを転送できます。デプロイ
「Deploy to Azure」をクリックすると、Azure リソース(App Service、Managed Identity、Bot 登録)がプロビジョニングされ、VS Code から直接プロキシエージェントをデプロイできます。
📝 注意: この手順では バックエンドはデプロイされません。

このリポジトリは Toolkit のテンプレートから作成されているため、VS Code で開くだけでこれらのワークフローをすぐに利用できます。
VS Code で個別の CEA フォルダー(例: `cea-proxy-py`)を開けば、Toolkit がそれを カスタムエンジンエージェントプロジェクト として認識します。
💡 ヒント: Toolkit は Copilot 対応のマニフェストや ZIP パッケージも生成できるため、手動での接続設定やスキーマ/バージョンの問題を減らせます。
これを行うには、いずれかのデバッグモード(例: local)を実行し、`cea-proxy-xx/appPackage/build` 配下に生成されるマニフェストを確認してください。
Copilot対応にするためのマニフェスト要点
M365 Agent Toolkit Extension は、必要な属性を含む manifest.json を自動生成してくれます。
ここでは、カスタムエンジンエージェント(CEA)を Copilot エージェントとして表示するために必要な要素を整理します。
CEA の宣言
ファイル:
`cea-proxy-ts/appPackage/manifest.json`
`cea-proxy-py/appPackage/manifest.json`
主要ポイント:
`copilotAgents.customEngineAgents: { "type": "bot", "id": "" }`
`bots.scopes` に `copilot` と `personal` を含める
`personal` スコープを指定することで、Teams Bot としても利用可能
任意で `commandLists` を追加すると、Copilot UI に推奨プロンプトが表示される
これが、Copilot にエージェントを Azure Bot Service 経由でルーティングさせる重要なリンクになります。
💡 ヒント: VS Code 用の Microsoft 365 Agents Toolkit を使えば、これらの属性や Bot ID の入力は自動で設定されます。
Copilot エージェントを組織に公開する方法
VS Code 拡張がビルドする appPackage ZIP ファイル を利用します。
この ZIP を Microsoft Teams 経由で組織にアップロードすれば、組織内で Copilot エージェントを利用可能になります。

このパターンを使うべきとき
すでにマルチエージェントAIアプリがあり、Copilot に統合したいがオーケストレーションを重ねたくない
エージェントAIバックエンドをUXチャネル向けミドルウェアから分離したい
オーケストレーション、プロンプト、ツール、モデル選択を厳密に管理したい(Azure OpenAIや独自モデルを利用)
複数チャネル(Copilot、Teams、Webなど)で1つのエンジンを再利用したい
FAQ
Q: カスタムエンジンエージェントと宣言的エージェントの違いは何ですか?
A: 宣言的エージェントは Copilot のオーケストレーション(指示、ナレッジ、アクション)に依存します。
カスタムエンジンエージェントは独自のオーケストレーターやモデルを利用し、Agents SDK はチャネルおよびアクティビティレイヤーとしてのみ活用します。
Q: Azure Bot Service は必要ですか?
A: はい。Microsoft 365 Agents SDK は、Copilot とエージェントエンドポイント間のチャネル接続を Azure Bot Service で処理します。
Q: LangChain など他のオーケストレーターを使えますか?
A: はい。SDK はオーケストレーターに依存しません。このリポジトリは Semantic Kernel を使用していますが、LangChain、Azure AI Foundry Agents、または独自エンジンを利用可能です。
Q: Teams にも対応していますか?
A: はい。プロキシエージェントは Copilot、Teams、Web など複数のチャネルで利用できます。
Azure Bot を使用することで、追加チャネルとの通信も可能になります。
リファレンス
Repo