Arquitetura de pipeline de agente

Os agentes do Microsoft Agent Framework usam uma arquitetura de pipeline em camadas para processar solicitações. Entender essa arquitetura ajuda você a personalizar o comportamento do agente adicionando middleware, provedores de contexto ou modificações no nível do cliente na camada apropriada.

ChatClientAgent Pipeline

Arquitetura de pipeline do agente C#

ChatClientAgent constrói um pipeline com três camadas principais:

  1. Middleware do agente – decoradores opcionais que encapsulam o agente para .Use() registro em log, validação ou transformação
  2. Camada de contexto – gerencia o histórico de chat (ChatHistoryProvider) e injeta contexto adicional (AIContextProviders)
  3. Camada de cliente de chat – O IChatClient com decoradores opcionais de middleware que lidam com a comunicação LLM

Quando você chama RunAsync(), sua solicitação flui por cada camada em sequência.

Pipeline do Agente

Arquitetura de pipeline do Python Agent

A classe Agent constrói um pipeline por meio da composição de classes com dois componentes principais:

Agente (componente externo):

  1. Middleware do Agente + Telemetria – as classes AgentMiddlewareLayer e AgentTelemetryLayer lidam com a invocação de middleware e a instrumentação OpenTelemetry
  2. RawAgent – Lógica do agente principal que invoca provedores de contexto e coleta middleware adicionado pelo provedor
  3. Provedores de Contexto – Lista unificada context_providers gerencia histórico, contexto adicional e middleware para chat e funções em cada execução

ChatClient (componente separado e intercambiável):

  1. FunctionInvocation – Manipula o loop de chamadas de ferramenta, invocando Middleware de Função + Telemetria por chamada de ferramenta
  2. Middleware de chat + Telemetria – camadas opcionais de middleware e de cadeia de instrumentação, incluindo qualquer middleware de chat adicionado por fornecedores de contexto, executado por chamada de modelo
  3. RawChatClient – Implementação específica do provedor (Azure OpenAI, OpenAI, Antropic etc.) que se comunica com o LLM

Quando você chama run(), sua solicitação flui pelas camadas do Agente e, em seguida, entra no pipeline do ChatClient para comunicação com LLM.

Arquitetura de pipeline de agente

Arquitetura do pipeline do Go Agent

No Go, os agentes usam um pipeline de middleware em camadas. Middlewares encapsulam a função do agente Run, cada um chamando next para passar o controle para a próxima camada.

Quando um agente é executado, seu ciclo de vida é aplicado nesta ordem:

  1. Middleware personalizado do agente - seu middleware registrado agent.Config.Middlewares, aplicado na ordem de declaração em todo o ciclo de vida do agente
  2. Provedor de histórico – Carrega mensagens anteriores e, posteriormente, armazena mensagens de solicitação/resposta
  3. Provedores de contexto - Injeta contexto, opções e estado de instâncias agent.ContextProvider registradas
  4. Middleware do provedor – middleware registrado pelo provedor, como chamada automática de ferramenta, saídas estruturadas e criação de resposta
  5. Provedor - O provedor de LLM subjacente, como OpenAI ou Anthropic

Camada de middleware do agente

O middleware do agente intercepta todas as chamadas para o método de execução do agente, permitindo que você inspecione ou modifique entradas e saídas.

Adicione middleware usando o padrão do construtor de agentes:

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

Você também pode usar MessageAIContextProvider como middleware de agente para injetar mensagens adicionais na solicitação. Isso funciona com qualquer tipo de agente, não apenas ChatClientAgent:

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

Essa camada encapsula toda a execução do agente, incluindo resolução de contexto e chamadas de cliente de chat. Isso tem benefícios, porque esses decoradores podem ser usados com qualquer tipo de agente, por exemplo A2AAgent , ou GitHubCopilotAgent, não apenas ChatClientAgent. Isso também significa que os decoradores nesse nível não podem necessariamente fazer suposições sobre o agente que eles estão decorando, o que significa que eles estão restritos a personalizar ou afetar a funcionalidade comum.

Adicione middleware ao criar o agente:

from agent_framework import Agent

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

A classe Agent herda de AgentMiddlewareLayer, que gerencia a invocação das funções de middleware antes de delegar para a lógica central do agente. Ele também herda do AgentTelemetryLayer, que lida com a emissão de intervalos, eventos e métricas para um back-end OpenTelemetry configurado. Essas duas camadas não fazem nada quando não estão configuradas.

Adicione middleware implementando a interface Middleware ou usando agent.MiddlewareFunc para middleware leve:

type Middleware interface {
    Run(next RunFunc, ctx context.Context, messages []*message.Message,
        options ...agent.Option) iter.Seq2[*agent.ResponseUpdate, error]
}

Cada middleware recebe a função next na cadeia e pode modificar mensagens ou opções antes de chamar next, processar respostas após chamar next ou interromper o pipeline.

timing := agent.MiddlewareFunc(
    func(next agent.RunFunc, ctx context.Context, messages []*message.Message, options ...agent.Option) iter.Seq2[*agent.ResponseUpdate, error] {
        start := time.Now()
        return func(yield func(*agent.ResponseUpdate, error) bool) {
            defer log.Printf("agent run completed in %s", time.Since(start))
            for update, err := range next(ctx, messages, options...) {
                if !yield(update, err) {
                    return
                }
            }
        }
    },
)

a := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
    Config: agent.Config{
        Middlewares: []agent.Middleware{timing},
    },
})

Para obter padrões detalhados de middleware e observabilidade, consulte Middleware do Agente e Observabilidade.

Camada de contexto

A camada de contexto é executada antes de cada chamada LLM para criar o histórico de mensagens completo e injetar contexto adicional.

ChatClientAgent tem dois tipos de provedor distintos:

  • ChatHistoryProvider (único) – Gerencia o armazenamento e a recuperação do histórico de conversas
  • AIContextProviders (lista) - Injeta contexto adicional, como memórias, documentos recuperados ou instruções dinâmicas
var agent = new ChatClientAgent(chatClient, new ChatClientAgentOptions
{
    ChatHistoryProvider = new InMemoryChatHistoryProvider(),
    AIContextProviders = [new MyMemoryProvider(), new MyRagProvider()],
});

O agente invoca o método de cada provedor antes de enviar mensagens para o cliente de chat, fazendo com que a saída de cada provedor seja passada como entrada para o próximo provedor.

A Agent classe usa uma lista unificada context_providers que pode incluir provedores de histórico e provedores de contexto:

from agent_framework import Agent, InMemoryHistoryProvider

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

Os provedores de contexto também podem anexar o middleware de chat ou função a uma única invocação por meio de SessionContext.extend_middleware(). O agente nivela essas adições na ordem do provedor antes de entrar no pipeline do ChatClient.

Os provedores de contexto são executados dentro do ciclo de vida do agente depois que o middleware personalizado entrou na execução e antes que o middleware do provider chame o modelo. Os provedores de contexto podem adicionar mensagens ou opções antes da chamada do provedor e manter o estado após a execução.

a := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
    Config: agent.Config{
        ContextProviders: []agent.ContextProvider{memoryProvider},
    },
})

Para obter padrões detalhados do provedor de contexto, consulte Provedores de Contexto.

Camada de cliente de chat

A camada de cliente de chat manipula a comunicação real com o serviço LLM.

ChatClientAgent usa uma IChatClient instância, que pode ser decorada com middleware adicional:

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

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

Você também pode usar AIContextProvider como middleware de cliente de chat para enriquecer mensagens, ferramentas e instruções no nível do cliente. Isso deve ser usado no contexto de um AIAgent em execução:

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

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

Por padrão, ChatClientAgent encapsula o cliente de chat fornecido com suporte para chamadas de funções. Defina UseProvidedChatClientAsIs = true nas opções para ignorar esse encapsulamento padrão.

A Agent classe aceita qualquer cliente que implemente SupportsChatGetResponse. O pipeline do ChatClient manipula middleware, telemetria, invocação de funções e comunicação específica do provedor.

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

O RawChatClient do ChatClient implementa a lógica específica do provedor para se comunicar com diferentes serviços LLM.

O middleware do provedor é executado após os provedores de histórico e de contexto, imediatamente antes do provedor de LLM subjacente. Recursos auxiliares no nível do agente, como OpenTelemetry e registro de execução, são registrados como middleware personalizado do agente e envolvem as etapas anteriores do ciclo de vida.

Componente Registration Camada Purpose
Chamada automática agent/harness/toolautocall Middleware do provedor Invoca automaticamente ferramentas de função
Saída estruturada agent.WithStructuredOutput Middleware de provedor Lida com a análise sintática de saída estruturada
OpenTelemetry provider/otelprovider Middleware do agente Rastreia invocações de agente
Executar registrador agent.Config.Logger Middleware do agente Registra as interações do agente

agent.ContextProvider os valores são componentes do ciclo de vida em vez de agent.Middleware implementações. Eles são executados entre o middleware de agente personalizado e o middleware de provedor.

Fluxo de execução

Quando você invoca um agente, a solicitação flui pelo pipeline:

  1. O middleware do agente é executado (se configurado)
  2. ChatHistoryProvider carrega o histórico de conversas na lista de mensagens de solicitação
  3. AIContextProviders adicionam mensagens, ferramentas ou instruções à solicitação
  4. O middleware IChatClient executa (caso esteja decorado)
  5. O IChatClient envia a solicitação para a LLM
  6. A resposta flui de volta pelas mesmas camadas
  7. ChatHistoryProvider e AIContextProviders são notificados sobre novas mensagens

Pipeline do agente:

  1. Middleware do Agente + Telemetria executa o middleware (se configurado) e registra spans
  2. RawAgent invoca provedores de contexto para carregar o histórico, adicionar contexto e coletar middleware de chat/função adicionado pelo provedor
  3. A solicitação é passada para o ChatClient

Pipeline do ChatClient:

  1. FunctionInvocation gerencia o loop de chamada da ferramenta
    • Para cada chamada de ferramenta, o Middleware de Função + Telemetria é executado, incluindo qualquer middleware de função adicionado por provedores de contexto
  2. Middleware de Chat + Telemetria é executado a cada chamada de modelo (se configurado), incluindo middleware de chat que tenha sido adicionado por provedores de contexto.
  3. RawChatClient gerencia a comunicação LLM específica do provedor
  4. A resposta flui de volta pelas mesmas camadas
  5. Os provedores de contexto são notificados sobre novas mensagens para armazenamento

Observação

Agentes especializados podem operar de forma diferente do pipeline descrito aqui.

  1. O middleware do agente personalizado é executado primeiro e encapsula o ciclo de vida completo do agente.
  2. O provedor de histórico carrega o histórico de conversas para a sessão atual quando o histórico local está ativo.
  3. Os provedores de contexto adicionam mensagens, opções ou estado antes da chamada do provedor.
  4. O middleware do provedor é executado, incluindo o middleware de chamada automática de ferramentas e o tratamento de saída estruturada, quando habilitado.
  5. O provedor envia a solicitação para o modelo.
  6. As atualizações de resposta fluem de volta por meio do middleware do provedor e do middleware do agente personalizado.
  7. Provedores de histórico e provedores de contexto armazenam o estado de resposta após uma execução bem-sucedida.

Outros tipos de agente

Nem todos os agentes utilizam a totalidade do ChatClientAgent pipeline. Agentes como A2AAgent, GitHubCopilotAgentou CopilotStudioAgent se comunicam com serviços remotos em vez de usar um local IChatClient. No entanto, eles ainda dão suporte ao middleware no nível do agente.

Pipeline de tipos de agentes diversos

Como esses agentes derivam de AIAgent, você pode usar os mesmos padrões de middleware de agente:

// 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();

Observação

Você não pode adicionar middleware de cliente de chat a esses agentes porque eles não usam IChatClient.

Outros tipos de agente

Nem todo agente do Python usa o pipeline completo Agent + ChatClient . GitHubCopilotAgent, por exemplo, envia solicitações por meio da CLI do GitHub Copilot em vez de um cliente de chat local.

Mesmo assim, o Python GitHubCopilotAgent ainda oferece suporte ao middleware do agente e agora executa context_providers em volta de cada invocação. As mensagens e instruções adicionadas pelo provedor são incluídas no prompt enviado ao Copilot e os provedores recebem o retorno de chamada correspondente after_run quando uma resposta está disponível.

Observação

Como GitHubCopilotAgent não usa um cliente de chat local, o middleware do cliente de chat ainda não se aplica.

Próximas Etapas