共用方式為


代理管線架構

Microsoft Agent Framework 中的代理程式採用分層管線架構來處理請求。 了解此架構有助於你透過在適當層級加入中介軟體、情境提供者或用戶端層級的修改,來自訂代理行為。

ChatClientAgent 管線

C# 代理管線架構

ChatClientAgent 建構出由三個主要層組成的管線:

  1. 代理中介軟體 - 選用的修飾器,可 .Use() 透過包裝代理進行日誌記錄、驗證或轉換
  2. 上下文層 - 管理聊天歷史ChatHistoryProvider()並注入額外的上下文(AIContextProviders
  3. 聊天用戶端層 —— IChatClient 配備可選的中介軟體裝飾器,負責大型語言模型通訊

當你呼叫 RunAsync()時,請求會依序通過每一層。

代理流程

Python 代理管線架構

Agent 類別透過類別組合建立一個管道,包含兩個主要部分:

代理人 (外部成分):

  1. 代理中介軟體 + 遙測——AgentMiddlewareLayerAgentTelemetryLayer 類別負責中介軟體調用與 OpenTelemetry 工具化
  2. RawAgent - 核心代理邏輯,呼叫上下文提供者並收集提供者新增的中介軟體
  3. 情境提供者 - 統一 context_providers 清單管理歷史、額外情境及每次執行的聊天/功能中介軟體

ChatClient (獨立且可互換的元件):

  1. FunctionInvocation - 處理工具呼叫迴圈,每次工具呼叫時調用函式中介軟體和進行遙測
  2. 聊天中介軟體 + 遙測 - 可選的中介軟體鏈與儀器層,包含上下文提供者新增的任何聊天中介軟體,依模型呼叫執行
  3. RawChatClient - 提供者專用實作(Azure OpenAI、OpenAI、Anthropic 等),與大型語言模型(Large Language Model, LLM)通訊

當你呼叫 run()時,你的請求會經過代理層,然後進入 ChatClient 管道進行 LLM 通訊。

代理中介軟體層

代理中介軟體會攔截每一次呼叫代理執行方法,讓你能檢查或修改輸入與輸出。

使用代理建構器模式新增中介軟體:

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

你也可以用 MessageAIContextProvider 代理中介軟體在請求中注入額外訊息。 這適用於任何代理類型,而不僅限於 ChatClientAgent

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

此層包覆整個代理執行,包括上下文解析與聊天客戶端通話。 這有其優點,因為這些裝飾器可以搭配任何類型的代理使用,例如 A2AAgent ,或 GitHubCopilotAgent,而不僅僅是 ChatClientAgent。 這也意味著此層級的裝飾器無法對其所裝飾的代理對象做出假設,這意味著其僅限於客製化或影響通用功能。

建立代理時新增中介軟體:

from agent_framework import Agent

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

Agent 類別繼承自 AgentMiddlewareLayer,它負責處理中介軟體的調用,然後再委派至核心代理邏輯。 它也繼承自 AgentTelemetryLayer,負責傳送 span、事件與指標到已設定的 OpenTelemetry 後端。 這兩層如果沒設定好,都沒什麼作用。

如需詳細的中介軟體與可觀察性模式,請參見 代理中介軟體可觀察性。

上下文層

上下文層會在每次 LLM 呼叫前執行,建立完整的訊息歷史並注入額外的上下文。

ChatClientAgent 有兩種不同的提供者類型:

  • ChatHistoryProvider (單人) - 管理對話紀錄的儲存與檢索
  • 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()中。 代理程式在進入 ChatClient 管道之前,會依提供者順序展平這些新增內容。

欲了解詳細的情境提供者模式,請參見 情境提供者

聊天用戶端層

聊天客戶端層負責處理與大型語言模型服務的實際通訊。

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.")

RawChatClient ChatClient 內部實作了提供者專屬邏輯,用於與不同 LLM 服務溝通。

執行流程

當你呼叫代理時,請求會透過管線流動:

  1. 代理中介軟體執行(若已設定)
  2. ChatHistoryProvider 會將對話歷史載入請求訊息清單
  3. AIContextProviders 會在請求中加入訊息、工具或指示
  4. IChatClient 中介軟體 執行(如果有裝飾)
  5. IChatClient 會將請求傳送給 LLM
  6. 回應會流經相同的層次
  7. ChatHistoryProviderAIContextProviders 會收到新訊息通知

代理流程:

  1. 代理中介軟體 + 遙測執行 中介軟體(若已設定),並記錄跨度
  2. RawAgent 會呼叫上下文提供者來載入歷史、新增上下文,並收集提供者新增的聊天/功能中介軟體
  3. 請求會轉交給聊天客戶端

ChatClient 流程:

  1. FunctionInvocation 管理工具呼叫迴圈
    • 每次工具呼叫都會執行 Function Middleware + Telemetry ,包括由上下文提供者新增的任何函式中介軟體
  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 不使用本地聊天客戶端,聊天客戶端中介軟體仍然不適用。

下一步