Extensão Durável

A Durable Extension for Microsoft Agent Framework traz a execução durável para agentes, orquestrações de vários agentes e fluxos de trabalho do Microsoft Agent Framework. Você pode usá-lo para persistir sessões de agente, orquestração de ponto de verificação e progresso do fluxo de trabalho, recuperar-se de falhas e dimensionar o trabalho entre hosts distribuídos sem alterar a lógica do agente principal.

A extensão dá suporte a dois modelos de hospedagem em C# e Python:

  • Azure Functions para hospedagem gerenciada sem servidor com o modelo de programação Azure Functions.
  • Traga sua própria computação/auto-hospedada para executar agentes duráveis e fluxos de trabalho em seu próprio processo de trabalho, serviço, contêiner, ambiente do Kubernetes ou infraestrutura de aplicativo existente.

Overview

Os agentes duráveis combinam o modelo de programação do Agent Framework com a infraestrutura de Tarefa Durável, como o Agendador de Tarefas Duráveis, para criar agentes que:

  • Manter o estado automaticamente entre solicitações e execuções de trabalho
  • Retomar após falhas sem perder o contexto da conversa ou repetir o trabalho concluído
  • Dimensionar entre trabalhadores distribuídos e sem estado com base na demanda
  • Orquestrar fluxos de trabalho de vários agentes com garantias de execução confiáveis
  • Fluxos de trabalho do Checkpoint Agent Framework criados com o modelo de fluxo de trabalho baseado em grafo
  • Pausar para entrada humana ou eventos externos sem consumir tokens de computação ou modelo enquanto aguarda
  • Transmitir respostas de forma confiável quando configurado com um agente de fluxo confiável, como o Redis
  • Gerenciar o ciclo de vida da sessão com limpeza de TTL (tempo de vida útil) da sessão e monitoramento baseado em dashboard

Quando usar agentes duráveis

Escolha agentes duráveis quando precisar:

  • Estado de conversa persistente: as sessões do agente sobrevivem a falhas de processo, reinicializações e eventos de expansão
  • 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 controlada por eventos: integrar com gatilhos, filas, webhooks, temporizadores ou eventos de aplicativo existentes
  • Estado de conversa automática: o histórico de conversas do agente é gerenciado e mantido automaticamente sem a necessidade de tratamento de estado explícito em seu código
  • Fluxos de trabalho do Agent Framework: tornar os fluxos de trabalho do Microsoft Agent Framework baseados em grafo duráveis para que cada etapa possa ser colocada em ponto de verificação e retomada
  • Sessões de longa duração: manter conversas úteis disponíveis ao usar a limpeza de TTL (tempo de vida útil) da sessão para remover sessões ociosas automaticamente
  • Respostas confiáveis em tempo real: transmitir a saída do token de maneira durável para aplicativos que precisam de UX em tempo real com garantias de entrega

Essa abordagem de hospedagem difere da hospedagem gerenciada de agente baseado em serviço (como o Serviço do Foundry Agent), que fornece infraestrutura totalmente gerenciada sem a necessidade de implantar ou gerenciar hosts de trabalho. Os agentes duráveis são ideais quando você precisa da flexibilidade da implantação de primeiro código combinada com o gerenciamento de estado durável.

Escolher um modelo de hospedagem

Modelo de hospedagem Escolha-o quando precisar
Azure Functions Um modelo de hospedagem gerenciado sem servidor; expansão interna e escala para zero; Azure Functions gatilhos e associações; Pontos de extremidade HTTP gerados pelo modelo de programação do Functions; o gatilho do servidor MCP; e gerenciamento mínimo de infraestrutura de host.
Traga sua própria computação/auto-hospedada Mais controle sobre o processo de host, o ambiente de implantação, o ciclo de vida de runtime, a infraestrutura, a rede, a autenticação ou a integração com um aplicativo ou serviço existente. Use esse modelo para contêineres, Kubernetes, trabalhos de longa execução, aplicativos de console, serviços personalizados ou ambientes de hospedagem que não sejam do Functions.

Quando hospedados no plano de hospedagem Azure Functions Flex Consumption, os agentes podem escalar para milhares de instâncias ou nenhuma instância quando fora de uso, permitindo que você pague apenas pela computação necessária. Em cenários auto-hospedados, seus próprios controles de host processam o tempo de vida, o dimensionamento, a rede e a implantação.

Como começar

Em um projeto .NET, escolha o conjunto de pacotes para o modelo de hospedagem.

Para Azure Functions hospedagem, adicione o pacote de integração Azure Functions e os pacotes de trabalho do 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 hospedagem de computação própria, adicione o pacote de integração de Tarefas Duráveis base e os pacotes de trabalho/cliente do Agendador de Tarefas Duráveis usados pelo host:

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

Em um projeto Python, escolha o pacote para seu modelo de hospedagem.

Para Azure Functions hospedagem, instale o pacote de integração Azure Functions.

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

Para hospedagem de computação própria, instale o pacote de integração da Tarefa Durável.

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

hospedagem Azure Functions

Com a Extensão Durável, você pode implantar e hospedar agentes do Microsoft Agent Framework em Azure Functions com pontos de extremidade HTTP internos e invocação baseada em orquestração. O Azure Functions fornece preços de pagamento por invocação controlados por evento com dimensionamento automático e gerenciamento mínimo de infraestrutura.

Quando você configura um agente durável em Azure Functions, a extensão cria automaticamente pontos de extremidade HTTP para seu agente e gerencia a infraestrutura subjacente para armazenar o estado da conversa, lidar com solicitações simultâneas e coordenar fluxos de trabalho de vários agentes. O Azure Functions integração de hospedagem também fornece conveniências específicas do Functions, como APIs REST geradas para enviar mensagens, verificar status e gerenciar sessões, além de gatilhos como o gatilho do servidor MCP para hospedar agentes como servidores MCP sem gravar 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 o uso de uma credencial específica (por exemplo, ManagedIdentityCredential) para evitar problemas de latência, investigação de credenciais não intencionais e possíveis riscos de segurança de mecanismos de fallback.

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])

Hospedagem bring-your-own-compute/self-hosted

Use a hospedagem bring-your-own-compute quando desejar os recursos de Extensão Durável sem usar o modelo de programação Azure Functions. Nesse modelo, seu processo inicia um trabalho de Tarefa Durável, registra agentes duráveis ou fluxos de trabalho e conecta-se a um back-end do Agendador de Tarefas Duráveis. O código do cliente pode ser executado no mesmo processo ou em um serviço separado.

Os trabalhadores auto-hospedados usam os mesmos principais recursos de Extensão Durável que Azure Functions hospedagem: ponto de verificação e retomada, orquestração de agente determinístico, fluxos de trabalho duráveis do Agent Framework, esperas humanas no loop, streaming confiável, limpeza de sessão ociosa, visibilidade do painel e execução distribuída entre instâncias de trabalho sem estado. Seu host é responsável por expor suas próprias APIs, gerenciamento de ciclo de vida, rede, autenticação e modelo de implantação.

Configure seu host com o pacote de integração de Tarefa Durável base. Use ConfigureDurableAgents para agentes duráveis e ConfigureDurableWorkflows para fluxos de trabalho do Microsoft Agent Framework baseados em grafo.

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 console .NET Durable Agents e < exemplos de console de fluxos de trabalho duráveis >.NET 1 para obter exemplos auto-hospedados executáveis.

Use o pacote de integração da Tarefa Durável para executar um processo de trabalho que registra agentes e escuta solicitações. O código do cliente pode se conectar ao mesmo hub de tarefas do Agendador de Tarefas Duráveis 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 Durable Task para obter exemplos de cliente de trabalho, incluindo hospedagem de agente único, roteamento de vários agentes, streaming confiável, encadeamento de orquestração, simultaneidade, condicional e padrões humanos no loop.

Fluxos de trabalho do Durable Agent Framework

A durabilidade não se limita a orquestrações duráveis. Microsoft fluxos de trabalho do Agent Framework criados com o modelo de fluxo de trabalho baseado em grafo também podem ser duráveis. A execução do fluxo de trabalho de pontos de verificação de Extensão Durável, portanto, as etapas concluídas do executor e do agente não são repetidas após uma reinicialização ou falha do processo.

Use orquestrações duráveis quando desejar coordenação imperativa com ramificação baseada em código, temporizadores, atividades e eventos externos. Use fluxos de trabalho duráveis do Agent Framework quando desejar um grafo declarativo de executores e agentes com roteamento digitado, fan-out/fan-in, bordas condicionais, eventos de fluxo de trabalho, estado compartilhado, sub-fluxos de trabalho ou portas de solicitação humanas no loop.

Note

Os fluxos de trabalho do Durable Agent Framework são diferentes do armazenamento de ponto de verificação em fluxos de trabalho padrão. O armazenamento de ponto de verificação ajuda a retomar uma execução de fluxo de trabalho no runtime do Agent Framework. A Extensão Durável executa o fluxo de trabalho na infraestrutura de Tarefa Durável para que o progresso do fluxo de trabalho seja verificado e recuperado entre os trabalhadores duráveis distribuídos. Para o ponto de verificação de fluxo de trabalho padrão, consulte Pontos de verificação e retomada.

Registre fluxos de trabalho baseados em grafo com ConfigureDurableWorkflows para aplicativos auto-hospedados ou ConfigureDurableWorkflows no construtor de aplicativos do Functions para hospedagem Azure Functions.

Confira os exemplos de Azure Functions de fluxos de trabalho duráveis .NET e .NET exemplos de console de fluxos de trabalho duráveis.

Exemplos de fluxo de trabalho duráveis estão disponíveis para hospedagem Azure Functions, incluindo estado compartilhado, nenhum estado compartilhado, execução de fluxo de trabalho paralelo e fluxos de trabalho humanos no loop.

Consulte os exemplos Python Azure Functions para exemplos de agente durável, orquestração, servidor MCP e fluxo de trabalho.

Samples

Linguagem Modelo de hospedagem Samples
C# Azure Functions .NET Durable Agents – Azure Functions, .NET Durable Workflows – Azure Functions
C# Traga sua própria computação/auto-hospedada .NET Durable Agents – Aplicativos de Console, .NET Durable Workflows – Aplicativos de Console
Python Azure Functions Python Azure Functions exemplos
Python Traga sua própria computação/auto-hospedada exemplos Python Durable Task

Threads de agente com estado com histórico de conversas

Os agentes mantêm threads persistentes que sobrevivem em várias interações. Cada thread é identificado por uma ID de thread exclusiva e armazena o histórico de conversa completo no armazenamento durável gerenciado pela infraestrutura de Tarefa Durável, como o Agendador de Tarefas Duráveis.

Esse padrão permite a continuidade da conversa em que o estado do agente é preservado por meio de falhas de processo e reinicializações, permitindo que o histórico completo de conversas seja mantido entre threads do usuário. O armazenamento durável garante que, mesmo que um processo de host reinicie ou o trabalho seja retomado em uma instância de trabalho diferente, a conversa continua diretamente de onde parou.

Use a limpeza de TTL (tempo de vida útil) da sessão para cargas de trabalho que precisam de continuidade durável durante o uso ativo, mas devem limpar automaticamente as conversas ociosas. A limpeza baseada em TTL impede que sessões não utilizados e o histórico de conversas se acumulem indefinidamente, preservando o estado da sessão ativa.

O exemplo de Azure Functions a seguir demonstra várias solicitações HTTP para o mesmo thread, mostrando como o contexto da conversa persiste. Em aplicativos auto-hospedados, use as APIs de cliente da Tarefa Durável de 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 no 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 a operação contínua.

Streaming confiável

A Extensão Durável dá suporte a streaming confiável para aplicativos que precisam de entrega de token em tempo real com garantias de entrega duráveis. O streaming pode ser usado com a extensão principal em ambos os modelos de hospedagem, mas os hosts distribuídos precisam de um agente de fluxo confiável, como o Redis, para que os fluxos de token possam ser entregues consistentemente entre reinicializações de processo, reconexões ou alterações de trabalho.

Use streaming confiável quando a experiência do usuário depender de respostas incrementais, mas a carga de trabalho ainda precisa de semântica de execução durável. Para obter exemplos executáveis, consulte os exemplos Python Durable Task, que incluem padrões de streaming confiáveis.

Orquestrações de vários agentes determinísticos

A Extensão Durável dá suporte à criação de fluxos de trabalho determinísticos que coordenam vários agentes usando orquestrações de Tarefa Durável. Em Azure Functions, elas usam orquestrações Durable Functions; em hosts de computação própria, são executados por meio do trabalho da Tarefa Durável e do cliente configurado.

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 maneira 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. Ao reproduzir o histórico de uma orquestração, você pode ver exatamente o que aconteceu em cada etapa.

As orquestrações executam de maneira 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 em que você precisa de ordem de execução garantida e tolerância a falhas.

Orquestrações sequenciais

No padrão sequencial de múltiplos agentes, agentes especializados operam em uma ordem específica, onde a saída de cada agente pode influenciar a operação do próximo agente. Esse padrão dá suporte à lógica condicional e ao branching com base nas respostas do agente.

Ao usar agentes em orquestrações, deve-se utilizar a context.GetAgent() API para obter uma instância de DurableAIAgent, que é uma subclasse específica do tipo padrão AIAgent, a qual encapsula um dos seus agentes registrados. O DurableAIAgent wrapper garante que as chamadas de agente sejam devidamente monitoradas e controladas 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 método app.get_agent() para obter uma instância de agente durável, que é um wrapper especial envolvendo um de seus agentes registrados. O wrapper de agente durável garante que as chamadas de agente sejam devidamente acompanhadas e marcadas pela estrutura 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

Orquestrações coordenam o trabalho entre vários agentes, sobrevivendo a falhas entre chamadas de agente. O contexto de orquestração fornece métodos para recuperar e interagir com agentes hospedados dentro de orquestrações.

Orquestrações paralelas

No padrão paralelo de vários agentes, você executa vários agentes simultaneamente e, em seguida, agrega seus resultados. Esse padrão é útil para reunir perspectivas diversas 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 é controlada usando uma lista de tarefas. O ponto de verificação automático garante que as execuções de agente concluídas não sejam repetidas ou perdidas se ocorrer uma falha durante a agregação.

Orquestrações humanas no loop

As orquestrações de agente determinístico podem pausar para entrada, aprovação ou revisão humanas sem consumir recursos de computação. A execução durável permite que as orquestrações aguardem dias ou até semanas enquanto aguardam respostas humanas. Quando combinados com a hospedagem sem servidor, todos os recursos de computação são reduzidos durante o período de espera, eliminando os custos de computação até que o humano forneça sua entrada.

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 aguardar eventos externos, mantendo de forma confiável seu estado enquanto esperam por feedback humano, sobrevivendo a falhas, reinicializações e períodos de espera prolongados. Quando a resposta humana chega, a orquestração é retomada automaticamente com o contexto completo da conversa e o estado de execução intactos.

Fornecendo entrada humana

Para enviar aprovação ou entrada para uma orquestração em espera, gere um evento externo para a instância de orquestração usando o SDK do cliente da Tarefa Durável ou os pontos de extremidade de extensão duráveis Azure Functions. Por exemplo, um revisor pode aprovar o 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)

Redução de custos

Fluxos de trabalho com humanos no loop com agentes duráveis são extremamente econômicos quando hospedados no plano Flex Consumption do Azure Functions. Para um fluxo de trabalho aguardando 24 horas pela aprovação, você paga apenas 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 agendador de tarefas duráveis

O DTS ( Durable Task Scheduler ) é o back-end durável recomendado para seus agentes duráveis, oferecendo o melhor desempenho, a infraestrutura totalmente gerenciada e a observabilidade interna por meio de um painel de interface do usuário. Azure Functions aplicativos podem usar outros back-ends de armazenamento (como Armazenamento do Azure), mas o DTS é otimizado especificamente para cargas de trabalho duráveis e fornece recursos de desempenho e monitoramento superiores. Os trabalhadores auto-hospedados também usam DTS para agendamento durável, estado e visibilidade do painel.

Insights de sessão do agente

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

Captura de tela do painel Agendador de Tarefas Duráveis mostrando o histórico de chat do agente com threads de conversa e mensagens.

Insights de orquestração

  • Visualização de vários agentes: consulte 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: acessar logs de execução detalhados
  • Monitoramento em tempo real: acompanhar orquestrações ativas, itens de trabalho enfileirados e estados de agente em sua implantação
  • Métricas de desempenho: Monitorar os tempos de resposta do agente, o uso de token e a duração da orquestração

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

Recursos de depuração

  • Exibir saídas de agente estruturadas e resultados de chamadas de ferramentas
  • Rastrear invocações de ferramentas e seus resultados
  • Monitorar o tratamento de eventos externos para cenários de intervenção humana

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

Tutorial: Criar e executar um agente durável com Azure Functions

Este tutorial mostra como criar e executar um agente de IA durável usando o modelo de hospedagem Azure Functions para a Extensão Durável. Você criará um aplicativo do Azure Functions que hospeda um agente com estado com pontos de extremidade HTTP internos e aprenderá a monitorá-lo usando o painel do Agendador de Tarefas Duráveis. Para agentes auto-hospedados, consulte os exemplos.

Pré-requisitos

Antes de começar, verifique se você tem os seguintes pré-requisitos:

Note

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

Baixar o projeto de início rápido

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

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

    mkdir MyDurableAgent
    cd MyDurableAgent
    

  1. Inicialize o projeto do modelo:

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

    Quando solicitado a obter um nome de ambiente, insira 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 Azure Functions, 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 do modelo:

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

    Quando solicitado a obter um nome de ambiente, insira um nome como my-durable-agent.

  2. Criar e ativar um ambiente virtual:

    uv venv .venv
    source .venv/bin/activate
    

Note

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

  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 Azure Functions, o código do agente e a infraestrutura como modelos de código. Ele também prepara um ambiente virtual com as dependências necessárias.

Provisionar recursos do Azure

Utilize a CLI do Desenvolvedor do Azure (Azure Developer CLI) para criar os recursos necessários do Azure para o seu agente durável.

  1. Prepare a infraestrutura:

    azd provision
    

    Este comando cria:

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

O processo de provisionamento leva alguns minutos. Depois de concluído, o azd armazena as informações de recurso criadas em seu ambiente.

Examinar o código do agente

Agora vamos examinar o código que define seu agente persistente.

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

Esse código:

  1. Recupera a configuração do Azure OpenAI de variáveis de ambiente.
  2. Cria um cliente do Azure OpenAI usando credenciais do Azure.
  3. Cria um agente de IA com instruções e um nome.
  4. Configura o aplicativo de funções do Azure para hospedar o agente com gerenciamento 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])

Esse código:

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

O agente agora está pronto para ser hospedado no Azure Functions. A extensão de tarefa durável cria automaticamente endpoints HTTP para interagir com seu agente e gerencia o estado da conversação em múltiplas requisições.

Configurar as 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 endpoint do Azure OpenAI dos recursos provisionados:

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

Seu local.settings.json deve ser como este:

{
  "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 somente para desenvolvimento local e não é implantado no Azure. Para implantações de produção, essas configurações são automaticamente configuradas em seu aplicativo do Azure Functions 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 Azure Functions para gerenciar gatilhos e estado interno).
  • Emulador do DTS (Durable Task Scheduler): gerencia o estado durável (histórico da conversa, estado de orquestração) e agendamento para seus agentes

Iniciar o Azurite

O Azurite emula os serviços de Armazenamento do Azure localmente. O Azure Functions o usa para gerenciar o estado interno. Você precisará executar isso em uma nova janela de terminal e mantê-la em execução enquanto desenvolve e testa seu agente durável.

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

    docker pull mcr.microsoft.com/azure-storage/azurite
    
  2. Inicie o Azurite em uma janela de terminal:

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

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

Mantenha essa janela do terminal aberta enquanto estiver desenvolvendo e testando seu agente durável.

Dica

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

Iniciar o emulador do Agendador de Tarefas Duráveis

O emulador DTS fornece um back-end confiável para gerenciar o estado do agente e as orquestrações. Ele armazena o histórico das conversas e garante que o estado do agente persista durante reinicializações. Ele também inicia orquestrações persistentes e agentes. Você precisará executar isso em uma nova janela de terminal separada e mantê-la em execução enquanto desenvolve e testa seu agente durável.

  1. Abra outra janela do terminal e faça um pull da imagem Docker do emulador do 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 ponto de extremidade gRPC do Agendador de Tarefas Duráveis (usado pelo aplicativo de Funções)
    • Porta 8082: O painel administrativo
  3. O painel estará disponível em http://localhost:8082.

Mantenha essa janela do terminal aberta enquanto estiver desenvolvendo e testando seu agente durável.

Dica

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áveis.

Executar o aplicativo de funções

Agora você está pronto para executar seu aplicativo do Azure Functions 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 runtime do Azure Functions:

    func start
    
  3. Você deverá ver a saída indicando que seu aplicativo de funções está em execução, incluindo os pontos de extremidade HTTP para 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 localmente

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

Iniciar uma nova conversa

Crie um novo thread 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?"

Resposta de exemplo (observe que o x-ms-thread-id cabeçalho contém a 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 da thread do cabeçalho x-ms-thread-id (por exemplo, @dafx-mydurableagent@263fa373-fa01-4705-abf2-5a114c2bb87d) para a próxima solicitação.

Continuar a conversa

Envie uma mensagem de acompanhamento para o mesmo thread, incluindo a 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 pela ID do thread real do cabeçalho da x-ms-thread-id resposta anterior.

Resposta de exemplo:

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ções ou a conversa for retomada por uma instância diferente.

Monitore com o painel do Agendador de Tarefas Duráveis

O Agendador de Tarefas Duráveis fornece um painel interno para monitorar e depurar 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.

Acessar o painel

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

  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 Habilitar páginas do Agente em Recursos de Visualização está selecionada.

Explorar conversas do agente

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

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

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

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

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

  • Marcadores de tempo e duração para cada interação
  • Conteúdo de prompt e resposta
  • Número de tokens usados

Dica

O painel DTS fornece atualizações em tempo real, para que você possa observar o comportamento do 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
    

    Esse comando empacota seu aplicativo e o implanta no aplicativo do Azure Functions criado durante o provisionamento.

  2. Aguarde até que a implantação seja concluída. A saída confirmará quando seu agente estiver rodando no Azure.

Testar o agente implantado

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

Obter a chave de função

O Azure Functions requer uma chave de API para funções disparadas 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`

Iniciar 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 tópico retornado no cabeçalho de resposta x-ms-thread-id.

Continuar a conversa no Azure

Envie uma mensagem de acompanhamento no mesmo thread. Substitua <thread-id> pela 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 da mesma forma como fazia localmente, demonstrando a durabilidade do estado do agente.

Monitorar 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 instância do Agendador de Tarefas Duráveis:

    azd env get-value DTS_NAME
    
  2. Abra o portal do Azure e pesquise 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. Exiba as conversas do agente da mesma forma que você fez com o emulador local.

O painel hospedado pelo Azure fornece os mesmos recursos de depuração e monitoramento do 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 Azure Functions

Este tutorial mostra como orquestrar vários agentes duráveis de IA usando o modelo de hospedagem Azure Functions e o padrão fan-out/fan-in. Você estenderá o agente durável do tutorial anterior para criar um sistema de vários agentes que processa a pergunta de um usuário e converterá a resposta em vários idiomas simultaneamente. Para obter exemplos de orquestração auto-hospedada, consulte os exemplos.

Noções básicas sobre o padrão de orquestração

A orquestração que você criará 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 pergunta
  3. Fan-out – A resposta do agente principal é enviada simultaneamente a 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 consolidados em uma única resposta JSON com a resposta e as traduções originais

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

Registrar agentes no início

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

Atualize-o Program.cs para registrar os agentes de tradução junto 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 function_app.py para registrar os agentes de tradução junto 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. Ele recupera agentes registrados do contexto durável e orquestra sua execução, chamando primeiro o agente principal e, em seguida, acionando simultaneamente os agentes de tradução.

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 arquivo function_app.py :

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

Testar a orquestração

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

  • Azurite em uma janela de terminal
  • Emulador do Agendador de Tarefas Durável em outra janela do terminal

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

  1. Inicie seu aplicativo do Azure Functions em uma nova janela de terminal:

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

    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 statusQueryGetUri (substitua abc123def456 pela ID da instância):

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

  1. Sondar o ponto de extremidade do status até que runtimeStatus seja Completed. Quando estiver concluído, você verá a saída de orquestração com a resposta do agente principal e 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..."
      }
    }
    

Monitorar a orquestração no painel

O painel do Agendador de Tarefas Durável oferece visibilidade na sua orquestração.

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

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

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

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

  5. Selecione a instância para ver:

    • A linha do tempo de orquestração
    • Execução do agente principal seguida por agentes de tradução simultâneos
    • Cada execução de agente (MyDurableAgent, depois tradutores franceses e espanhóis)
    • Padrões de fan-out e fan-in visualizados
    • Tempo e duração para cada etapa

Implantar a orquestração no Azure

Implante o aplicativo atualizado usando a CLI do Desenvolvedor do Azure:

azd deploy

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

Testar a orquestração implantada

Após a implantação, teste a 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 interna:

    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 exibir os resultados com traduções.

Próximas Etapas 

Recursos adicionais: