次の方法で共有


エージェント パイプラインのアーキテクチャ

Microsoft Agent Framework のエージェントは、階層化されたパイプライン アーキテクチャを使用して要求を処理します。 このアーキテクチャを理解すると、ミドルウェア、コンテキスト プロバイダー、またはクライアント レベルの変更を適切なレイヤーに追加することで、エージェントの動作をカスタマイズできます。

ChatClientAgent パイプライン

C# エージェント パイプライン のアーキテクチャ

ChatClientAgentは、次の 3 つの主要なレイヤーを持つパイプラインを構築します。

  1. エージェント ミドルウェア - ログ記録、検証、または変換のために .Use() を介してエージェントをラップするオプションのデコレーター
  2. コンテキスト レイヤー - チャット履歴 (ChatHistoryProvider) を管理し、追加のコンテキスト (AIContextProviders) を挿入します
  3. チャット クライアント レイヤー - LLM 通信を処理するオプションのミドルウェア デコレーターを含むIChatClient

RunAsync()を呼び出すと、要求は各レイヤーを順番に流れます。

エージェント パイプライン

Python エージェント パイプライン のアーキテクチャ

Agent クラスは、2 つの主要なコンポーネントを含むクラスコンポジションを通じてパイプラインを構築します。

エージェント (外部コンポーネント):

  1. エージェント ミドルウェアとテレメトリ - AgentMiddlewareLayer クラスと AgentTelemetryLayer クラスがミドルウェア呼び出しと OpenTelemetry インストルメンテーションを処理します
  2. RawAgent - コンテキスト プロバイダーを呼び出し、プロバイダーによって追加されたミドルウェアを収集するコア エージェント ロジック
  3. コンテキスト プロバイダー - 統合 context_providers リストは、履歴、追加のコンテキスト、および実行ごとのチャット/関数ミドルウェアを管理します

ChatClient (独立した交換可能なコンポーネント):

  1. FunctionInvocation - ツール呼び出しループを処理し、関数ミドルウェアとツール呼び出しごとのテレメトリを呼び出します
  2. チャット ミドルウェア + テレメトリ - 省略可能なミドルウェア チェーンとインストルメンテーション レイヤー (コンテキスト プロバイダーによって追加されたチャット ミドルウェアを含む)、モデル呼び出しごとに実行される
  3. RawChatClient - LLM と通信するプロバイダー固有の実装 (Azure OpenAI、OpenAI、Anthropic など)

run()を呼び出すと、要求はエージェント レイヤーを経由し、LLM 通信のために ChatClient パイプラインに送信されます。

エージェント ミドルウェア レイヤー

エージェント ミドルウェアは、エージェントの実行メソッドに対するすべての呼び出しをインターセプトし、入力と出力を検査または変更できるようにします。

エージェント ビルダー パターンを使用してミドルウェアを追加します。

var middlewareAgent = originalAgent
    .AsBuilder()
    .Use(runFunc: MyAgentMiddleware, runStreamingFunc: MyStreamingMiddleware)
    .Build();

MessageAIContextProviderをエージェント ミドルウェアとして使用して、要求に追加のメッセージを挿入することもできます。 これは、 ChatClientAgentだけでなく、任意のエージェントの種類で機能します。

var contextAgent = originalAgent
    .AsBuilder()
    .UseAIContextProviders(new MyMessageContextProvider())
    .Build();

このレイヤーは、コンテキスト解決やチャット クライアント呼び出しなど、エージェントの実行全体をラップします。 これには利点があります。これらのデコレーターは、A2AAgentだけでなく、GitHubCopilotAgentChatClientAgentなど、あらゆる種類のエージェントで使用できます。 つまり、このレベルのデコレーターは、必ずしも、装飾するエージェントに関して前提を立てることはできません。つまり、一般的な機能のカスタマイズまたは影響に限定されます。

エージェントの作成時にミドルウェアを追加します。

from agent_framework import Agent

agent = Agent(
    client=my_client,
    instructions="You are helpful.",
    middleware=[my_middleware_func],
)

Agent クラスは、コア エージェント ロジックに委任する前にミドルウェアの呼び出しを処理するAgentMiddlewareLayerから継承します。 また、構成された OpenTelemetry バックエンドへのスパン、イベント、メトリックの出力を処理する AgentTelemetryLayer も継承します。 これらの両方のレイヤーは、構成されていない場合は何も行いません。

ミドルウェアと可観測性のパターンの詳細については、 エージェント ミドルウェア可観測性に関する記事を参照してください。

コンテキスト レイヤー

コンテキスト レイヤーは、各 LLM 呼び出しの前に実行され、完全なメッセージ履歴を構築し、追加のコンテキストを挿入します。

ChatClientAgent には、2 つの異なるプロバイダーの種類があります。

  • ChatHistoryProvider (1) - 会話履歴の保存と取得を管理します
  • AIContextProviders (リスト) - メモリ、取得されたドキュメント、動的命令などの追加のコンテキストを挿入します
var agent = new ChatClientAgent(chatClient, new ChatClientAgentOptions
{
    ChatHistoryProvider = new InMemoryChatHistoryProvider(),
    AIContextProviders = [new MyMemoryProvider(), new MyRagProvider()],
});

エージェントは、各プロバイダーの出力が次のプロバイダーに入力として渡された状態でチャット クライアントにメッセージを送信する前に、各プロバイダーの InvokingAsync() メソッドを呼び出します。

Agent クラスは、履歴プロバイダーとコンテキスト プロバイダーの両方を含めることができる統合context_providers リストを使用します。

from agent_framework import Agent, InMemoryHistoryProvider

agent = Agent(
    client=my_client,
    context_providers=[
        InMemoryHistoryProvider(),
        MyMemoryProvider(),
        MyRagProvider(),
    ],
)

コンテキスト プロバイダーは、 SessionContext.extend_middleware()を介してチャットまたは関数ミドルウェアを 1 つの呼び出しにアタッチすることもできます。 エージェントは、ChatClient パイプラインに入る前に、これらの追加をプロバイダーの順序でフラット化します。

コンテキスト プロバイダーのパターンの詳細については、「 コンテキスト プロバイダー」を参照してください。

チャット クライアント レイヤー

チャット クライアント レイヤーは、LLM サービスとの実際の通信を処理します。

ChatClientAgent では、追加のミドルウェアで修飾できる IChatClient インスタンスが使用されます。

var chatClient = new AIProjectClient(endpoint, credential)
    .GetProjectOpenAIClient()
    .GetProjectResponsesClient()
    .AsIChatClient(deploymentName)
    .AsBuilder()
    .Use(CustomChatClientMiddleware)
    .Build();

var agent = new ChatClientAgent(chatClient, instructions: "You are helpful.");

AIContextProviderをチャット クライアント ミドルウェアとして使用して、クライアント レベルでメッセージ、ツール、および命令を強化することもできます。 これは、実行中の AIAgentのコンテキスト内で使用する必要があります。

var chatClient = new AIProjectClient(endpoint, credential)
    .GetProjectOpenAIClient()
    .GetProjectResponsesClient()
    .AsIChatClient(deploymentName)
    .AsBuilder()
    .UseAIContextProviders(new MyContextProvider())
    .Build();

var agent = new ChatClientAgent(chatClient, instructions: "You are helpful.");

既定では、 ChatClientAgent は、提供されたチャット クライアントを関数呼び出しのサポートでラップします。 この既定の折り返しをスキップするには、オプションに UseProvidedChatClientAsIs = true を設定します。

Agent クラスは、SupportsChatGetResponseを実装するすべてのクライアントを受け入れます。 ChatClient パイプラインは、ミドルウェア、テレメトリ、関数呼び出し、プロバイダー固有の通信を処理します。

from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient

client = FoundryChatClient(
    credential=credential,
    project_endpoint=endpoint,
    model=model,
)

agent = Agent(client=client, instructions="You are helpful.")

ChatClient 内の RawChatClient は、さまざまな LLM サービスと通信するためのプロバイダー固有のロジックを実装します。

実行フロー

エージェントを呼び出すと、要求はパイプラインを通過します。

  1. エージェント ミドルウェア が実行される (構成されている場合)
  2. ChatHistoryProvider が会話履歴を要求メッセージ一覧に読み込む
  3. AIContextProviders が 要求にメッセージ、ツール、または命令を追加する
  4. IChatClient ミドルウェア が実行される (装飾されている場合)
  5. IChatClient が LLM に要求を送信する
  6. 応答は同じレイヤーを通って戻ります
  7. ChatHistoryProviderAIContextProviders に新しいメッセージが通知される

エージェント パイプライン:

  1. エージェント ミドルウェア + テレメトリ はミドルウェア(構成されている場合)を実行し、スパンを記録する。
  2. RawAgent によってコンテキスト プロバイダーが呼び出され、履歴の読み込み、コンテキストの追加、プロバイダーによって追加されたチャット/関数ミドルウェアの収集が行われます
  3. 要求が ChatClient に渡される

ChatClient パイプライン:

  1. FunctionInvocation は 、ツール呼び出しループを管理します
    • ツール呼び出しごとに、 関数ミドルウェアとテレメトリが 実行されます。これには、コンテキスト プロバイダーによって追加されたすべての関数ミドルウェアが含まれます
  2. チャット ミドルウェア + テレメトリは 、コンテキスト プロバイダーによって追加されたチャット ミドルウェアを含め、モデル呼び出し (構成されている場合) ごとに実行されます
  3. RawChatClient が プロバイダー固有の LLM 通信を処理する
  4. 応答は同じレイヤーを通って戻ります
  5. コンテキスト プロバイダーには、 ストレージの新しいメッセージが通知されます

特殊化されたエージェントは、ここで説明するパイプラインとは動作が異なる場合があります。

その他のエージェントの種類

すべてのエージェントが完全な ChatClientAgent パイプラインを使用するわけではありません。 A2AAgentGitHubCopilotAgentCopilotStudioAgentなどのエージェントは、ローカル IChatClientを使用するのではなく、リモート サービスと通信します。 ただし、エージェント レベルのミドルウェアは引き続きサポートされます。

他のエージェントタイプのパイプライン

これらのエージェントは AIAgentから派生しているため、同じエージェント ミドルウェア パターンを使用できます。

// Agent middleware works with any AIAgent
var a2aAgent = originalA2AAgent
    .AsBuilder()
    .Use(runFunc: LoggingMiddleware)
    .UseAIContextProviders(new MyMessageContextProvider())
    .Build();

// Same pattern works for GitHubCopilotAgent
var copilotAgent = originalCopilotAgent
    .AsBuilder()
    .Use(runFunc: AuditMiddleware)
    .Build();

チャット クライアント ミドルウェアは、 IChatClientを使用しないため、これらのエージェントに追加できません。

その他のエージェントの種類

すべての Python エージェントが完全な Agent + ChatClient パイプラインを使用するわけではありません。 GitHubCopilotAgentたとえば、ローカル チャット クライアントではなく GitHub Copilot CLI を介して要求を送信します。

それでも、Python GitHubCopilotAgent は引き続きエージェント ミドルウェアをサポートし、各呼び出し context_providers 実行されるようになりました。 プロバイダーが追加したメッセージと命令は、Copilot に送信されるプロンプトに含まれており、応答が使用可能になると、プロバイダーは一致する after_run コールバックを受け取ります。

GitHubCopilotAgentはローカル チャット クライアントを使用しないため、チャット クライアント ミドルウェアは引き続き適用されません。

次のステップ