Compartir a través de


Orquestaciones de flujos de trabajo de Microsoft Agent Framework: secuencial

En la orquestación secuencial, los agentes se organizan en una tubería. Cada agente procesa la tarea a su vez, pasando su salida al siguiente agente de la secuencia. Esto es ideal para los flujos de trabajo en los que cada paso se basa en el anterior, como la revisión de documentos, las canalizaciones de procesamiento de datos o el razonamiento de varias fases.

Orquestación secuencial

Temas que se abordarán

  • Creación de una canalización secuencial de agentes
  • Cómo encadenar agentes en la que cada uno se basa en el resultado anterior
  • Cómo mezclar agentes con ejecutores personalizados para tareas especializadas
  • Cómo realizar el seguimiento del flujo de conversación a través de la canalización

Definir los agentes

En la orquestación secuencial, los agentes se organizan en una canalización en la que cada agente procesa la tarea a su vez, pasando la salida al siguiente agente de la secuencia.

Configuración del cliente de Azure OpenAI

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Extensions.AI;
using Microsoft.Agents.AI;

// 1) Set up the Azure OpenAI client
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ??
    throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
var client = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
    .GetChatClient(deploymentName)
    .AsIChatClient();

Cree agentes especializados que funcionen en secuencia:

// 2) Helper method to create translation agents
static ChatClientAgent GetTranslationAgent(string targetLanguage, IChatClient chatClient) =>
    new(chatClient,
        $"You are a translation assistant who only responds in {targetLanguage}. Respond to any " +
        $"input by outputting the name of the input language and then translating the input to {targetLanguage}.");

// Create translation agents for sequential processing
var translationAgents = (from lang in (string[])["French", "Spanish", "English"]
                         select GetTranslationAgent(lang, client));

Configurar la orquestación secuencial

Compile el flujo de trabajo mediante AgentWorkflowBuilder:

// 3) Build sequential workflow
var workflow = AgentWorkflowBuilder.BuildSequential(translationAgents);

Ejecución del flujo de trabajo secuencial

Ejecute el flujo de trabajo y procese los eventos:

// 4) Run the workflow
var messages = new List<ChatMessage> { new(ChatRole.User, "Hello, world!") };

StreamingRun run = await InProcessExecution.StreamAsync(workflow, messages);
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));

List<ChatMessage> result = new();
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
{
    if (evt is AgentRunUpdateEvent e)
    {
        Console.WriteLine($"{e.ExecutorId}: {e.Data}");
    }
    else if (evt is WorkflowOutputEvent outputEvt)
    {
        result = (List<ChatMessage>)outputEvt.Data!;
        break;
    }
}

// Display final result
foreach (var message in result)
{
    Console.WriteLine($"{message.Role}: {message.Content}");
}

Salida de ejemplo

French_Translation: User: Hello, world!
French_Translation: Assistant: English detected. Bonjour, le monde !
Spanish_Translation: Assistant: French detected. ¡Hola, mundo!
English_Translation: Assistant: Spanish detected. Hello, world!

Conceptos clave

  • Procesamiento secuencial: cada agente procesa la salida del agente anterior en orden
  • AgentWorkflowBuilder.BuildSequential(): crea un flujo de trabajo de canalización a partir de una colección de agentes.
  • ChatClientAgent: representa un agente respaldado por un cliente de chat con instrucciones específicas.
  • StreamingRun: proporciona ejecución en tiempo real con funcionalidades de streaming de eventos
  • Control de eventos: supervisar el progreso del agente a través de AgentRunUpdateEvent y su finalización a través de WorkflowOutputEvent

En la orquestación secuencial, cada agente procesa la tarea a su vez, con la salida que fluye de una a la siguiente. Comencemos definiendo agentes para un proceso de dos fases:

from agent_framework.azure import AzureChatClient
from azure.identity import AzureCliCredential

# 1) Create agents using AzureChatClient
chat_client = AzureChatClient(credential=AzureCliCredential())

writer = chat_client.create_agent(
    instructions=(
        "You are a concise copywriter. Provide a single, punchy marketing sentence based on the prompt."
    ),
    name="writer",
)

reviewer = chat_client.create_agent(
    instructions=(
        "You are a thoughtful reviewer. Give brief feedback on the previous assistant message."
    ),
    name="reviewer",
)

Configurar la orquestación secuencial

La SequentialBuilder clase crea una canalización donde los agentes procesan las tareas en orden. Cada agente ve el historial de conversaciones completo y agrega su respuesta:

from agent_framework import SequentialBuilder

# 2) Build sequential workflow: writer -> reviewer
workflow = SequentialBuilder().participants([writer, reviewer]).build()

Ejecución del flujo de trabajo secuencial

Ejecute el flujo de trabajo y recopile la conversación final que muestra la contribución de cada agente:

from agent_framework import ChatMessage, WorkflowOutputEvent

# 3) Run and print final conversation
output_evt: WorkflowOutputEvent | None = None
async for event in workflow.run_stream("Write a tagline for a budget-friendly eBike."):
    if isinstance(event, WorkflowOutputEvent):
        output_evt = event

if output_evt:
    print("===== Final Conversation =====")
    messages: list[ChatMessage] | Any = output_evt.data
    for i, msg in enumerate(messages, start=1):
        name = msg.author_name or ("assistant" if msg.role == Role.ASSISTANT else "user")
        print(f"{'-' * 60}\n{i:02d} [{name}]\n{msg.text}")

Salida de ejemplo

===== Final Conversation =====
------------------------------------------------------------
01 [user]
Write a tagline for a budget-friendly eBike.
------------------------------------------------------------
02 [writer]
Ride farther, spend less—your affordable eBike adventure starts here.
------------------------------------------------------------
03 [reviewer]
This tagline clearly communicates affordability and the benefit of extended travel, making it
appealing to budget-conscious consumers. It has a friendly and motivating tone, though it could
be slightly shorter for more punch. Overall, a strong and effective suggestion!

Avanzado: Mezcla de agentes con ejecutores personalizados

La orquestación secuencial admite la combinación de agentes con ejecutores personalizados para el procesamiento especializado. Esto resulta útil cuando se necesita lógica personalizada que no requiera un LLM:

Definir un ejecutor personalizado

from agent_framework import Executor, WorkflowContext, handler
from agent_framework import ChatMessage, Role

class Summarizer(Executor):
    """Simple summarizer: consumes full conversation and appends an assistant summary."""

    @handler
    async def summarize(
        self,
        conversation: list[ChatMessage],
        ctx: WorkflowContext[list[ChatMessage]]
    ) -> None:
        users = sum(1 for m in conversation if m.role == Role.USER)
        assistants = sum(1 for m in conversation if m.role == Role.ASSISTANT)
        summary = ChatMessage(
            role=Role.ASSISTANT,
            text=f"Summary -> users:{users} assistants:{assistants}"
        )
        await ctx.send_message(list(conversation) + [summary])

Creación de un flujo de trabajo secuencial mixto

# Create a content agent
content = chat_client.create_agent(
    instructions="Produce a concise paragraph answering the user's request.",
    name="content",
)

# Build sequential workflow: content -> summarizer
summarizer = Summarizer(id="summarizer")
workflow = SequentialBuilder().participants([content, summarizer]).build()

Salida de ejemplo con Ejecutor personalizado

------------------------------------------------------------
01 [user]
Explain the benefits of budget eBikes for commuters.
------------------------------------------------------------
02 [content]
Budget eBikes offer commuters an affordable, eco-friendly alternative to cars and public transport.
Their electric assistance reduces physical strain and allows riders to cover longer distances quickly,
minimizing travel time and fatigue. Budget models are low-cost to maintain and operate, making them accessible
for a wider range of people. Additionally, eBikes help reduce traffic congestion and carbon emissions,
supporting greener urban environments. Overall, budget eBikes provide cost-effective, efficient, and
sustainable transportation for daily commuting needs.
------------------------------------------------------------
03 [assistant]
Summary -> users:1 assistants:1

Conceptos clave

  • Contexto compartido: cada participante recibe el historial de conversaciones completo, incluidos todos los mensajes anteriores.
  • Order Matters: los agentes se ejecutan estrictamente en el orden especificado en la participants() lista
  • Participantes flexibles: puede mezclar agentes y ejecutores personalizados en cualquier orden
  • Flujo de conversación: cada agente o ejecutor se anexa a la conversación y crea un diálogo completo.

Pasos siguientes