Extensão Duradoura

A Durable Extension for Microsoft Agent Framework traz execução duradoura a agentes, orquestrações multi-agente e fluxos de trabalho do Microsoft Agent Framework. Pode usá-lo para persistir sessões de agentes, orquestração de checkpoints e progresso de fluxos de trabalho, recuperar de falhas e escalar trabalho entre hosts distribuídos sem alterar a lógica principal do seu agente.

A extensão suporta dois modelos de alojamento em C# e Python:

  • Funções do Azure para alojamento gerido e serverless com o modelo de programação Funções do Azure.
  • Traga a sua própria computação / self-hosted para executar agentes e fluxos de trabalho duráveis no seu próprio processo de trabalho, serviço, contentor, ambiente Kubernetes ou infraestrutura de aplicação existente.

Overview

Agentes Duráveis combinam o modelo de programação do Agent Framework com a infraestrutura de Tarefas Duradouras, como o Durable Task Scheduler, para criar agentes que:

  • Persiste o estado automaticamente entre pedidos e execuções de trabalhadores
  • Retome após falhas sem perder o contexto da conversa ou repetir o trabalho concluído
  • Escala entre trabalhadores distribuídos e apátridas com base na procura
  • Orquestre fluxos de trabalho multi-agente com garantias de execução fiáveis
  • Fluxos de trabalho do Checkpoint Agent Framework construídos com o modelo de workflow baseado em grafos
  • Pausa para entrada humana ou eventos externos sem consumir tokens de computação ou modelo enquanto espera
  • Respostas de stream de forma fiável quando configuradas com um broker de stream fiável, como o Redis
  • Gerir o ciclo de vida da sessão com limpeza de tempo para viver (TTL) da sessão e monitorização baseada em dashboards

Quando usar agentes duráveis

Escolha agentes duráveis quando precisar:

  • Estado de conversa persistente: As sessões do agente sobrevivem a falhas de processos, reinicios e eventos de escalonamento
  • Orquestrações complexas: coordene vários agentes com fluxos de trabalho determinísticos e confiáveis que podem ser executados por dias ou semanas
  • Orquestração orientada a eventos: Integrar com triggers, filas, webhooks, temporizadores ou eventos de aplicação existentes
  • Estado de conversação automático: o histórico de conversas do agente é automaticamente gerido e persistido sem exigir um tratamento explícito do estado no seu código
  • <>fluxos de trabalho do Durable Agent Framework: Tornar os fluxos de trabalho do Agent Framework baseados em grafos Microsoft duráveis para que cada etapa possa ser checkpoint e retomada
  • Sessões de longa duração: Mantenha conversas úteis disponíveis enquanto utiliza a limpeza TTL (session time-to-live) para remover automaticamente sessões ociosas
  • Respostas fiáveis em tempo real: Transmita a saída de tokens de forma durável para aplicações que necessitam de UX em tempo real com garantias de entrega

Esta abordagem de alojamento difere da hospedagem baseada em serviços geridos por agentes (como o Foundry Agent Service), que fornece infraestrutura totalmente gerida sem necessidade de implementar ou gerir hosts de trabalho. Agentes duráveis são ideais quando precisa da flexibilidade de uma implementação em primeiro lugar do código combinada com uma gestão de estado duradoura.

Escolha um modelo de alojamento

Modelo de hospedagem Escolhe-a quando precisares
Funções do Azure Um modelo de alojamento gerido e serverless; escala incorporada e escala até zero; Funções do Azure triggers e bindings; endpoints HTTP gerados pelo modelo de programação Functions; o disparador do servidor MCP; e gestão mínima da infraestrutura do host.
Traga-te-tu-próprio-computo / auto-hospedado Mais controlo sobre o processo anfitrião, ambiente de implementação, ciclo de vida em tempo de execução, infraestrutura, rede, autenticação ou integração com uma aplicação ou serviço existente. Use este modelo para containers, Kubernetes, trabalhadores de longa duração, aplicações de consola, serviços personalizados ou ambientes de alojamento que não sejam funções.

Quando hospedados no plano de hospedagem do Funções do Azure Flex Consumption , os agentes podem ser dimensionados para milhares de instâncias ou para zero instâncias quando não estão em uso, permitindo que você pague apenas pela computação necessária. Em cenários auto-hospedados, o seu próprio host controla a vida útil do processo, escalabilidade, rede e implementação.

Como Começar

Num projeto .NET, escolha o conjunto de pacotes para o seu modelo de alojamento.

Para alojamento do Funções do Azure, adicione o pacote de integração Funções do Azure e os pacotes de trabalhadores Functions.

dotnet add package Azure.AI.Projects --prerelease
dotnet add package Azure.Identity
dotnet add package Microsoft.Agents.AI.Foundry --prerelease
dotnet add package Microsoft.Agents.AI.Hosting.AzureFunctions --prerelease

Note

Além desses pacotes, verifique se seu projeto usa a versão 2.2.0 ou posterior do pacote Microsoft.Azure.Functions.Worker .

Para alojamento de transporte do seu próprio computador, adicione o pacote base de integração Durable Task e os pacotes de trabalhadores/clientes Durable Task Scheduler usados pelo seu anfitrião:

dotnet add package Microsoft.Agents.AI.DurableTask --prerelease
dotnet add package Microsoft.DurableTask.Client.AzureManaged
dotnet add package Microsoft.DurableTask.Worker.AzureManaged
dotnet add package Microsoft.Extensions.Hosting

Num projeto Python, escolhe o pacote para o teu modelo de alojamento.

Para alojamento do Funções do Azure, instale o pacote de integração Funções do Azure.

pip install azure-identity
pip install agent-framework-azurefunctions --pre

Para alojamento de transporte do seu próprio computador, instale o pacote de integração Durable Task.

pip install azure-identity
pip install agent-framework-durabletask --pre

Funções do Azure hosting

Com a Durable Extension, pode implementar e alojar agentes Microsoft Agent Framework em Funções do Azure com endpoints HTTP incorporados e invocação baseada em orquestração. O Funções do Azure fornece preços de pagamento por invocação orientados por eventos com dimensionamento automático e gerenciamento mínimo de infraestrutura.

Quando configura um agente duradouro no Funções do Azure, a extensão cria automaticamente endpoints HTTP para o seu agente e gere a infraestrutura subjacente para armazenar o estado da conversa, tratar pedidos concorrentes e coordenar fluxos de trabalho multi-agente. A integração de alojamento do Funções do Azure também oferece conveniências específicas para as Funções, como APIs REST geradas para enviar mensagens, verificar o estado e gerir sessões, além de gatilhos como o gatilho do servidor MCP para alojar agentes como servidores MCP sem escrever cola de gatilho.

using System;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting.AzureFunctions;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.Hosting;

var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT") ?? "gpt-4o-mini";

// Create an AI agent following the standard Microsoft Agent Framework pattern
AIAgent agent = new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
    .AsAIAgent(
        model: deploymentName,
        instructions: "You are good at telling jokes.",
        name: "Joker");

// Configure the function app to host the agent with durable thread management
// This automatically creates HTTP endpoints and manages state persistence
using IHost app = FunctionsApplication
    .CreateBuilder(args)
    .ConfigureFunctionsWebApplication()
    .ConfigureDurableAgents(options =>
        options.AddAIAgent(agent)
    )
    .Build();
app.Run();

Warning

DefaultAzureCredential é conveniente para o desenvolvimento, mas requer uma consideração cuidadosa na produção. Em produção, considere usar uma credencial específica (por exemplo, ManagedIdentityCredential) para evitar problemas de latência, sondagens não intencionais de credenciais e potenciais riscos de segurança provenientes de mecanismos de recurso.

import os
from agent_framework.azure import AgentFunctionApp
from agent_framework.openai import OpenAIChatCompletionClient
from azure.identity import DefaultAzureCredential

endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
deployment_name = os.getenv("AZURE_OPENAI_CHAT_COMPLETION_MODEL", "gpt-4o-mini")
api_version = os.getenv("AZURE_OPENAI_API_VERSION")

# Create an AI agent following the standard Microsoft Agent Framework pattern
agent = OpenAIChatCompletionClient(
    azure_endpoint=endpoint,
    model=deployment_name,
    api_version=api_version,
    credential=DefaultAzureCredential()
).as_agent(
    instructions="You are good at telling jokes.",
    name="Joker"
)

# Configure the function app to host the agent with durable thread management
# This automatically creates HTTP endpoints and manages state persistence
app = AgentFunctionApp(agents=[agent])

Traga a sua própria computação / alojamento auto-hospedado

Use alojamento de transporte do seu próprio computador quando quiser as capacidades da Extensão Durável sem usar o modelo de programação do Funções do Azure. Neste modelo, o seu processo inicia um trabalhador de Tarefas Duráveis, regista agentes ou fluxos de trabalho duráveis e liga-se a um backend de Agendador de Tarefas Duráveis. O código do cliente pode correr no mesmo processo ou num serviço separado.

Os trabalhadores auto-hospedados utilizam as mesmas capacidades centrais de Extensão Durável que o alojamento Funções do Azure: checkpointing e retomada, orquestração determinística de agentes, fluxos de trabalho duráveis no Agent Framework, esperas humanas no ciclo, streaming fiável, limpeza de sessões ociosas, visibilidade de dashboards e execução distribuída entre instâncias de trabalhadores sem estado. O seu host é responsável por expor as suas próprias APIs, gestão do ciclo de vida, redes, autenticação e modelo de implementação.

Configure o seu host com o pacote base de integração Durable Task. Use ConfigureDurableAgents para agentes duráveis e ConfigureDurableWorkflows para fluxos de trabalho baseados em grafos Microsoft Agent Framework.

string connectionString = Environment.GetEnvironmentVariable("DURABLE_TASK_SCHEDULER_CONNECTION_STRING")
    ?? "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None";

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.ConfigureDurableAgents(
            options => options.AddAIAgent(agent),
            workerBuilder: builder => builder.UseDurableTaskScheduler(connectionString),
            clientBuilder: builder => builder.UseDurableTaskScheduler(connectionString));
    })
    .Build();

await host.StartAsync();

Consulte os exemplos de consola .NET Durable Agents e .NET Durable Workflows para consoles para exemplos auto-hospedados executáveis.

Use o pacote de integração Durable Task para executar um processo worker que regista agentes e escuta pedidos. O código do cliente pode ligar-se ao mesmo hub de tarefas do Durable Task Scheduler a partir de outro processo.

from agent_framework.azure import DurableAIAgentWorker
from durabletask.azuremanaged.worker import DurableTaskSchedulerWorker

worker = DurableTaskSchedulerWorker(
    host_address="http://localhost:8080",
    secure_channel=False,
    taskhub="default",
)

agent_worker = DurableAIAgentWorker(worker)
agent_worker.add_agent(agent)

worker.start()

Consulte os exemplos Python Tarefas Duradouras para exemplos de cliente trabalhador, incluindo alojamento de agente único, encaminhamento multi-agente, streaming fiável, cadeia de orquestração, concorrência, condicionais e padrões de humano no ciclo.

Fluxos de trabalho do Durable Agent Framework

A durabilidade não se limita a orquestrações duráveis. Os fluxos de trabalho do Microsoft Agent Framework construídos com o modelo de workflow baseado em grafos também podem ser tornados duráveis. A execução do fluxo de trabalho dos checkpoints da Extensão Durável, para que os passos concluídos do executor e do agente não sejam repetidos após o reinício ou falha do processo.

Use orquestrações duráveis quando quiser coordenação imperativa com ramificações baseadas em código, temporizadores, atividades e eventos externos. Use fluxos de trabalho duráveis do Agent Framework quando quiser um grafo declarativo de executores e agentes com roteamento tipado, fan-out/fan-in, arestas condicionais, eventos de workflow, estado partilhado, subfluxos de trabalho ou portas de pedido humano-in-the-loop.

Note

Os fluxos de trabalho do Durable Agent Framework são diferentes do armazenamento por checkpoint nos fluxos de trabalho padrão. O armazenamento Checkpoint ajuda a retomar um fluxo de trabalho no runtime do Agent Framework. A Extensão Durável executa o fluxo de trabalho na infraestrutura de Tarefas Duráveis para que o progresso do fluxo de trabalho seja controlado e recuperado entre trabalhadores duráveis distribuídos. Para checkpointing padrão de workflow, veja Checkpoints e retomada.

Registe fluxos de trabalho baseados em grafos com ConfigureDurableWorkflows para aplicações self-hosted ou ConfigureDurableWorkflows no construtor de aplicações Functions para alojamento Funções do Azure.

Consulte os exemplos de consola Funções do Azure .NET Fluxos de Trabalho Duráveis e .NET Fluxos de Trabalho Duradouros.

Existem exemplos duráveis de workflows disponíveis para alojamento do Funções do Azure, incluindo estado partilhado, sem estado partilhado, execução paralela de workflows e workflows de pessoa no ciclo.

Veja os exemplos Python Funções do Azure para exemplos de agentes duráveis, orquestração, servidor MCP e fluxos de trabalho.

Samples

Linguagem Modelo de hospedagem Samples
C# Funções do Azure .NET Agentes Duráveis - Funções do Azure, .NET Fluxos de Trabalho Duráveis - Funções do Azure
C# Traga-te-tu-próprio-computo / auto-hospedado .NET Agentes Duráveis - Aplicações de Consola, .NET Fluxos de Trabalho Duráveis - Aplicações de Consola
Python Funções do Azure Python Funções do Azure amostras
Python Traga-te-tu-próprio-computo / auto-hospedado Python Amostras de Tarefas Duráveis

Tópicos de agentes com estado e histórico de conversas

Os agentes mantêm threads persistentes que perduram em várias interações. Cada thread é identificado por um ID único de thread e armazena o histórico completo de conversas em armazenamento durable gerido pela infraestrutura Durable Task, como o Durable Task Scheduler.

Esse padrão permite a continuidade da conversação, onde o estado do agente é preservado por meio de falhas e reinicializações do processo, permitindo que o histórico completo da conversa seja mantido nos threads do usuário. O armazenamento durável garante que, mesmo que um processo anfitrião reinicie ou o trabalho retome numa instância de trabalhador diferente, a conversa continue de forma fluida de onde terminou.

Use a limpeza TTL (session time-to-live) para cargas de trabalho que necessitem de continuidade duradoura durante o uso ativo, mas que devem automaticamente limpar conversas ociosas. A limpeza baseada em TTL impede que sessões não utilizadas e o histórico de conversas se acumulem indefinidamente, mantendo o estado ativo da sessão.

O exemplo seguinte do Funções do Azure demonstra múltiplos pedidos HTTP para o mesmo thread, mostrando como o contexto da conversa persiste. Em aplicações self-hosted, utilize as APIs do cliente Durable Task do seu próprio processo ou serviço.

# First interaction - start a new thread
curl -X POST https://your-function-app.azurewebsites.net/api/agents/Joker/run \
  -H "Content-Type: text/plain" \
  -d "Tell me a joke about pirates"

# Response includes thread ID in x-ms-thread-id header and joke as plain text
# HTTP/1.1 200 OK
# Content-Type: text/plain
# x-ms-thread-id: @dafx-joker@263fa373-fa01-4705-abf2-5a114c2bb87d
#
# Why don't pirates shower before they walk the plank? Because they'll just wash up on shore later!

# Second interaction - continue the same thread with context
curl -X POST "https://your-function-app.azurewebsites.net/api/agents/Joker/run?thread_id=@dafx-joker@263fa373-fa01-4705-abf2-5a114c2bb87d" \
  -H "Content-Type: text/plain" \
  -d "Tell me another one about the same topic"

# Agent remembers the pirate context from the first message and responds with plain text
# What's a pirate's favorite letter? You'd think it's R, but it's actually the C!

O estado do agente é mantido em armazenamento durável, permitindo a execução distribuída em várias instâncias. Qualquer instância pode retomar a execução de um agente após interrupções ou falhas, garantindo uma operação contínua.

Streaming fiável

A Extensão Durável suporta streaming fiável para aplicações que necessitam de entrega de tokens em tempo real com garantias de entrega duradouras. O streaming pode ser usado com a extensão principal em ambos os modelos de alojamento, mas os hosts distribuídos precisam de um broker de fluxos fiável, como o Redis, para que os fluxos de tokens possam ser entregues de forma consistente através de reinícios de processos, reconexões ou alterações de trabalhadores.

Use streaming fiável quando a experiência do utilizador depende de respostas incrementais, mas a carga de trabalho ainda necessita de semântica de execução duradoura. Para exemplos executáveis, veja as amostras Python Durable Task, que incluem padrões de streaming fiáveis.

Orquestrações determinísticas multi-agente

A Extensão Durável suporta a construção de fluxos de trabalho determinísticos que coordenam múltiplos agentes usando orquestrações de Tarefas Duráveis. Em Funções do Azure, estes usam orquestrações Durable Functions; em hosts de transporte do seu próprio computo, passam pelo trabalhador Durable Task e pelo cliente que configura.

Orquestrações são fluxos de trabalho baseados em código que coordenam várias operações (como chamadas de agente, chamadas de API externas ou temporizadores) de forma confiável. Determinístico significa que o código de orquestração é executado da mesma maneira quando reproduzido após uma falha, tornando os fluxos de trabalho confiáveis e depuráveis — quando você reproduz o histórico de uma orquestração, pode ver exatamente o que aconteceu em cada etapa.

As orquestrações são executadas de forma confiável, sobrevivendo a falhas entre chamadas de agentes, e fornecem processos previsíveis e repetíveis. Isso os torna ideais para cenários complexos de vários agentes, onde você precisa de ordem de execução garantida e tolerância a falhas.

Orquestrações sequenciais

No padrão multiagente sequencial, agentes especializados são executados em uma ordem específica, onde a saída de cada agente pode influenciar a execução do próximo agente. Esse padrão suporta lógica condicional e ramificação com base nas respostas do agente.

Ao usar agentes em orquestrações, deve-se usar a context.GetAgent() API para obter uma instância de DurableAIAgent, que é uma subclasse especial do tipo padrão AIAgent que encapsula um dos seus agentes registados. O DurableAIAgent wrapper garante que as chamadas do agente sejam devidamente rastreadas e verificadas pela estrutura de orquestração durável.

using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask;
using Microsoft.Agents.AI.DurableTask;

[Function(nameof(SpamDetectionOrchestration))]
public static async Task<string> SpamDetectionOrchestration(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    Email email = context.GetInput<Email>();

    // Check if the email is spam
    DurableAIAgent spamDetectionAgent = context.GetAgent("SpamDetectionAgent");
    AgentSession spamSession = await spamDetectionAgent.CreateSessionAsync();

    AgentResponse<DetectionResult> spamDetectionResponse = await spamDetectionAgent.RunAsync<DetectionResult>(
        message: $"Analyze this email for spam: {email.EmailContent}",
        session: spamSession);
    DetectionResult result = spamDetectionResponse.Result;

    if (result.IsSpam)
    {
        return await context.CallActivityAsync<string>(nameof(HandleSpamEmail), result.Reason);
    }

    // Generate response for legitimate email
    DurableAIAgent emailAssistantAgent = context.GetAgent("EmailAssistantAgent");
    AgentSession emailSession = await emailAssistantAgent.CreateSessionAsync();

    AgentResponse<EmailResponse> emailAssistantResponse = await emailAssistantAgent.RunAsync<EmailResponse>(
        message: $"Draft a professional response to: {email.EmailContent}",
        session: emailSession);

    return await context.CallActivityAsync<string>(nameof(SendEmail), emailAssistantResponse.Result.Response);
}

Ao usar agentes em orquestrações, você deve usar o app.get_agent() método para obter uma instância de agente durável, que é um wrapper especial em torno de um de seus agentes registrados. O envoltório do agente durável garante que as chamadas do agente sejam devidamente rastreadas e registradas pelo framework de orquestração durável.

import azure.durable_functions as df
from typing import cast
from agent_framework.azure import AgentFunctionApp
from pydantic import BaseModel

class SpamDetectionResult(BaseModel):
    is_spam: bool
    reason: str

class EmailResponse(BaseModel):
    response: str

app = AgentFunctionApp(agents=[spam_detection_agent, email_assistant_agent])

@app.orchestration_trigger(context_name="context")
def spam_detection_orchestration(context: df.DurableOrchestrationContext):
    email = context.get_input()

    # Check if the email is spam
    spam_agent = app.get_agent(context, "SpamDetectionAgent")
    spam_thread = spam_agent.create_session()

    spam_result_raw = yield spam_agent.run(
        messages=f"Analyze this email for spam: {email['content']}",
        session=spam_thread,
        response_format=SpamDetectionResult
    )
    spam_result = cast(SpamDetectionResult, spam_result_raw.get("structured_response"))

    if spam_result.is_spam:
        result = yield context.call_activity("handle_spam_email", spam_result.reason)
        return result

    # Generate response for legitimate email
    email_agent = app.get_agent(context, "EmailAssistantAgent")
    email_thread = email_agent.create_session()

    email_response_raw = yield email_agent.run(
        messages=f"Draft a professional response to: {email['content']}",
        session=email_thread,
        response_format=EmailResponse
    )
    email_response = cast(EmailResponse, email_response_raw.get("structured_response"))

    result = yield context.call_activity("send_email", email_response.response)
    return result

As orquestrações coordenam o trabalho entre múltiplos agentes, continuando a funcionar apesar de falhas nas comunicações entre os agentes. O contexto de orquestração fornece métodos para recuperar e interagir com agentes hospedados em orquestrações.

Orquestrações paralelas

No padrão multiagente paralelo, você executa vários agentes simultaneamente e, em seguida, agrega seus resultados. Esse padrão é útil para reunir diversas perspetivas ou processar subtarefas independentes simultaneamente.

using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask;
using Microsoft.Agents.AI.DurableTask;

[Function(nameof(ResearchOrchestration))]
public static async Task<string> ResearchOrchestration(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    string topic = context.GetInput<string>();

    // Execute multiple research agents in parallel
    DurableAIAgent technicalAgent = context.GetAgent("TechnicalResearchAgent");
    DurableAIAgent marketAgent = context.GetAgent("MarketResearchAgent");
    DurableAIAgent competitorAgent = context.GetAgent("CompetitorResearchAgent");

    // Start all agent runs concurrently
    Task<AgentResponse<TextResponse>> technicalTask = 
        technicalAgent.RunAsync<TextResponse>($"Research technical aspects of {topic}");
    Task<AgentResponse<TextResponse>> marketTask = 
        marketAgent.RunAsync<TextResponse>($"Research market trends for {topic}");
    Task<AgentResponse<TextResponse>> competitorTask = 
        competitorAgent.RunAsync<TextResponse>($"Research competitors in {topic}");

    // Wait for all tasks to complete
    await Task.WhenAll(technicalTask, marketTask, competitorTask);

    // Aggregate results
    string allResearch = string.Join("\n\n", 
        technicalTask.Result.Result.Text,
        marketTask.Result.Result.Text,
        competitorTask.Result.Result.Text);

    DurableAIAgent summaryAgent = context.GetAgent("SummaryAgent");
    AgentResponse<TextResponse> summaryResponse = 
        await summaryAgent.RunAsync<TextResponse>($"Summarize this research:\n{allResearch}");

    return summaryResponse.Result.Text;
}
import azure.durable_functions as df
from agent_framework.azure import AgentFunctionApp

app = AgentFunctionApp(agents=[technical_agent, market_agent, competitor_agent, summary_agent])

@app.orchestration_trigger(context_name="context")
def research_orchestration(context: df.DurableOrchestrationContext):
    topic = context.get_input()

    # Execute multiple research agents in parallel
    technical_agent = app.get_agent(context, "TechnicalResearchAgent")
    market_agent = app.get_agent(context, "MarketResearchAgent")
    competitor_agent = app.get_agent(context, "CompetitorResearchAgent")

    technical_task = technical_agent.run(messages=f"Research technical aspects of {topic}")
    market_task = market_agent.run(messages=f"Research market trends for {topic}")
    competitor_task = competitor_agent.run(messages=f"Research competitors in {topic}")

    # Wait for all tasks to complete
    results = yield context.task_all([technical_task, market_task, competitor_task])

    # Aggregate results
    all_research = "\n\n".join([r.get('response', '') for r in results])

    summary_agent = app.get_agent(context, "SummaryAgent")
    summary = yield summary_agent.run(messages=f"Summarize this research:\n{all_research}")

    return summary.get('response', '')

A execução paralela é rastreada usando uma lista de tarefas. O ponto de verificação automático garante que as execuções concluídas do agente não sejam repetidas ou perdidas se ocorrer uma falha durante a agregação.

Orquestrações humanas no loop

As orquestrações de agentes determinísticos podem pausar para entrada humana, aprovação ou revisão sem consumir recursos de computação. A execução durável permite que as orquestrações esperem dias ou até semanas enquanto esperam por respostas humanas. Quando combinado com hospedagem sem servidor, todos os recursos de computação são desativados durante o período de espera, eliminando os custos de computação até que o usuário forneça sua contribuição.

using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask;
using Microsoft.Agents.AI.DurableTask;

[Function(nameof(ContentApprovalWorkflow))]
public static async Task<string> ContentApprovalWorkflow(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    string topic = context.GetInput<string>();

    // Generate content using an agent
    DurableAIAgent contentAgent = context.GetAgent("ContentGenerationAgent");
    AgentResponse<GeneratedContent> contentResponse = 
        await contentAgent.RunAsync<GeneratedContent>($"Write an article about {topic}");
    GeneratedContent draftContent = contentResponse.Result;

    // Send for human review
    await context.CallActivityAsync(nameof(NotifyReviewer), draftContent);

    // Wait for approval with timeout
    HumanApprovalResponse approvalResponse;
    try
    {
        approvalResponse = await context.WaitForExternalEvent<HumanApprovalResponse>(
            eventName: "ApprovalDecision",
            timeout: TimeSpan.FromHours(24));
    }
    catch (OperationCanceledException)
    {
        // Timeout occurred - escalate for review
        return await context.CallActivityAsync<string>(nameof(EscalateForReview), draftContent);
    }

    if (approvalResponse.Approved)
    {
        return await context.CallActivityAsync<string>(nameof(PublishContent), draftContent);
    }

    return "Content rejected";
}
import azure.durable_functions as df
from datetime import timedelta
from agent_framework.azure import AgentFunctionApp

app = AgentFunctionApp(agents=[content_agent])

@app.orchestration_trigger(context_name="context")
def content_approval_workflow(context: df.DurableOrchestrationContext):
    topic = context.get_input()

    # Generate content using an agent
    content_agent = app.get_agent(context, "ContentGenerationAgent")
    draft_content = yield content_agent.run(
        messages=f"Write an article about {topic}"
    )

    # Send for human review
    yield context.call_activity("notify_reviewer", draft_content)

    # Wait for approval with timeout
    approval_task = context.wait_for_external_event("ApprovalDecision")
    timeout_task = context.create_timer(
        context.current_utc_datetime + timedelta(hours=24)
    )

    winner = yield context.task_any([approval_task, timeout_task])

    if winner == approval_task:
        timeout_task.cancel()
        approval_data = approval_task.result
        if approval_data.get("approved"):
            result = yield context.call_activity("publish_content", draft_content)
            return result
        return "Content rejected"

    # Timeout occurred - escalate for review
    result = yield context.call_activity("escalate_for_review", draft_content)
    return result

As orquestrações de agentes determinísticos podem esperar por eventos externos, persistindo de forma duradoura o seu estado enquanto aguardam o feedback humano, sobrevivendo a falhas, reinicializações e longos períodos de espera. Quando a resposta humana chega, a orquestração é retomada automaticamente com o contexto completo da conversa e o estado de execução intactos.

Fornecer contributo humano

Para enviar aprovação ou entrada para uma orquestração em espera, levante um evento externo para a instância de orquestração usando o SDK do cliente Durable Task ou os endpoints da extensão Funções do Azure Durable. Por exemplo, um revisor pode aprovar conteúdo por meio de um formulário da Web que chama:

await client.RaiseEventAsync(instanceId, "ApprovalDecision", new HumanApprovalResponse 
{ 
    Approved = true,
    Feedback = "Looks great!"
});
approval_data = {
    "approved": True,
    "feedback": "Looks great!"
}
await client.raise_event(instance_id, "ApprovalDecision", approval_data)

Eficiência de custos

Os fluxos de trabalho human-in-the-loop com agentes duráveis são extremamente econômicos quando hospedados no plano Funções do Azure Flex Consumption. Para um fluxo de trabalho que aguarda 24 horas para aprovação, você paga apenas por alguns segundos de tempo de execução (o tempo para gerar conteúdo, enviar notificação e processar a resposta) — não as 24 horas de espera. Durante o período de espera, nenhum recurso de computação é consumido.

Observabilidade com o Agendador de Tarefas Durável

O Durable Task Scheduler (DTS) é o back-end durável recomendado para seus agentes duráveis, oferecendo o melhor desempenho, infraestrutura totalmente gerenciada e observabilidade integrada por meio de um painel de interface do usuário. As aplicações Funções do Azure podem usar outros backends de armazenamento (como o Armazenamento do Azure), mas o DTS está otimizado especificamente para cargas de trabalho duráveis e oferece capacidades superiores de desempenho e monitorização. Os trabalhadores auto-hospedados também utilizam o DTS para marcação duradoura, visibilidade do estado e do painel de controlo.

Perspetivas sobre sessões de agentes

  • Histórico de conversas: Consulte o histórico completo de conversas de cada sessão com agentes, incluindo todas as mensagens, chamadas de ferramentas e contexto da conversa em qualquer momento
  • Tempo de tarefa: monitore quanto tempo tarefas específicas e interações do agente levam para serem concluídas

Captura de tela do painel do Agendador de Tarefas Duráveis mostrando o histórico de bate-papo do agente com conversas e mensagens.

Perceções sobre orquestração

  • Visualização de vários agentes: veja o fluxo de execução ao chamar vários agentes especializados com representação visual de execuções paralelas e ramificação condicional
  • Histórico de execução: Acesse logs de execução detalhados
  • Monitoramento em tempo real: rastreie orquestrações ativas, itens de trabalho enfileirados e estados do agente em toda a implantação
  • Métricas de desempenho: monitore os tempos de resposta do agente, o uso do token e a duração da orquestração

Captura de tela do painel do Agendador de Tarefas Duráveis mostrando a visualização da orquestração com várias interações do agente e a execução do fluxo de trabalho.

Capacidades de depuração

  • Visualize saídas de agentes estruturados e resultados de chamadas de ferramentas
  • Invocações de ferramentas de rastreamento e seus resultados
  • Monitorizar a manipulação de eventos externos para cenários com humanos no sistema.

O painel permite que você entenda exatamente o que seus agentes estão fazendo, diagnostique problemas rapidamente e otimize o desempenho com base em dados reais de execução.

Tutorial: Crie e execute um agente duradouro com o Funções do Azure

Este tutorial mostra-lhe como criar e executar um agente de IA durável usando o modelo de alojamento Funções do Azure para a Durable Extension. Você criará uma aplicação do Funções do Azure que hospeda um agente com estado e pontos de extremidade HTTP incorporados, e aprenderá a monitorizá-la usando o painel do Agendador de Tarefas Duráveis. Para agentes auto-hospedados, consulte os exemplos.

Pré-requisitos

Antes de começar, certifique-se de ter os seguintes pré-requisitos:

Note

O Microsoft Agent Framework é suportado com todas as versões ativamente suportadas do .NET. Para os fins deste exemplo, recomendamos o SDK do .NET 9 ou uma versão posterior.

Faça o download do projeto de início rápido

Use a CLI do Desenvolvedor do Azure para inicializar um novo projeto a partir do modelo de início rápido de agentes duráveis.

  1. Crie um novo diretório para seu projeto e navegue até ele:

    mkdir MyDurableAgent
    cd MyDurableAgent
    

  1. Inicialize o projeto a partir do modelo:

    azd init --template durable-agents-quickstart-dotnet
    

    Quando for solicitado um nome de ambiente, digite um nome como my-durable-agent.

Isso baixa o projeto de início rápido com todos os arquivos necessários, incluindo a configuração do Funções do Azure, o código do agente e a infraestrutura como modelos de código.

  1. Crie um novo diretório para seu projeto e navegue até ele:

    mkdir MyDurableAgent
    cd MyDurableAgent
    

  1. Inicialize o projeto a partir do modelo:

    azd init --template durable-agents-quickstart-python
    

    Quando for solicitado um nome de ambiente, digite um nome como my-durable-agent.

  2. Crie e ative um ambiente virtual:

    uv venv .venv
    source .venv/bin/activate
    

Note

python3 -m venv .venv também funciona, mas pode manter-se indefinidamente em Windows com Microsoft Store Python devido a um problema conhecido ensurepip. Use uv venv .venv para evitar isto.

  1. Instale os pacotes necessários:

    python -m pip install -r requirements.txt
    

Isso baixa o projeto de início rápido com todos os arquivos necessários, incluindo a configuração do Funções do Azure, o código do agente e a infraestrutura como modelos de código. Também prepara um ambiente virtual com as dependências necessárias.

Provisionar recursos do Azure

Use o CLI do Desenvolvedor do Azure para criar os recursos necessários do Azure para o seu agente durável.

  1. Provisionar a infraestrutura:

    azd provision
    

    Este comando cria:

    • Um serviço OpenAI do Azure com uma implementação gpt-4o-mini
    • Um aplicativo do Funções do Azure com plano de hospedagem Flex Consumption
    • Uma conta de Armazenamento do Azure para o tempo de execução e armazenamento durável do Funções do Azure
    • Uma instância do Agendador de Tarefas Durável (Plano de consumo) para gerenciar o estado do agente
    • Configurações de rede e identidade necessárias
  2. Quando solicitado, selecione sua assinatura do Azure e escolha um local para os recursos.

O processo de provisionamento leva alguns minutos. Uma vez concluído, azd armazena as informações dos recursos criados no seu ambiente.

Revise o código do agente

Agora vamos examinar o código que define seu agente durável.

Abra Program.cs para ver a configuração do agente:

using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting.AzureFunctions;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.Hosting;

var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") 
    ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT environment variable is not set");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT") ?? "gpt-4o-mini";

// Create an AI agent following the standard Microsoft Agent Framework pattern
AIAgent agent = new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
    .AsAIAgent(
        model: deploymentName,
        instructions: "You are a helpful assistant that can answer questions and provide information.",
        name: "MyDurableAgent");

using IHost app = FunctionsApplication
    .CreateBuilder(args)
    .ConfigureFunctionsWebApplication()
    .ConfigureDurableAgents(options => options.AddAIAgent(agent))
    .Build();
app.Run();

Este código:

  1. Recupera sua configuração do Azure OpenAI a partir de variáveis de ambiente.
  2. Cria um cliente OpenAI do Azure usando credenciais do Azure.
  3. Cria um agente de IA com instruções e um nome.
  4. Configura a aplicação Funções do Azure para hospedar o agente com gestão de threads persistente.

Abra function_app.py para ver a configuração do agente:

import os
from agent_framework.azure import AgentFunctionApp
from agent_framework.openai import OpenAIChatCompletionClient
from azure.identity import DefaultAzureCredential

endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
if not endpoint:
    raise ValueError("AZURE_OPENAI_ENDPOINT is not set.")
deployment_name = os.getenv("AZURE_OPENAI_CHAT_COMPLETION_MODEL", "gpt-4o-mini")
api_version = os.getenv("AZURE_OPENAI_API_VERSION")

# Create an AI agent following the standard Microsoft Agent Framework pattern
agent = OpenAIChatCompletionClient(
    azure_endpoint=endpoint,
    model=deployment_name,
    api_version=api_version,
    credential=DefaultAzureCredential()
).as_agent(
    instructions="You are a helpful assistant that can answer questions and provide information.",
    name="MyDurableAgent"
)

# Configure the function app to host the agent with durable thread management
app = AgentFunctionApp(agents=[agent])

Este código:

  • Recupera sua configuração do Azure OpenAI a partir de variáveis de ambiente.
  • Cria um cliente OpenAI do Azure usando credenciais do Azure.
  • Cria um agente de IA com instruções e um nome.
  • Configura a aplicação Funções do Azure para hospedar o agente com gestão de threads persistente.

O agente agora está pronto para ser hospedado no Funções do Azure. A extensão de tarefa durável cria automaticamente pontos de extremidade HTTP para interagir com seu agente e gerencia o estado da conversa em várias solicitações.

Definir configurações locais

Crie um local.settings.json arquivo para desenvolvimento local com base no arquivo de exemplo incluído no projeto.

  1. Copie o arquivo de configurações de exemplo:

    cp local.settings.sample.json local.settings.json
    

  1. Obtenha o seu endpoint do Azure OpenAI a partir dos recursos provisionados:

    azd env get-value AZURE_OPENAI_ENDPOINT
    
  2. Abra local.settings.json e substitua <your-resource-name> o AZURE_OPENAI_ENDPOINT valor pelo ponto de extremidade do comando anterior.

O seu local.settings.json deve ter esta aparência:

{
  "IsEncrypted": false,
  "Values": {
    // ... other settings ...
    "AZURE_OPENAI_ENDPOINT": "https://your-openai-resource.openai.azure.com",
    "AZURE_OPENAI_DEPLOYMENT": "gpt-4o-mini",
    "TASKHUB_NAME": "default"
  }
}

Note

O local.settings.json arquivo é usado apenas para desenvolvimento local e não é implantado no Azure. Para implantações de produção, essas configurações são definidas automaticamente em seu aplicativo Funções do Azure pelos modelos de infraestrutura.

Iniciar dependências de desenvolvimento local

Para executar agentes duráveis localmente, você precisa iniciar dois serviços:

  • Azurite: emula os serviços de armazenamento do Azure (usados pelo Funções do Azure para gerenciar gatilhos e estado interno).
  • Emulador do Programador de Tarefas Duráveis (DTS): administra o estado durável (histórico de conversas, estado de orquestração) e o agendamento para os seus agentes

Iniciar Azurite

O Azurite emula os serviços de Armazenamento do Azure localmente. Funções do Azure utiliza-o para gerir o estado interno. Você precisará executar isso em uma nova janela do terminal e mantê-lo funcionando enquanto desenvolve e testa seu agente durável.

  1. Abra uma nova janela do terminal e puxe a imagem do Azurite Docker:

    docker pull mcr.microsoft.com/azure-storage/azurite
    
  2. Inicie o Azurite numa janela do terminal:

    docker run -p 10000:10000 -p 10001:10001 -p 10002:10002 mcr.microsoft.com/azure-storage/azurite
    

    O Azurite iniciará e escutará nas portas padrão para os serviços Blob (10000), Fila (10001) e Tabela (10002).

Mantenha a janela do terminal aberta enquanto estiver a desenvolver e testar o seu agente durável.

Tip

Para obter mais informações sobre o Azurite, incluindo métodos de instalação alternativos, consulte Usar emulador Azurite para desenvolvimento local do Armazenamento do Azure.

Inicie o emulador do Durable Task Scheduler

O emulador DTS fornece o back-end resistente para gerir o estado do agente e as orquestrações. Ele armazena o histórico de conversas e garante que o estado do seu agente persista durante as reinicializações. Ele também aciona orquestrações e agentes duráveis. Você precisará executar isso em uma nova janela de terminal separada e mantê-lo funcionando enquanto desenvolve e testa seu agente durável.

  1. Abra outra nova janela do terminal e puxe a imagem do Docker do emulador DTS:

    docker pull mcr.microsoft.com/dts/dts-emulator:latest
    
  2. Execute o emulador DTS:

    docker run -p 8080:8080 -p 8082:8082 mcr.microsoft.com/dts/dts-emulator:latest
    

    Este comando inicia o emulador e expõe:

    • Porta 8080: O endpoint gRPC para o Agendador de Tarefas Duráveis (usado pelo Functions app)
    • Porta 8082: O painel administrativo
  3. O painel estará disponível em http://localhost:8082.

Mantenha a janela do terminal aberta enquanto estiver a desenvolver e testar o seu agente durável.

Tip

Para saber mais sobre o emulador DTS, incluindo como configurar vários hubs de tarefas e acessar o painel, consulte Desenvolver com o Agendador de Tarefas Durável.

Execute o aplicativo de função

Agora você está pronto para executar seu aplicativo Funções do Azure com o agente durável.

  1. Em uma nova janela de terminal (mantendo o Azurite e o emulador DTS em execução em janelas separadas), navegue até o diretório do projeto.

  2. Inicie o tempo de execução do Funções do Azure:

    func start
    
  3. Deve ver um resultado indicando que a sua função está em execução, incluindo os pontos de extremidade HTTP para o seu agente:

    Functions:
         http-MyDurableAgent: [POST] http://localhost:7071/api/agents/MyDurableAgent/run
         dafx-MyDurableAgent: entityTrigger
    

Esses pontos de extremidade gerenciam o estado da conversa automaticamente - você não precisa criar ou gerenciar objetos de thread por conta própria.

Testar o agente ao nível local

Agora você pode interagir com seu agente durável usando solicitações HTTP. O agente mantém o estado de conversação em várias solicitações, permitindo conversas em vários turnos.

Iniciar uma nova conversa

Crie um novo tópico e envie sua primeira mensagem:

curl -i -X POST http://localhost:7071/api/agents/MyDurableAgent/run \
  -H "Content-Type: text/plain" \
  -d "What are three popular programming languages?"

Exemplo de resposta (observe que o x-ms-thread-id cabeçalho contém o ID do thread):

HTTP/1.1 200 OK
Content-Type: text/plain
x-ms-thread-id: @dafx-mydurableagent@263fa373-fa01-4705-abf2-5a114c2bb87d
Content-Length: 189

Three popular programming languages are Python, JavaScript, and Java. Python is known for its simplicity and readability, JavaScript powers web interactivity, and Java is widely used in enterprise applications.

Salve o ID do thread do x-ms-thread-id cabeçalho (por exemplo, @dafx-mydurableagent@263fa373-fa01-4705-abf2-5a114c2bb87d) para a próxima solicitação.

Continue a conversa

Envie uma mensagem de acompanhamento para o mesmo thread incluindo o ID do thread como um parâmetro de consulta:

curl -X POST "http://localhost:7071/api/agents/MyDurableAgent/run?thread_id=@dafx-mydurableagent@263fa373-fa01-4705-abf2-5a114c2bb87d" \
  -H "Content-Type: text/plain" \
  -d "Which one is best for beginners?"

Substitua @dafx-mydurableagent@263fa373-fa01-4705-abf2-5a114c2bb87d pelo ID de thread real do x-ms-thread-id cabeçalho da resposta anterior.

Exemplo de resposta:

Python is often considered the best choice for beginners among those three. Its clean syntax reads almost like English, making it easier to learn programming concepts without getting overwhelmed by complex syntax. It's also versatile and widely used in education.

Observe que o agente se lembra do contexto da mensagem anterior (as três linguagens de programação) sem que você precise especificá-las novamente. Como o estado da conversa é armazenado de forma durável pelo Agendador de Tarefas Duráveis, esse histórico persiste mesmo se você reiniciar o aplicativo de função ou se a conversa for retomada por uma instância diferente.

Monitore com o painel do Agendador de Tarefas Durável

O Durable Task Scheduler oferece um painel incorporado para monitorizar e depurar os seus agentes duráveis. O painel oferece visibilidade profunda das operações do agente, do histórico de conversas e do fluxo de execução.

Aceda ao painel

  1. Abra o painel do emulador DTS local no http://localhost:8082 no seu navegador da Web.

  2. Selecione o hub de tarefas padrão na lista para exibir seus detalhes.

  3. Selecione o ícone de engrenagem no canto superior direito para abrir as configurações e verifique se a opção Ativar páginas do agente em Visualizar recursos está selecionada.

Explore as conversas dos agentes

  1. No painel, navegue até a guia Agentes .

  2. Selecione seu thread de agente durável (por exemplo, mydurableagent - 263fa373-fa01-4705-abf2-5a114c2bb87d) na lista.

    Você verá uma visão detalhada do thread do agente, incluindo o histórico completo de conversas com todas as mensagens e respostas.

    Captura de tela do painel do Agendador de Tarefas Duráveis mostrando o histórico de conversas de um thread de agente.

O painel fornece uma visualização da linha do tempo para ajudá-lo a entender o fluxo da conversa. As principais informações incluem:

  • Carimbos de data/hora e duração de cada interação
  • Conteúdo de comandos e respostas
  • Número de fichas utilizadas

Tip

O painel DTS fornece atualizações em tempo real, para que você possa observar o comportamento do seu agente enquanto interage com ele por meio dos pontos de extremidade HTTP.

Publicar no Azure

Agora que você testou seu agente durável localmente, implante-o no Azure.

  1. Implante o aplicativo:

    azd deploy
    

    Este comando empacota seu aplicativo e o implanta no aplicativo Funções do Azure criado durante o provisionamento.

  2. Aguarde até que a implementação seja concluída. A saída confirmará quando seu agente está sendo executado no Azure.

Testar o agente implantado

Após a implantação, teste seu agente em execução no Azure.

Obter a tecla de função

O Funções do Azure requer uma chave de API para funções acionadas por HTTP em produção:

API_KEY=`az functionapp function keys list --name $(azd env get-value AZURE_FUNCTION_NAME) --resource-group $(azd env get-value AZURE_RESOURCE_GROUP) --function-name http-MyDurableAgent --query default -o tsv`

Inicie uma nova conversa no Azure

Crie um novo thread e envie sua primeira mensagem para o agente implantado:

curl -i -X POST "https://$(azd env get-value AZURE_FUNCTION_NAME).azurewebsites.net/api/agents/MyDurableAgent/run?code=$API_KEY" \
  -H "Content-Type: text/plain" \
  -d "What are three popular programming languages?"

Observe o ID do thread retornado no cabeçalho da x-ms-thread-id resposta.

Continue a conversa em Azure

Envie uma mensagem de acompanhamento no mesmo tópico. Substitua <thread-id> pelo ID do thread da resposta anterior:

THREAD_ID="<thread-id>"
curl -X POST "https://$(azd env get-value AZURE_FUNCTION_NAME).azurewebsites.net/api/agents/MyDurableAgent/run?code=$API_KEY&thread_id=$THREAD_ID" \
  -H "Content-Type: text/plain" \
  -d "Which is easiest to learn?"

O agente mantém o contexto de conversação no Azure tal como fazia localmente, demonstrando a durabilidade do estado do agente.

Monitorizar o agente implantado

Você pode monitorar seu agente implantado usando o painel do Agendador de Tarefas Duráveis no Azure.

  1. Obtenha o nome da sua instância do Durable Task Scheduler:

    azd env get-value DTS_NAME
    
  2. Abra o portal do Azure e procure o nome do Agendador de Tarefas Duráveis da etapa anterior.

  3. Na folha de visão geral do recurso Agendador de Tarefas Duráveis, selecione o hub de tarefas padrão na lista.

  4. Selecione Abrir painel na parte superior da página do hub de tarefas para abrir o painel de monitoramento.

  5. Veja as conversas do seu agente tal como fez com o emulador local.

O painel hospedado no Azure fornece os mesmos recursos de depuração e monitoramento que o emulador local, permitindo que você inspecione o histórico de conversas, rastreie chamadas de ferramentas e analise o desempenho em seu ambiente de produção.

Tutorial: Orquestrar agentes duráveis com Funções do Azure

Este tutorial mostra-te como orquestrar múltiplos agentes de IA duráveis usando o modelo de alojamento Funções do Azure e o padrão de fan-out/fan-in. Vais estender o agente duradouro do tutorial anterior para criar um sistema multi-agente que processa a pergunta do utilizador e depois traduz a resposta para várias línguas em simultâneo. Para exemplos de orquestração auto-hospedada, veja os samples.

Compreender o padrão de orquestração

A orquestração que você construirá segue este fluxo:

  1. Entrada do usuário - Uma pergunta ou mensagem do usuário
  2. Agente principal - O MyDurableAgent do primeiro tutorial processa a questão
  3. Fan-out - A resposta do agente principal é enviada simultaneamente para ambos os agentes de tradução
  4. Agentes de tradução - Dois agentes especializados traduzem a resposta (francês e espanhol)
  5. Fan-in - Os resultados são agregados em uma única resposta JSON com a resposta original e traduções

Este padrão permite o processamento simultâneo, reduzindo o tempo total de resposta em comparação com a tradução sequencial.

Registrar agentes na inicialização

Para usar corretamente os agentes em orquestrações duráveis, registre-os na inicialização do aplicativo. Podem ser utilizados em execuções de orquestração.

Atualize o seu Program.cs para registar os agentes de tradução juntamente com os existentes MyDurableAgent:

using System;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting.AzureFunctions;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.Hosting;

// Get the Azure OpenAI configuration
string endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
    ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
string deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT")
    ?? "gpt-4o-mini";

// Create the Microsoft Foundry client
AIProjectClient client = new(new Uri(endpoint), new DefaultAzureCredential());

// Create the main agent from the first tutorial
AIAgent mainAgent = client.AsAIAgent(
    model: deploymentName,
    instructions: "You are a helpful assistant that can answer questions and provide information.",
    name: "MyDurableAgent");

// Create translation agents
AIAgent frenchAgent = client.AsAIAgent(
    model: deploymentName,
    instructions: "You are a translator. Translate the following text to French. Return only the translation, no explanations.",
    name: "FrenchTranslator");

AIAgent spanishAgent = client.AsAIAgent(
    model: deploymentName,
    instructions: "You are a translator. Translate the following text to Spanish. Return only the translation, no explanations.",
    name: "SpanishTranslator");

// Build and configure the Functions host
using IHost app = FunctionsApplication
    .CreateBuilder(args)
    .ConfigureFunctionsWebApplication()
    .ConfigureDurableAgents(options =>
    {
        // Register all agents for use in orchestrations and HTTP endpoints
        options.AddAIAgent(mainAgent);
        options.AddAIAgent(frenchAgent);
        options.AddAIAgent(spanishAgent);
    })
    .Build();

app.Run();

Atualize o seu function_app.py para registar os agentes de tradução juntamente com os existentes MyDurableAgent:

import os
from azure.identity import DefaultAzureCredential
from agent_framework.azure import AgentFunctionApp
from agent_framework.openai import OpenAIChatCompletionClient

# Get the Azure OpenAI configuration
endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
if not endpoint:
    raise ValueError("AZURE_OPENAI_ENDPOINT is not set.")
deployment_name = os.getenv("AZURE_OPENAI_CHAT_COMPLETION_MODEL", "gpt-4o-mini")
api_version = os.getenv("AZURE_OPENAI_API_VERSION")

# Create the Azure OpenAI client
chat_client = OpenAIChatCompletionClient(
    azure_endpoint=endpoint,
    model=deployment_name,
    api_version=api_version,
    credential=DefaultAzureCredential()
)

# Create the main agent from the first tutorial
main_agent = chat_client.as_agent(
    instructions="You are a helpful assistant that can answer questions and provide information.",
    name="MyDurableAgent"
)

# Create translation agents
french_agent = chat_client.as_agent(
    instructions="You are a translator. Translate the following text to French. Return only the translation, no explanations.",
    name="FrenchTranslator"
)

spanish_agent = chat_client.as_agent(
    instructions="You are a translator. Translate the following text to Spanish. Return only the translation, no explanations.",
    name="SpanishTranslator"
)

# Create the function app and register all agents
app = AgentFunctionApp(agents=[main_agent, french_agent, spanish_agent])

Criar uma função de orquestração

Uma função de orquestração coordena o fluxo de trabalho entre vários agentes. Recupera agentes registados do contexto durável e orquestra a sua execução, chamando primeiro o agente principal e, em seguida, desdobrando-se para agentes de tradução simultaneamente.

Crie um novo arquivo nomeado AgentOrchestration.cs no diretório do projeto:

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.DurableTask;
using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask;

namespace MyDurableAgent;

public static class AgentOrchestration
{
    // Define a strongly-typed response structure for agent outputs
    public sealed record TextResponse(string Text);

    [Function("agent_orchestration_workflow")]
    public static async Task<Dictionary<string, string>> AgentOrchestrationWorkflow(
        [OrchestrationTrigger] TaskOrchestrationContext context)
    {
        var input = context.GetInput<string>() ?? throw new ArgumentNullException(nameof(context), "Input cannot be null");

        // Step 1: Get the main agent's response
        DurableAIAgent mainAgent = context.GetAgent("MyDurableAgent");
        AgentResponse<TextResponse> mainResponse = await mainAgent.RunAsync<TextResponse>(input);
        string agentResponse = mainResponse.Result.Text;

        // Step 2: Fan out - get the translation agents and run them concurrently
        DurableAIAgent frenchAgent = context.GetAgent("FrenchTranslator");
        DurableAIAgent spanishAgent = context.GetAgent("SpanishTranslator");

        Task<AgentResponse<TextResponse>> frenchTask = frenchAgent.RunAsync<TextResponse>(agentResponse);
        Task<AgentResponse<TextResponse>> spanishTask = spanishAgent.RunAsync<TextResponse>(agentResponse);

        // Step 3: Wait for both translation tasks to complete (fan-in)
        await Task.WhenAll(frenchTask, spanishTask);

        // Get the translation results
        TextResponse frenchResponse = (await frenchTask).Result;
        TextResponse spanishResponse = (await spanishTask).Result;

        // Step 4: Combine results into a dictionary
        var result = new Dictionary<string, string>
        {
            ["original"] = agentResponse,
            ["french"] = frenchResponse.Text,
            ["spanish"] = spanishResponse.Text
        };

        return result;
    }
}

Adicione a função de orquestração ao seu function_app.py ficheiro:

import azure.durable_functions as df

@app.orchestration_trigger(context_name="context")
def agent_orchestration_workflow(context: df.DurableOrchestrationContext):
    """
    Orchestration function that coordinates multiple agents.
    Returns a dictionary with the original response and translations.
    """
    input_text = context.get_input()

    # Step 1: Get the main agent's response
    main_agent = app.get_agent(context, "MyDurableAgent")
    main_response = yield main_agent.run(input_text)
    agent_response = main_response.text

    # Step 2: Fan out - get the translation agents and run them concurrently
    french_agent = app.get_agent(context, "FrenchTranslator")
    spanish_agent = app.get_agent(context, "SpanishTranslator")

    parallel_tasks = [
        french_agent.run(agent_response),
        spanish_agent.run(agent_response)
    ]

    # Step 3: Wait for both translation tasks to complete (fan-in)
    translations = yield context.task_all(parallel_tasks) # type: ignore

    # Step 4: Combine results into a dictionary
    result = {
        "original": agent_response,
        "french": translations[0].text,
        "spanish": translations[1].text
    }

    return result

Teste a orquestração

Verifique se as dependências de desenvolvimento local do primeiro tutorial ainda estão em execução:

  • Azurite numa janela de terminal
  • Emulador durável do Agendador de tarefas em outra janela do terminal

Com suas dependências de desenvolvimento local em execução:

  1. Inicie seu aplicativo Funções do Azure em uma nova janela de terminal:

    func start
    
  2. A extensão Durable Functions cria automaticamente pontos de extremidade HTTP integrados para gerenciar orquestrações. Inicie a orquestração usando a API integrada:

    curl -X POST http://localhost:7071/runtime/webhooks/durabletask/orchestrators/agent_orchestration_workflow \
      -H "Content-Type: application/json" \
      -d '"\"What are three popular programming languages?\""'
    

  1. A resposta inclui URLs para gerenciar a instância de orquestração:

    {
      "id": "abc123def456",
      "statusQueryGetUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123def456",
      "sendEventPostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123def456/raiseEvent/{eventName}",
      "terminatePostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123def456/terminate",
      "purgeHistoryDeleteUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123def456"
    }
    
  2. Consulte o status da orquestração usando o statusQueryGetUri (substitua abc123def456 pelo ID da instância real):

    curl http://localhost:7071/runtime/webhooks/durabletask/instances/abc123def456
    

  1. Sonde o ponto de extremidade de status até runtimeStatus que seja Completed. Quando terminar, verá o resultado da orquestração com a resposta do agente principal e as suas traduções:

    {
      "name": "agent_orchestration_workflow",
      "instanceId": "abc123def456",
      "runtimeStatus": "Completed",
      "output": {
        "original": "Three popular programming languages are Python, JavaScript, and Java. Python is known for its simplicity...",
        "french": "Trois langages de programmation populaires sont Python, JavaScript et Java. Python est connu pour sa simplicité...",
        "spanish": "Tres lenguajes de programación populares son Python, JavaScript y Java. Python es conocido por su simplicidad..."
      }
    }
    

Monitore a orquestração no painel de controlo

O painel do Durable Task Scheduler fornece visibilidade à sua orquestração:

  1. Abra http://localhost:8082 no seu navegador.

  2. Selecione o hub de tarefas "padrão".

  3. Selecione a guia "Orquestrações".

  4. Encontre sua instância de orquestração na lista.

  5. Selecione a instância para ver:

    • A linha do tempo da orquestração
    • Execução do agente principal seguida de agentes de tradução a operar em simultâneo
    • Cada execução de agente (MyDurableAgent, depois tradutores de francês e espanhol)
    • Padrões de fan-out e fan-in visualizados
    • Calendário e duração de cada etapa

Deploye a orquestração para Azure

Implante o aplicativo atualizado usando a CLI do Azure Developer:

azd deploy

Isso implanta seu código atualizado com a nova função de orquestração e agentes adicionais para o aplicativo Funções do Azure criado no primeiro tutorial.

Testar a orquestração implantada

Após a implantação, teste sua orquestração em execução no Azure.

  1. Obtenha a chave do sistema para a extensão durável:

    SYSTEM_KEY=$(az functionapp keys list --name $(azd env get-value AZURE_FUNCTION_NAME) --resource-group $(azd env get-value AZURE_RESOURCE_GROUP) --query "systemKeys.durabletask_extension" -o tsv)
    

  1. Inicie a orquestração usando a API integrada:

    curl -X POST "https://$(azd env get-value AZURE_FUNCTION_NAME).azurewebsites.net/runtime/webhooks/durabletask/orchestrators/agent_orchestration_workflow?code=$SYSTEM_KEY" \
      -H "Content-Type: application/json" \
      -d '"\"What are three popular programming languages?\""'
    

  1. Use o statusQueryGetUri da resposta para verificar a conclusão e veja os resultados com traduções.

Passos seguintes

Recursos adicionais: