Microsoft のエージェント フレームワークを使用したマルチエージェント AI システムの構築
はじめに
マルチエージェント AI システムの時代が到来しました。業界は、単一のモノリシック AI がすべてを処理するのではなく、よく組織された専門家チームのように、協力して複雑な問題を解決する専門エージェントに移行しています。 1 人のエージェントが調査を行い、もう 1 人が分析し、3 人目が書き込みを行い、コーディネーターが全員の進捗状況を把握します。
大規模な言語モデルを扱ったことがある場合は、1 つのプロンプトで実行できる処理の上限に達している可能性があります。コンテキスト ウィンドウがいっぱいになり、命令が複雑になり、品質が低下します。マルチエージェント アーキテクチャは、各エージェントが 1 つの分野の専門家となり、複雑なタスクを焦点を絞った責任に分解することでこの問題を解決します。
より広範なセマンティック カーネル エコシステムの一部である Microsoft のエージェント フレームワークは、.NET 開発者にまさにこの種のシステムを構築するための最上級のツールキットを提供します。この投稿では、ゼロからマルチエージェント パイプラインを完全に機能させるまでに取り組み、開始するために必要な中心的な概念、オーケストレーション パターン、実践的なコードを取り上げます。
Microsoft のエージェント フレームワークとは何ですか?
Agent Framework は、.NET で AI エージェントとマルチエージェント システムを構築、オーケストレーション、展開するための Microsoft の答えです。これは、2023 年以来 Microsoft の AI オーケストレーション用のオープンソース SDK であるセマンティック カーネルと並行し、深く統合されています。
次のように考えてください。セマンティック カーネル はプリミティブ (カーネル、プラグイン、メモリ、プランナー) を提供し、エージェント フレームワーク は、エージェント間の通信と調整のために特別に設計された高レベルの抽象化を提供します。
このフレームワークは、Azure OpenAI、OpenAI、Azure AI Foundry でホストされるモデルなど、複数のモデル プロバイダーをサポートします。モデルに依存しない設計ですが、Azure エコシステムと深く統合されているため、エンタープライズ シナリオにとって特に魅力的です。
主な機能は次のとおりです。
- 複数のエージェント タイプ: さまざまなバックエンドの
ChatCompletionAgent、OpenAIAssistantAgent、およびAzureAIAgent - オーケストレーション パターン: 順次、同時、ハンドオフ、グループ チャットのワークフロー
- プラグイン エコシステム: ネイティブ C# 機能、OpenAPI 仕様、モデル コンテキスト プロトコル (MCP) ツールを使用してエージェントを拡張します。
- 会話管理: 組み込みのスレッド化、履歴管理、および終了戦略
- 可観測性: エージェントの対話を追跡するための OpenTelemetry との統合
主要な概念
コードを書く前に、語彙を確立しましょう。エージェント フレームワークは、いくつかのコア抽象化を中心に展開します。
エージェント
エージェントは AI モデルによってサポートされるエンティティであり、特定の命令 (システム プロンプト)、名前、およびオプションでプラグインまたはツールのセットで構成されます。各エージェントはスペシャリストです。エージェントが何を知っているか、何ができるか、どのように動作するかを定義します。
ChatCompletionAgent最も単純なエージェント タイプ。チャット完了エンドポイント (Azure OpenAI、OpenAI など) をラップし、会話を維持します。呼び出し間はステートレスです。履歴を提供すると、応答します。これにより、軽量になり、推論が容易になります。
ChatCompletionAgent agent = new()
{
Name = "Reviewer",
Instructions = "You are a senior code reviewer. Analyze the provided code for bugs, security issues, and style violations. Be concise and actionable.",
Kernel = kernel
};
OpenAIAssistantAgent
このエージェント タイプは、サーバー側の会話状態、ファイル処理、コード解釈を提供する OpenAI Assistants API を利用します。これはより重いですが、永続的なスレッドと、コードインタープリタやファイル検索などの組み込みツールを提供します。
OpenAIAssistantAgent agent = await OpenAIAssistantAgent.CreateAsync(
clientProvider: clientProvider,
definition: new OpenAIAssistantDefinition("gpt-4o")
{
Name = "DataAnalyst",
Instructions = "You analyze datasets and produce statistical summaries."
}
);
エージェントグループチャット
これがオーケストレーターです。 AgentGroupChat は、複数のエージェント間のマルチターン会話を管理し、次に話す人、会話がいつ終了するか、履歴がどのように共有されるかを制御します。ここで、マルチエージェントのコラボレーションの魔法が起こります。
オーケストレーション パターン
このフレームワークは 4 つの主要なオーケストレーション パターンをサポートしており、それぞれが異なる問題に適しています。
シーケンシャル
エージェントは、定義された順序で次々に実行されます。エージェント A の出力はエージェント B にフィードされ、エージェント B の出力はエージェント C にフィードされます。これは、パイプライン (ドラフト → レビュー → 編集 → 公開) に最適です。
// Conceptual flow
var draft = await writerAgent.InvokeAsync("Write a blog post about .NET 9");
var reviewed = await reviewerAgent.InvokeAsync($"Review this: {draft}");
var edited = await editorAgent.InvokeAsync($"Edit based on feedback: {reviewed}");
同時実行
複数のエージェントが同じ入力に対して同時に作業します。作業を扇状に広げてから、結果を集計します。 3 人のレビュー担当者が同じプル リクエストを検討するなど、多様な視点を得るのに最適です。
ハンドオフ
エージェントは、会話コンテキストに基づいて制御を別のエージェントに移すことを決定します。これはカスタマー サービス チームの仕組みを模倣しています。最前線のエージェントが基本的な問い合わせを処理し、必要に応じて専門家にエスカレーションします。
グループチャット
複数のエージェントがオープンな会話に参加し、選択戦略に基づいて交代します。 AgentGroupChat クラスは、構成可能な交代および終了ロジックを使用してこのパターンを実装します。
最初のエージェントを構築する
実践してみましょう。最初のエージェントを段階的に構築する方法を次に示します。
前提条件
必要なものは次のとおりです。
- .NET 9 SDK
- デプロイされたモデルを含む Azure OpenAI リソース (例:
gpt-4o) - Visual Studio または VS Code
プロジェクトのセットアップ
新しいコンソール アプリケーションを作成し、必要なパッケージをインストールします。
dotnet new console -n AgentDemo
cd AgentDemo
dotnet add package Microsoft.SemanticKernel --prerelease
dotnet add package Microsoft.SemanticKernel.Agents.Core --prerelease
dotnet add package Azure.AI.OpenAI
dotnet add package Azure.Identity
単純なエージェントの作成
まず、Azure OpenAI 構成を使用してカーネルをセットアップします。
using Azure.Identity;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.ChatCompletion;
var builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(
deploymentName: "gpt-4o",
endpoint: "https://your-resource.openai.azure.com/",
credentials: new DefaultAzureCredential()
);
Kernel kernel = builder.Build();
次に、エージェントを作成して呼び出します。
ChatCompletionAgent agent = new()
{
Name = "TechWriter",
Instructions = """
You are a technical writer specializing in software documentation.
Write clear, concise content aimed at experienced developers.
Use code examples when appropriate.
Always structure your output with headings and bullet points.
""",
Kernel = kernel
};
ChatHistory history = new();
history.AddUserMessage("Explain dependency injection in .NET in 200 words.");
await foreach (ChatMessageContent response in agent.InvokeAsync(history))
{
Console.WriteLine(response.Content);
}
それだけです。働いているエージェントがいます。しかし、本当の力はエージェントが協力するときに発揮されます。
AgentGroupChat を使用したマルチエージェント オーケストレーション
もっと興味深いもの、つまり複数のエージェントが協力するグループ チャットを構築してみましょう。 AgentGroupChat クラスは、次に誰が話すか、いつ停止するかなどの会話フローを管理します。
エージェントの定義
ライター、レビューアー、編集者の 3 人のエージェントを作成します。
ChatCompletionAgent writer = new()
{
Name = "Writer",
Instructions = """
You are a content writer. When given a topic, produce a well-structured
draft. Focus on clarity and technical accuracy.
When you receive feedback from the Reviewer, incorporate it into a
revised draft.
""",
Kernel = kernel
};
ChatCompletionAgent reviewer = new()
{
Name = "Reviewer",
Instructions = """
You are a content reviewer. Analyze drafts for technical accuracy,
clarity, and completeness. Provide specific, actionable feedback.
Do NOT rewrite the content — only provide feedback.
When the content meets your standards, respond with: APPROVED
""",
Kernel = kernel
};
ChatCompletionAgent editor = new()
{
Name = "Editor",
Instructions = """
You are an editor. Once content is approved by the Reviewer,
polish it for grammar, tone, and formatting.
Output only the final polished version.
When you have produced the final version, respond with: COMPLETE
""",
Kernel = kernel
};
グループチャットの設定
AgentGroupChat には 2 つの重要な設定が必要です。選択戦略 (次に誰が話すか) と 終了戦略 (いつ停止するか) です。
AgentGroupChat chat = new(writer, reviewer, editor)
{
ExecutionSettings = new()
{
SelectionStrategy = new SequentialSelectionStrategy(),
TerminationStrategy = new ApprovalTerminationStrategy()
{
Agents = [editor],
MaximumIterations = 12
}
}
};
カスタム終了戦略終了戦略は、会話がいつ終了するかを定義します。これは、「COMPLETE」キーワードを検索するカスタムのものです。
class ApprovalTerminationStrategy : TerminationStrategy
{
protected override Task<bool> ShouldAgentTerminateAsync(
Agent agent,
IReadOnlyList<ChatMessageContent> history,
CancellationToken cancellationToken = default)
{
bool isComplete = history
.Last()
.Content?
.Contains("COMPLETE", StringComparison.OrdinalIgnoreCase) ?? false;
return Task.FromResult(isComplete);
}
}
会話を進める
ユーザー メッセージで会話を開始し、エージェントが協力できるようにします。
chat.AddChatMessage(
new ChatMessageContent(AuthorRole.User,
"Write a 300-word technical overview of gRPC vs REST for microservices.")
);
await foreach (ChatMessageContent message in chat.InvokeAsync())
{
Console.WriteLine($"[{message.AuthorName}]: {message.Content}");
Console.WriteLine("---");
}
フローは次のようになります。
- ライターが草稿を作成します
- レビュー担当者がフィードバックを提供します
- ライターはフィードバックに基づいて修正します
- 査読者は「承認済み」と言う
- 編集者が磨きをかけて「完了」と言います
- 会話が終了します
このやり取りは、終了条件が満たされるか MaximumIterations に達するまで自動的に継続されます。
プラグインとツール
エージェントは、外部システムと対話できるようになると真に強力になります。 Agent Framework は 3 つの主要な拡張メカニズムをサポートしています。
ネイティブ関数 (カーネルプラグイン)
エージェントにツールとして C# メソッドへのアクセスを許可できます。エージェントは、必要であると判断した場合に、これらの関数を呼び出します。
public class ContentToolsPlugin
{
[KernelFunction("word_count")]
[Description("Counts the number of words in the provided text.")]
public int WordCount([Description("The text to count words in")] string text)
{
return text.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
}
[KernelFunction("check_readability")]
[Description("Calculates a readability score for the given text.")]
public string CheckReadability([Description("The text to analyze")] string text)
{
var words = text.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
var sentences = text.Split(['.', '!', '?'], StringSplitOptions.RemoveEmptyEntries).Length;
if (sentences == 0) return "Unable to calculate — no sentences found.";
double avgWordsPerSentence = (double)words / sentences;
return avgWordsPerSentence switch
{
< 15 => $"Easy to read (avg {avgWordsPerSentence:F1} words/sentence)",
< 25 => $"Moderate difficulty (avg {avgWordsPerSentence:F1} words/sentence)",
_ => $"Difficult to read (avg {avgWordsPerSentence:F1} words/sentence). Consider shorter sentences."
};
}
}
エージェントを作成する前に、カーネルにプラグインを登録します。
kernel.Plugins.AddFromType<ContentToolsPlugin>();
ChatCompletionAgent analyst = new()
{
Name = "ContentAnalyst",
Instructions = "Analyze content using available tools. Report word count and readability.",
Kernel = kernel,
Arguments = new KernelArguments(
new PromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
})
};
モデル コンテキスト プロトコル (MCP)
MCP は、AI モデルを外部ツールやデータ ソースに接続するためのオープン スタンダードです。エージェント フレームワークは MCP をサポートしています。つまり、エージェントは MCP 準拠のサーバーによって公開されているツールを使用できます。これにより、ファイル システム、データベース、API などへの扉がすべて標準化されたインターフェイスを通じて開かれます。
// Example: Adding an MCP server for file operations
kernel.Plugins.AddFromMcpServer("filesystem",
new Uri("http://localhost:3000/mcp"));
これは、エージェントがあなたが構築したものに限定されず、他の人が開発して共有している MCP ツールのエコシステムを利用できることを意味するため、特に興味深いものです。
実際の例: コンテンツ レビュー パイプライン
実践的なシナリオですべてをまとめてみましょう。ドキュメント チームのコンテンツ レビューを自動化する内部ツールを構築していると想像してください。パイプラインには 4 つのステージがあります。
- 研究者 — 関連する技術情報を収集します
- ライター — 調査に基づいて草稿を作成します
- レビュー担当者 — 正確さと完全性をチェックします
- 発行者 — 最終出力をフォーマットして準備します
要約された実装は次のとおりです。
using Azure.Identity;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.ChatCompletion;
// Build the kernel
var builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(
deploymentName: "gpt-4o",
endpoint: "https://your-resource.openai.azure.com/",
credentials: new DefaultAzureCredential()
);
Kernel kernel = builder.Build();
// Define specialized agents
ChatCompletionAgent researcher = new()
{
Name = "Researcher",
Instructions = """
You are a technical researcher. Given a topic, identify the key
concepts, recent developments, and important details that should
be covered. Output a structured research brief.
""",
Kernel = kernel
};
ChatCompletionAgent writer = new()
{
Name = "Writer",
Instructions = """
You are a technical writer. Using the research brief provided,
write a comprehensive, well-structured article. Include code
examples where relevant. Target audience: experienced developers.
""",
Kernel = kernel
};
ChatCompletionAgent reviewer = new()
{
Name = "Reviewer",
Instructions = """
You are a senior technical reviewer. Check the article for:
- Technical accuracy
- Completeness relative to the research brief
- Code correctness
- Clarity and structure
If everything looks good, respond with APPROVED.
Otherwise, provide specific feedback for revision.
""",
Kernel = kernel
};
ChatCompletionAgent publisher = new()
{
Name = "Publisher",
Instructions = """
You are a content publisher. Once the article is approved,
format it with proper markdown, add a summary at the top,
and ensure consistent formatting throughout.
End your response with COMPLETE.
""",
Kernel = kernel
};
// Configure the group chat
AgentGroupChat chat = new(researcher, writer, reviewer, publisher)
{
ExecutionSettings = new()
{
SelectionStrategy = new SequentialSelectionStrategy(),
TerminationStrategy = new ApprovalTerminationStrategy()
{
Agents = [publisher],
MaximumIterations = 15
}
}
};
// Start the pipeline
chat.AddChatMessage(new ChatMessageContent(
AuthorRole.User,
"Create a technical article about implementing health checks in ASP.NET Core microservices."
));
await foreach (ChatMessageContent message in chat.InvokeAsync())
{
Console.ForegroundColor = message.AuthorName switch
{
"Researcher" => ConsoleColor.Cyan,
"Writer" => ConsoleColor.Green,
"Reviewer" => ConsoleColor.Yellow,
"Publisher" => ConsoleColor.Magenta,
_ => ConsoleColor.White
};
Console.WriteLine($"\n{'='new string('=', 60)}");
Console.WriteLine($"[{message.AuthorName}]");
Console.WriteLine(new string('=', 60));
Console.WriteLine(message.Content);
}
Console.ResetColor();
このパイプラインは、エージェントの協力を通じて、完全に調査、執筆、レビュー、フォーマットされた記事を作成します。各エージェントは自分が最も得意とすることに集中し、AgentGroupChat がワークフローを調整します。
ベストプラクティス
いくつかのマルチエージェント システムを構築した後、私が最も価値があると感じたパターンと実践方法を次に示します。
エラー処理
終了戦略には常に MaximumIterations を設定してください。これがないと、エージェントは無限ループに陥る可能性があります。特に、レビュー担当者が問題を発見し続け、ライターが改善せずに改訂を続ける場合に発生します。
TerminationStrategy = new ApprovalTerminationStrategy()
{
MaximumIterations = 12 // Safety net
}
エージェントの呼び出しを try-catch ブロックでラップします。 API レート制限、ネットワークの問題、モデル エラーはすべて実稼働システムの現実です。
try
{
await foreach (var message in chat.InvokeAsync(cancellationToken))
{
// Process messages
}
}
catch (HttpOperationException ex) when (ex.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
{
// Implement retry with exponential backoff
await Task.Delay(TimeSpan.FromSeconds(30), cancellationToken);
}
可観測性Agent Framework は OpenTelemetry と統合されているため、エージェントのあらゆる対話、ツール呼び出し、トークンの使用状況を追跡できます。これは、どのエージェントが問題を引き起こしたかが必ずしも明らかではないマルチエージェント ワークフローをデバッグする場合に不可欠です。
セマンティック カーネル テレメトリ パッケージを追加し、優先エクスポーター (Application Insights、Jaeger など) を構成することにより、基本的なテレメトリをセットアップします。
builder.Services.AddOpenTelemetry()
.WithTracing(tracing =>
{
tracing.AddSource("Microsoft.SemanticKernel*");
tracing.AddOtlpExporter();
});
コスト管理
マルチエージェント システムでは API コストが倍増します。すべてのエージェント ターンは API 呼び出しであり、グループ チャットでは多くのターンが発生する可能性があります。コストを管理するためのいくつかの戦略:
- より単純なエージェントには安価なモデルを使用: すべてのエージェントが GPT-4o を必要とするわけではありません。レビュー担当者は小規模なモデルで問題なく機能する可能性がありますが、強力なモデルを必要とするのはライターだけです。
- 履歴を制限: 実行設定で
ReducedHistoryCountを使用して、各エージェントが受信する会話コンテキストの量を制限します。 - 厳格な反復制限を設定: 適切な
MaximumIterations値を使用して暴走した会話を防ぎます。 - 可能な場合はキャッシュ: エージェントが同じ検索を繰り返し実行する場合は、結果をプラグインにキャッシュします。
エージェントの設計
- 指示に重点を置く: 各エージェントは単一の明確な責任を負う必要があります。広範囲にわたる指示は、すべてのタスクにわたって平凡なパフォーマンスにつながります。
- 出力形式について明確にする: エージェントに応答の構成方法を正確に伝えます。これにより、ダウンストリーム解析の信頼性が高まります。
- 終了キーワードを使用する: エージェントが終了を示すために使用する明確なシグナル (「承認」や「完了」など) を定義します。これにより、終了戦略がシンプルかつ予測可能になります。
結論
マルチエージェント AI システムは、インテリジェント アプリケーションの構築方法における根本的な変化を表しています。単一のプロンプトですべてを処理するのではなく、問題を専門的な役割に分解し、エージェントが協力できるようにすることができます。
Microsoft の Agent Framework を使用すると、.NET 開発者にとってこれが実用的になります。エージェント、グループ チャット、選択と終了の戦略などの抽象化はクリーンであり、自然に構成されています。セマンティック カーネルのプラグイン エコシステムと Azure のモデル ホスティングを組み合わせることで、運用グレードのマルチエージェント システムを構築するためのフルスタックが得られます。
フレームワークはまだ進化中ですが (多くのパッケージはプレビュー段階です)、核となるパターンはしっかりしており、方向性は明確です。 .NET で AI を活用したアプリケーションを構築している場合は、今がマルチエージェント アーキテクチャの実験を開始する時期です。
小規模から始めて、単純なタスクで共同作業する 2 つのエージェントを構築します。単一エージェントのアプローチと比較して品質の向上が確認できたら、すべてをエージェント チームに分解したくなるでしょう。
コーディングを楽しんでください!