Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A extensão de tarefa durável do Microsoft Agent Framework permite que você crie agentes de IA com estado e orquestrações determinísticas de vários agentes em um ambiente sem servidor no Azure.
O Azure Functions é um serviço de computação sem servidor que permite executar código sob demanda sem gerenciar a infraestrutura. A extensão de tarefa durável baseia-se nessa base para fornecer gerenciamento de estado durável, o que significa que o histórico de conversas e o estado de execução do agente são mantidos de forma confiável e sobrevivem a falhas, reinicializações e operações de longa execução.
Visão geral
Os agentes duráveis combinam o poder do Agent Framework com o Azure Durable Functions para criar agentes que:
- Manter o estado automaticamente entre invocações de função
- Retomar após falhas sem perder o contexto da conversa
- Dimensionar automaticamente com base na demanda
- Orquestrar fluxos de trabalho de vários agentes com garantias de execução confiáveis
Quando usar agentes duráveis
Escolha agentes duráveis quando precisar:
- Controle de código completo: implantar e gerenciar seu próprio ambiente de computação, mantendo benefícios sem servidor
- 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 do Azure Functions (HTTP, temporizadores, filas etc.) e associações para fluxos de trabalho de agente controlados por eventos
- 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
Essa abordagem de hospedagem sem servidor difere da hospedagem gerenciada de agente baseado em serviço (como o Azure AI Foundry Agent Service), que fornece infraestrutura totalmente gerenciada sem exigir que você implante ou gerencie aplicativos do Azure Functions. Os agentes duráveis são ideais quando você precisa da flexibilidade da implantação baseada em código combinada com a confiabilidade da gestão de estado persistente.
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.
Como começar
Em um projeto do .NET Azure Functions, adicione os pacotes NuGet necessários.
dotnet add package Azure.AI.OpenAI --prerelease
dotnet add package Azure.Identity
dotnet add package Microsoft.Agents.AI.OpenAI --prerelease
dotnet add package Microsoft.Agents.AI.Hosting.AzureFunctions --prerelease
Observação
Além desses pacotes, verifique se seu projeto usa a versão 2.2.0 ou posterior do pacote Microsoft.Azure.Functions.Worker .
Em um projeto do Python Azure Functions, instale os pacotes do Python necessários.
pip install azure-identity
pip install agent-framework-azurefunctions --pre
Hospedagem sem servidor
Com a extensão de tarefa durável, você pode implantar e hospedar agentes do Microsoft Agent Framework no Azure Functions com pontos de extremidade HTTP integrados e invocação baseada em orquestração de tarefas. 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, a extensão de tarefa durável cria automaticamente pontos de extremidade HTTP para seu agente e gerencia toda a infraestrutura subjacente para armazenar o estado da conversa, lidar com solicitações simultâneas e coordenar fluxos de trabalho de vários agentes.
using System;
using Azure.AI.OpenAI;
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 AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
.GetChatClient(deploymentName)
.AsAIAgent(
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();
import os
from agent_framework.azure import AzureOpenAIChatClient, AgentFunctionApp
from azure.identity import DefaultAzureCredential
endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
deployment_name = os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4o-mini")
# Create an AI agent following the standard Microsoft Agent Framework pattern
agent = AzureOpenAIChatClient(
endpoint=endpoint,
deployment_name=deployment_name,
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])
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 pelo 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 a instância do Azure Functions reinicie ou seja dimensionada para uma instância diferente, a conversa continua diretamente de onde parou.
O exemplo a seguir demonstra várias solicitações HTTP para o mesmo thread, mostrando como o contexto da conversa persiste:
# 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.
Orquestrações de vários agentes determinísticos
A extensão de tarefas duráveis suporta a criação de fluxos de trabalho determinísticos que coordenam vários agentes usando orquestrações do Azure Durable Functions.
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 do Durable 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)
Eficiência de custo
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. Embora o Azure Functions possa usar outros back-ends de armazenamento (como o Armazenamento do Azure), o DTS é otimizado especificamente para cargas de trabalho duráveis e fornece recursos de desempenho e monitoramento superiores.
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
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
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
Este tutorial mostra como criar e executar um agente de IA durável usando a extensão de tarefa durável para o Microsoft Agent Framework. 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.
Pré-requisitos
Antes de começar, verifique se de que tem os seguintes pré-requisitos:
- SDK do .NET 9.0 ou posterior
- Ferramentas Principais do Azure Functions v4.x
- CLI do Azure Developer CLI
- CLI do Azure instalada e autenticada
- Docker Desktop instalado e em execução (para desenvolvimento local com o Azurite e o emulador do Agendador de Tarefas Duráveis)
- Uma assinatura do Azure com permissões para criar recursos
Observação
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.
- Python 3.10 ou posterior
- Ferramentas Principais do Azure Functions v4.x
- CLI do Azure Developer CLI
- CLI do Azure instalada e autenticada
- Docker Desktop instalado e em execução (para desenvolvimento local com o Azurite e o emulador do Agendador de Tarefas Duráveis)
- Uma assinatura do Azure com permissões para criar recursos
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.
Crie um novo diretório para seu projeto e navegue até ele:
mkdir MyDurableAgent cd MyDurableAgent
Inicialize o projeto do modelo:
azd init --template durable-agents-quickstart-dotnetQuando 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.
Crie um novo diretório para seu projeto e navegue até ele:
mkdir MyDurableAgent cd MyDurableAgent
Inicialize o projeto do modelo:
azd init --template durable-agents-quickstart-pythonQuando solicitado a obter um nome de ambiente, insira um nome como
my-durable-agent.Criar e ativar um ambiente virtual:
python3 -m venv .venv source .venv/bin/activate
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.
Prepare a infraestrutura:
azd provisionEste 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 Azure Storage 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
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.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting.AzureFunctions;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Hosting;
using OpenAI;
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 AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
.GetChatClient(deploymentName)
.AsAIAgent(
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:
- 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.
Abra function_app.py para ver a configuração do agente:
import os
from agent_framework.azure import AzureOpenAIChatClient, AgentFunctionApp
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_DEPLOYMENT_NAME", "gpt-4o-mini")
# Create an AI agent following the standard Microsoft Agent Framework pattern
agent = AzureOpenAIChatClient(
endpoint=endpoint,
deployment_name=deployment_name,
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.
Copie o arquivo de configurações de exemplo:
cp local.settings.sample.json local.settings.json
Obtenha o endpoint do Azure OpenAI dos recursos provisionados:
azd env get-value AZURE_OPENAI_ENDPOINTAbra
local.settings.jsone substitua<your-resource-name>no valorAZURE_OPENAI_ENDPOINTpelo 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"
}
}
Observação
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.
Abra uma nova janela do terminal e puxe a imagem Docker do Azurite.
docker pull mcr.microsoft.com/azure-storage/azuriteInicie o Azurite em uma janela de terminal:
docker run -p 10000:10000 -p 10001:10001 -p 10002:10002 mcr.microsoft.com/azure-storage/azuriteO 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.
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:latestExecute o emulador DTS:
docker run -p 8080:8080 -p 8082:8082 mcr.microsoft.com/dts/dts-emulator:latestEste 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
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.
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.
Inicie o runtime do Azure Functions:
func startVocê 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 localmente o agente
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
Abra o painel do emulador DTS local no navegador da Web em
http://localhost:8082.Selecione o hub de tarefas padrão na lista para exibir seus detalhes.
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
No painel, navegue até a guia Agentes .
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.
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.
Implante o aplicativo:
azd deployEsse comando empacota seu aplicativo e o implanta no aplicativo do Azure Functions criado durante o provisionamento.
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.
Obtenha o nome da instância do Agendador de Tarefas Duráveis:
azd env get-value DTS_NAMEAbra o portal do Azure e pesquise o nome do Agendador de Tarefas Duráveis da etapa anterior.
Na folha de visão geral do recurso Agendador de Tarefas Duráveis, selecione o hub de tarefas padrão na lista.
Selecione Abrir Painel na parte superior da página do hub de tarefas para abrir o painel de monitoramento.
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
Este tutorial mostra como orquestrar vários agentes duráveis de IA usando 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.
Noções básicas sobre o padrão de orquestração
A orquestração que você criará segue este fluxo:
- Entrada do usuário – Uma pergunta ou mensagem do usuário
-
Agente principal – O
MyDurableAgentdo primeiro tutorial processa a pergunta - Fan-out – A resposta do agente principal é enviada simultaneamente a ambos os agentes de tradução
- Agentes de tradução - Dois agentes especializados traduzem a resposta (francês e espanhol)
- 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.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting.AzureFunctions;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.Hosting;
using OpenAI;
using OpenAI.Chat;
// 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 Azure OpenAI client
AzureOpenAIClient client = new(new Uri(endpoint), new DefaultAzureCredential());
ChatClient chatClient = client.GetChatClient(deploymentName);
// Create the main agent from the first tutorial
AIAgent mainAgent = chatClient.AsAIAgent(
instructions: "You are a helpful assistant that can answer questions and provide information.",
name: "MyDurableAgent");
// Create translation agents
AIAgent frenchAgent = chatClient.AsAIAgent(
instructions: "You are a translator. Translate the following text to French. Return only the translation, no explanations.",
name: "FrenchTranslator");
AIAgent spanishAgent = chatClient.AsAIAgent(
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 AzureOpenAIChatClient, AgentFunctionApp
# 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_DEPLOYMENT", "gpt-4o-mini")
# Create the Azure OpenAI client
chat_client = AzureOpenAIChatClient(
endpoint=endpoint,
deployment_name=deployment_name,
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:
Inicie seu aplicativo do Azure Functions em uma nova janela de terminal:
func startA 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?\""'
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" }Consulte o status da orquestração usando
statusQueryGetUri(substituaabc123def456pela ID da instância):curl http://localhost:7071/runtime/webhooks/durabletask/instances/abc123def456
Sondar o ponto de extremidade do status até que
runtimeStatussejaCompleted. 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.
Abra
http://localhost:8082no navegador.Selecione o hub de tarefas "padrão".
Selecione a guia "Orquestrações".
Localize sua instância de orquestração na lista.
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.
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)
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?\""'
- Use o
statusQueryGetUrida resposta para verificar a conclusão e exibir os resultados com traduções.
Próximas etapas
Recursos adicionais: