Freigeben über


Azure-Funktionen (dauerhaft)

Die dauerhafte Aufgabenerweiterung für das Microsoft-Agenten-Framework ermöglicht es Ihnen, zustandsbehaftete KI-Agenten und deterministische Orchestrierungen in einer serverlosen Umgebung auf Azure zu erstellen.

Azure Functions ist ein serverloser Computedienst, mit dem Sie Code bei Bedarf ausführen können, ohne die Infrastruktur zu verwalten. Die dauerhafte Aufgabenerweiterung baut auf dieser Grundlage auf, um eine dauerhafte Zustandsverwaltung bereitzustellen, was bedeutet, dass der Unterhaltungsverlauf und der Ausführungszustand Ihres Agents zuverlässig beibehalten werden und Fehler, Neustarts und lange ausgeführte Vorgänge überleben.

Überblick

Dauerhafte Agents kombinieren die Leistungsfähigkeit von Agent Framework mit Azure Durable Functions, um Agents zu erstellen, die:

  • Status automatisch über Funktionsaufrufe hinweg beibehalten
  • Fortsetzen nach Fehlern ohne Verlust des Unterhaltungskontexts
  • Automatische Skalierung basierend auf Bedarf
  • Koordinieren von Multi-Agent-Workflows mit zuverlässigen Ausführungsgarantien

Verwendung von dauerhaften Agenten

Wählen Sie dauerhafte Agents aus, wenn Sie folgendes benötigen:

  • Vollständige Codekontrolle: Bereitstellen und Verwalten Ihrer eigenen Computeumgebung bei gleichzeitiger Aufrechterhaltung von serverlosen Vorteilen
  • Komplexe Orchestrierungen: Koordinieren mehrerer Agents mit deterministischen, zuverlässigen Workflows, die tage- oder wochenlang ausgeführt werden können
  • Ereignisgesteuerte Orchestrierung: Integration mit Azure Functions Triggern (HTTP, Timer, Warteschlangen usw.) und Bindungen für ereignisgesteuerte Agent-Workflows
  • Automatischer Unterhaltungszustand: Der Verlauf der Agentunterhaltung wird automatisch verwaltet und beibehalten, ohne dass eine explizite Verwaltung des Zustands in Ihrem Code erforderlich ist.

Dieser serverlose Hostingansatz unterscheidet sich von verwaltetem dienstbasiertem Agent-Hosting (z. B. Azure AI Foundry Agent Service), der vollständig verwaltete Infrastruktur bereitstellt, ohne dass Sie Azure Functions-Apps bereitstellen oder verwalten müssen. "Permanente Agenten sind ideal, wenn Sie die Flexibilität einer Code-orientierten Bereitstellung mit der Zuverlässigkeit einer persistenten Zustandsverwaltung kombinieren müssen."

Wenn Sie im Hostingplan für Azure Functions Flex Consumption gehostet werden, können Agents auf Tausende von Instanzen oder auf Nullinstanzen skalieren, wenn sie nicht verwendet werden, sodass Sie nur für die berechnung bezahlen können, die Sie benötigen.

Erste Schritte

Fügen Sie in einem .NET Azure Functions-Projekt die erforderlichen NuGet-Pakete hinzu.

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

Hinweis

Stellen Sie zusätzlich zu diesen Paketen sicher, dass Ihr Projekt Version 2.2.0 oder höher des Microsoft.Azure.Functions.Worker-Pakets verwendet.

Installieren Sie in einem Python Azure Functions-Projekt die erforderlichen Python-Pakete.

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

Serverloses Hosting

Mit der dauerhaften Aufgabenerweiterung können Sie Microsoft Agent Framework-Agents in Azure Functions mit integrierten HTTP-Endpunkten und orchestrierungsbasiertem Aufruf bereitstellen und hosten. Azure Functions bietet ein ereignisgesteuertes, nutzungsabhängiges Preismodell mit automatischer Skalierung und minimalem Infrastrukturmanagement.

Wenn Sie einen dauerhaften Agenten konfigurieren, erstellt die dauerhafte Aufgaben-Erweiterung automatisch HTTP-Endpunkte für Ihren Agenten und verwaltet die zugrunde liegende Infrastruktur zum Speichern des Unterhaltungszustands, zum Behandeln gleichzeitiger Anforderungen und zur Koordination von Workflows mit mehreren Agenten.

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

Statusbehaftete Agent-Threads mit Unterhaltungsverlauf

Agents verwalten persistente Threads, die über mehrere Interaktionen hinweg überleben. Jeder Thread wird durch eine eindeutige Thread-ID identifiziert und speichert den gesamten Unterhaltungsverlauf im dauerhaften Speicher, der vom Durable Task Scheduler verwaltet wird.

Dieses Muster ermöglicht die Unterhaltungskontinuität, bei der der Agentstatus durch Prozessabstürzen und Neustarts beibehalten wird, sodass der vollständige Unterhaltungsverlauf über Benutzerthreads hinweg verwaltet werden kann. Der dauerhafte Speicher stellt sicher, dass die Unterhaltung auch dann nahtlos fortgesetzt wird, wenn Ihre Azure Functions-Instanz neu gestartet oder auf eine andere Instanz skaliert wird.

Im folgenden Beispiel werden mehrere HTTP-Anforderungen an denselben Thread veranschaulicht, die zeigen, wie der Unterhaltungskontext beibehalten wird:

# 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!

Der Agentstatus wird im dauerhaften Speicher beibehalten und ermöglicht die verteilte Ausführung über mehrere Instanzen hinweg. Jede Instanz kann die Ausführung eines Agents nach Unterbrechungen oder Fehlern fortsetzen und den kontinuierlichen Betrieb sicherstellen.

Deterministische Multi-Agent-Orchestrierungen

Die dauerhafte Aufgabenerweiterung unterstützt das Erstellen deterministischer Workflows, die mehrere Agents mithilfe von Azure Durable Functions-Orchestrierungen koordinieren.

Orchestrierungen sind codebasierte Workflows, die mehrere Vorgänge (z. B. Agentaufrufe, externe API-Aufrufe oder Timer) zuverlässig koordinieren. Deterministisch bedeutet, dass der Orchestrierungscode bei der Wiedergabe nach einem Fehler auf die gleiche Weise ausgeführt wird, was Workflows zuverlässig und debuggierbar macht – wenn Sie den Verlauf einer Orchestrierung wiedergeben, können Sie genau sehen, was bei jedem Schritt passiert ist.

Orchestrierungen werden zuverlässig durchgeführt, überstehen Ausfälle zwischen Agentaufrufen und bieten vorhersehbare und wiederholbare Prozesse. Dies macht sie ideal für komplexe Multi-Agent-Szenarien, in denen Sie eine garantierte Ausführungsreihenfolge und Fehlertoleranz benötigen.

Sequenzielle Orchestrierungen

Im sequenziellen Multi-Agent-Muster werden spezialisierte Agents in einer bestimmten Reihenfolge ausgeführt, in der die Ausgabe jedes Agents die Ausführung des nächsten Agents beeinflussen kann. Dieses Muster unterstützt bedingte Logik und Verzweigung basierend auf Agentantworten.

Wenn Sie Agents in Orchestrierungen verwenden, müssen Sie die context.GetAgent() API verwenden, um eine Instanz abzurufen, bei der es sich um eine DurableAIAgent spezielle Unterklasse des Standardtyps AIAgent handelt, der einen Ihrer registrierten Agents umschließt. Der DurableAIAgent Wrapper stellt sicher, dass Agentaufrufe vom dauerhaften Orchestrierungsframework ordnungsgemäß nachverfolgt und überprüft werden.

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

Wenn Sie Agenten in Orchestrierungen verwenden, müssen Sie die app.get_agent() Methode verwenden, um eine dauerhafte Agenteninstanz zu erhalten, die ein spezieller Wrapper um einen Ihrer registrierten Agenten ist. Der dauerhafte Agentwrapper stellt sicher, dass Agentaufrufe vom dauerhaften Orchestrierungsframework ordnungsgemäß nachverfolgt und überprüft werden.

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

Orchestrierungen koordinieren die Arbeit mehrerer Agenten und überstehen Fehler zwischen Agentenanrufen. Der Orchestrierungskontext stellt Methoden zum Abrufen und Interagieren mit gehosteten Agents innerhalb von Orchestrierungen bereit.

Parallele Orchestrierungen

Im parallelen Multi-Agent-Muster führen Sie mehrere Agents gleichzeitig aus und aggregieren dann deren Ergebnisse. Dieses Muster ist nützlich, um verschiedene Perspektiven zu sammeln oder unabhängige Teilvorgänge gleichzeitig zu verarbeiten.

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', '')

Die parallele Ausführung wird mithilfe einer Liste von Aufgaben nachverfolgt. Durch die automatische Prüfpunkterstellung wird sichergestellt, dass abgeschlossene Agenten-Ausführungen nicht wiederholt oder verloren gehen, wenn während der Aggregierung ein Fehler auftritt.

Human-in-the-Loop-Orchestrierungen

Deterministische Agent-Orchestrierungen können für menschliche Eingaben, Genehmigungen oder Überprüfungen anhalten, ohne Rechenressourcen zu verbrauchen. Dauerhafte Ausführung ermöglicht es Orchestrierungen, Tage oder sogar Wochen zu warten, während sie auf menschliche Reaktionen warten. In Kombination mit serverless Hosting werden alle Rechenressourcen während der Wartezeit heruntergefahren, wodurch die Rechenkosten vermieden werden, bis der Benutzer seine Eingabe bereitstellt.

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

Deterministische Agent-Orchestrierungen können auf externe Ereignisse warten und ihren Zustand dauerhaft speichern, während sie auf menschliches Feedback warten, Fehler überstehen und Neustarts sowie erweiterte Wartezeiten überdauern. Wenn die menschliche Antwort eingeht, wird der Orchestrierungsvorgang automatisch fortgesetzt, wobei der vollständige Unterhaltungskontext und der Ausführungszustand intakt sind.

Bereitstellen von menschlichen Eingaben

Um genehmigungs- oder Eingaben an eine Warteoperation zu senden, lösen Sie ein externes Ereignis mit dem Client-SDK für dauerhafte Funktionen an die Orchestrierungsinstanz aus. Beispielsweise kann ein Prüfer Inhalte über ein Webformular genehmigen, das Folgendes aufruft:

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)

Kosteneffizienz

Human-in-the-Loop-Workflows mit dauerhaften Agents sind extrem kostengünstig, wenn sie im Azure Functions Flex Consumption-Plan gehostet werden. Für einen Workflow, der 24 Stunden auf die Genehmigung wartet, zahlen Sie nur einige Sekunden Ausführungszeit (die Zeit zum Generieren von Inhalten, Senden von Benachrichtigungen und Verarbeiten der Antwort) – nicht die 24 Stunden wartezeit. Während des Wartezeitzeitraums werden keine Computeressourcen verbraucht.

Überwachbarkeit mit dem Durable Task Scheduler

Der Durable Task Scheduler (DTS) ist das empfohlene dauerhafte Back-End für Ihre dauerhaften Agents, das die beste Leistung, vollständig verwaltete Infrastruktur und integrierte Observierbarkeit über ein UI-Dashboard bietet. Während Azure Functions andere Speicher-Back-Ends (z. B. Azure Storage) verwenden kann, ist DTS speziell für dauerhafte Workloads optimiert und bietet überlegene Leistungs- und Überwachungsfunktionen.

Einblicke in die Agentsitzung

  • Aufgezeichnete Unterhaltungen: Anzeigen des vollständigen Chatverlaufs für jede Agentsitzung, einschließlich aller Nachrichten, Toolanrufe und Unterhaltungskontexte zu einem beliebigen Zeitpunkt
  • Aufgabenzeitmessung: Überwachen, wie lange bestimmte Aufgaben und Agentinteraktionen zur Fertigstellung benötigen

Screenshot des Dashboards

Orchestrierungserkenntnisse

  • Visualisierung mit mehreren Agents: Anzeigen des Ausführungsflusses beim Aufrufen mehrerer spezialisierter Agents mit visueller Darstellung paralleler Ausführung und bedingter Verzweigung
  • Ausführungsverlauf: Zugreifen auf detaillierte Ausführungsprotokolle
  • Echtzeitüberwachung: Verfolgen aktiver Orchestrierungen, Warteschlangen-Arbeitsaufgaben und Agentenzustände über Ihre gesamte Bereitstellung hinweg
  • Leistungsmetriken: Überwachen von Agentantwortzeiten, Tokenverwendung und Orchestrierungsdauer

Screenshot des Dashboards

Debuggingfunktionen

  • Anzeigen strukturierter Agent-Ausgaben und Toolaufrufergebnisse
  • Aufrufe von Tracing-Tools und deren Ergebnisse
  • Überwachung der Verarbeitung externer Ereignisse in Szenarien mit menschlicher Einbindung

Mit dem Dashboard können Sie genau verstehen, was Ihre Agents tun, Probleme schnell diagnostizieren und die Leistung basierend auf realen Ausführungsdaten optimieren.

Lernprogramm: Erstellen und Ausführen eines dauerhaften Agents

In diesem Lernprogramm erfahren Sie, wie Sie einen dauerhaften KI-Agent mithilfe der dauerhaften Aufgabenerweiterung für Microsoft Agent Framework erstellen und ausführen. Sie erstellen eine Azure Functions-App, die einen zustandsbehafteten Agent mit integrierten HTTP-Endpunkten hostet, und erfahren, wie Sie sie mithilfe des Dashboards für dauerhafte Aufgabenplanung überwachen.

Voraussetzungen

Stellen Sie sicher, dass die folgenden Voraussetzungen erfüllt sind, bevor Sie beginnen:

Hinweis

Microsoft Agent Framework wird mit allen aktiv unterstützten Versionen von .NET unterstützt. Für die Zwecke dieses Beispiels empfehlen wir das .NET 9 SDK oder eine höhere Version.

Herunterladen des Schnellstartprojekts

Verwenden Sie Azure Developer CLI, um ein neues Projekt aus der Schnellstartvorlage für dauerhafte Agenten zu initialisieren.

  1. Erstellen Sie ein neues Verzeichnis für Ihr Projekt, und navigieren Sie zu diesem Verzeichnis:

    mkdir MyDurableAgent
    cd MyDurableAgent
    

  1. Initialisieren Sie das Projekt aus der Vorlage:

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

    Wenn Sie zur Eingabe eines Umgebungsnamens aufgefordert werden, geben Sie einen Namen wie my-durable-agent.

Dadurch wird das Schnellstartprojekt mit allen erforderlichen Dateien heruntergeladen, einschließlich der Azure Functions-Konfiguration, des Agentcodes und der Infrastruktur als Codevorlagen.

  1. Erstellen Sie ein neues Verzeichnis für Ihr Projekt, und navigieren Sie zu diesem Verzeichnis:

    mkdir MyDurableAgent
    cd MyDurableAgent
    

  1. Initialisieren Sie das Projekt aus der Vorlage:

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

    Wenn Sie zur Eingabe eines Umgebungsnamens aufgefordert werden, geben Sie einen Namen wie my-durable-agent.

  2. Erstellen und Aktivieren einer virtuellen Umgebung:

    python3 -m venv .venv
    source .venv/bin/activate
    

  1. Installieren Sie die erforderlichen Pakete:

    python -m pip install -r requirements.txt
    

Dadurch wird das Schnellstartprojekt mit allen erforderlichen Dateien heruntergeladen, einschließlich der Azure Functions-Konfiguration, des Agentcodes und der Infrastruktur als Codevorlagen. Außerdem wird eine virtuelle Umgebung mit den erforderlichen Abhängigkeiten vorbereitet.

Bereitstellen von Azure-Ressourcen

Verwenden Sie azure Developer CLI, um die erforderlichen Azure-Ressourcen für Ihren dauerhaften Agent zu erstellen.

  1. Bereitstellen der Infrastruktur:

    azd provision
    

    Mit diesem Befehl wird Folgendes erstellt:

    • Ein Azure OpenAI-Dienst mit einer gpt-4o-mini-Bereitstellung
    • Eine Azure Functions-App mit Flex-Verbrauch-Hostingplan
    • Ein Azure Storage-Konto für die Laufzeit und den dauerhaften Speicher von Azure Functions
    • Eine Dauerhafte Task Scheduler-Instanz (Verbrauchsplan) zur Verwaltung des Agent-Zustands
    • Erforderliche Netzwerk- und Identitätskonfigurationen
  2. Wenn Sie dazu aufgefordert werden, wählen Sie Ihr Azure-Abonnement aus, und wählen Sie einen Speicherort für die Ressourcen aus.

Der Bereitstellungsprozess dauert einige Minuten. Nach Abschluss speichert azd die erstellten Ressourceninformationen in Ihrer Umgebung.

Überprüfen des Agenten-Codes

Sehen wir uns nun den Code an, der Ihren dauerhaften Agenten definiert.

Öffnen Program.cs , um die Agentkonfiguration anzuzeigen:

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

Für diesen Code gilt Folgendes:

  1. Ruft Ihre Azure OpenAI-Konfiguration aus Umgebungsvariablen ab.
  2. Erstellt einen Azure OpenAI-Client mit Azure-Anmeldeinformationen.
  3. Erstellt einen KI-Agent mit Anweisungen und einem Namen.
  4. Konfiguriert die Azure Functions-App so, dass der Agent mit dauerhafter Threadverwaltung gehostet wird.

Öffnen function_app.py , um die Agentkonfiguration anzuzeigen:

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

Für diesen Code gilt Folgendes:

  • Ruft Ihre Azure OpenAI-Konfiguration aus Umgebungsvariablen ab.
  • Erstellt einen Azure OpenAI-Client mit Azure-Anmeldeinformationen.
  • Erstellt einen KI-Agent mit Anweisungen und einem Namen.
  • Konfiguriert die Azure Functions-App so, dass der Agent mit dauerhafter Threadverwaltung gehostet wird.

Der Agent kann jetzt in Azure-Funktionen gehostet werden. Die dauerhafte Aufgabenerweiterung erstellt automatisch HTTP-Endpunkte für die Interaktion mit Ihrem Agenten und verwaltet den Gesprächsstatus über mehrere Anforderungen hinweg.

Konfigurieren lokaler Einstellungen

Erstellen Sie eine local.settings.json Datei für die lokale Entwicklung basierend auf der Beispieldatei, die im Projekt enthalten ist.

  1. Kopieren Sie die Beispieleinstellungsdatei:

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

  1. Rufen Sie Ihren Azure OpenAI-Endpunkt aus den bereitgestellten Ressourcen ab:

    azd env get-value AZURE_OPENAI_ENDPOINT
    
  2. Öffnen Sie local.settings.json und ersetzen Sie den Wert in <your-resource-name> durch den Endpunkt aus dem vorherigen Befehl.

Ihr local.settings.json sollte wie folgt aussehen:

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

Hinweis

Die local.settings.json Datei wird nur für die lokale Entwicklung verwendet und wird nicht in Azure bereitgestellt. Bei Produktionsbereitstellungen werden diese Einstellungen automatisch in Ihrer Azure Functions-App anhand der Infrastrukturvorlagen konfiguriert.

Starte lokale Entwicklungsumgebungsverbindungen

Um dauerhafte Agents lokal auszuführen, müssen Sie zwei Dienste starten:

  • Azurite: Emuliert Azure Storage-Dienste (verwendet von Azure Functions zum Verwalten von Triggern und internem Zustand).
  • Durable Task Scheduler (DTS)-Emulator: Verwaltet dauerhaften Zustand (Unterhaltungsverlauf, Orchestrierungszustand) und Planung für Ihre Agents

Starten Sie Azurite

Azurite emuliert Azure Storage-Dienste lokal. Die Azure-Funktionen verwenden sie zum Verwalten des internen Zustands. Sie müssen dies in einem neuen Terminalfenster ausführen und es im Hintergrund weiterlaufen lassen, während Sie Ihren persistenten Agenten entwickeln und testen.

  1. Öffnen Sie ein neues Terminalfenster, und ziehen Sie das Azurite Docker-Image:

    docker pull mcr.microsoft.com/azure-storage/azurite
    
  2. Starten Sie Azurite in einem Terminalfenster:

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

    Azurite beginnt und überwacht die Standardports für Blob-Dienste (10000), Warteschlange (10001) und Tabelle (10002).

Lassen Sie dieses Terminalfenster geöffnet, während Sie Ihren dauerhaften Agent entwickeln und testen.

Tipp

Weitere Informationen zu Azurite, einschließlich alternativer Installationsmethoden, finden Sie unter Verwenden des Azurite-Emulators für die lokale Azure Storage-Entwicklung.

Starten des Emulators "Durable Task Scheduler"

Der DTS-Emulator stellt das zuverlässige Back-End bereit, das für die Verwaltung des Agentenzustands und der Orchestrierungen zuständig ist. Er speichert den Gesprächsverlauf und stellt sicher, dass der Status Ihres Agenten über Neustarts hinweg beibehalten wird. Sie löst auch dauerhafte Orchestrierungen und Agenten aus. Sie müssen dies in einem separaten neuen Terminalfenster ausführen und laufen lassen, während Sie Ihren robusten Agenten entwickeln und testen.

  1. Öffnen Sie ein weiteres neues Terminalfenster, und ziehen Sie das Docker-Image des DTS-Emulators:

    docker pull mcr.microsoft.com/dts/dts-emulator:latest
    
  2. Führen Sie den DTS-Emulator aus:

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

    Dieser Befehl startet den Emulator und macht Folgendes verfügbar:

    • Port 8080: Der gRPC-Endpunkt für den Durable Task Scheduler (verwendet von Ihrer Functions-App)
    • Port 8082: Das Verwaltungsdashboard
  3. Das Dashboard ist verfügbar unter http://localhost:8082.

Lassen Sie dieses Terminalfenster geöffnet, während Sie Ihren dauerhaften Agent entwickeln und testen.

Tipp

Weitere Informationen zum DTS-Emulator, einschließlich der Konfiguration mehrerer Aufgabenhubs und des Zugriffs auf das Dashboard, finden Sie unter Develop with Durable Task Scheduler.

Führen Sie die Funktions-App aus

Jetzt können Sie Ihre Azure Functions-App mit dem dauerhaften Agent ausführen.

  1. Navigieren Sie in einem neuen Terminalfenster (wobei sowohl Azurite als auch der DTS-Emulator in separaten Fenstern ausgeführt wird), zu Ihrem Projektverzeichnis.

  2. Starten Sie die Azure Functions-Laufzeit:

    func start
    
  3. Es sollte eine Ausgabe angezeigt werden, die angibt, dass Ihre Funktions-App ausgeführt wird, einschließlich der HTTP-Endpunkte für Ihren Agent:

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

Diese Endpunkte verwalten den Unterhaltungszustand automatisch – Sie müssen keine Threadobjekte selbst erstellen oder verwalten.

Testen Sie den Agenten lokal

Jetzt können Sie mit Ihrem dauerhaften Agent mithilfe von HTTP-Anforderungen interagieren. Der Agent verwaltet den Gesprächsstatus über mehrere Anforderungen hinweg und ermöglicht mehrere Gesprächsrunden.

Beginnen einer neuen Unterhaltung

Erstellen Sie einen neuen Thread, und senden Sie Ihre erste Nachricht:

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

Beispielantwort (Beachten Sie, dass der x-ms-thread-id Header die Thread-ID enthält):

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.

Speichern Sie die Thread-ID aus dem x-ms-thread-id Header (z. B. @dafx-mydurableagent@263fa373-fa01-4705-abf2-5a114c2bb87d) für die nächste Anforderung.

Fortsetzen der Unterhaltung

Senden Sie eine Nachverfolgungsnachricht an denselben Thread, indem Sie die Thread-ID als Abfrageparameter einschließen:

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?"

Ersetzen Sie @dafx-mydurableagent@263fa373-fa01-4705-abf2-5a114c2bb87d durch die tatsächliche Thread-ID aus dem x-ms-thread-id-Header der vorherigen Antwort.

Beispielantwort:

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.

Beachten Sie, dass der Agent den Kontext aus der vorherigen Nachricht (die drei Programmiersprachen) merkt, ohne sie erneut angeben zu müssen. Da der Gesprächszustand dauerhaft vom Durable Task Scheduler gespeichert wird, bleibt dieser Verlauf erhalten, selbst wenn Sie die Funktion-App neu starten oder die Unterhaltung von einer anderen Instanz fortgesetzt wird.

Überwachen mit dem Dashboard "Durable Task Scheduler"

Der Durable Task Scheduler bietet ein integriertes Dashboard zum Überwachen und Debuggen Ihrer dauerhaften Agenten. Das Dashboard bietet umfassende Einblicke in die Tätigkeiten der Agenten, den Konversationsverlauf und die Ablauffolge.

Zugreifen auf das Dashboard

  1. Öffnen Sie das Dashboard für Ihren lokalen DTS-Emulator in http://localhost:8082 Ihrem Webbrowser.

  2. Wählen Sie den Standardmäßigen Aufgabenhub aus der Liste aus, um die Details anzuzeigen.

  3. Wählen Sie das Zahnradsymbol in der oberen rechten Ecke aus, um die Einstellungen zu öffnen, und stellen Sie sicher, dass die Option „Seiten für Agenten aktivieren“ unter „Vorschaufeatures“ ausgewählt ist.

Agentengespräche erkunden

  1. Navigieren Sie im Dashboard zur Registerkarte "Agents ".

  2. Wählen Sie Ihren dauerhaften Agent-Thread (z. B. mydurableagent - 263fa373-fa01-4705-abf2-5a114c2bb87d) aus der Liste aus.

    Sie sehen eine detaillierte Ansicht des Agentthreads, einschließlich des vollständigen Unterhaltungsverlaufs mit allen Nachrichten und Antworten.

    Screenshot des Dashboards

Das Dashboard bietet eine Zeitachsenansicht, mit der Sie den Fluss der Unterhaltung verstehen können. Zu den wichtigsten Informationen gehören:

  • Zeitstempel und Dauer für jede Interaktion
  • Eingabe- und Antwortinhalte
  • Anzahl der verwendeten Token

Tipp

Das DTS-Dashboard bietet Echtzeitupdates, sodass Sie das Verhalten Ihres Agents während der Interaktion mit dem Agent über die HTTP-Endpunkte beobachten können.

In Azure bereitstellen

Nachdem Sie Ihren dauerhaften Agent lokal getestet haben, stellen Sie ihn in Azure bereit.

  1. Bereitstellen der Anwendung:

    azd deploy
    

    Dieser Befehl verpackt Ihre Anwendung und stellt sie in der Azure Functions-App bereit, die während der Bereitstellung erstellt wurde.

  2. Warten Sie, bis die Bereitstellung abgeschlossen ist. Die Ausgabe bestätigt, ob Ihr Agent in Azure läuft.

Testen des bereitgestellten Agents

Testen Sie nach der Bereitstellung Ihren Agent, der in Azure ausgeführt wird.

Holen Sie die Funktionstaste

Azure Functions erfordert einen API-Schlüssel für HTTP-ausgelöste Funktionen in der Produktion:

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`

Starten einer neuen Unterhaltung in Azure

Erstellen Sie einen neuen Thread, und senden Sie Ihre erste Nachricht an den bereitgestellten Agent:

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?"

Beachten Sie die Thread-ID, die im x-ms-thread-id Antwortheader zurückgegeben wird.

Fortsetzen der Unterhaltung in Azure

Senden Sie eine Nachverfolgungsnachricht im selben Thread. Ersetzen Sie <thread-id> durch die Thread-ID aus der vorherigen Antwort:

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?"

Der Agent verwaltet den Unterhaltungskontext in Azure genauso wie lokal, was die Haltbarkeit des Agentstatus veranschaulicht.

Überwachen des bereitgestellten Agents

Sie können Ihren bereitgestellten Agent über das Dashboard "Durable Task Scheduler" in Azure überwachen.

  1. Rufen Sie den Namen Ihrer Permanent Task Scheduler-Instanz ab:

    azd env get-value DTS_NAME
    
  2. Öffnen Sie das Azure-Portal , und suchen Sie im vorherigen Schritt nach dem Namen des dauerhaften Vorgangsplaners.

  3. Wählen Sie im Übersichtsblatt der Ressource "Durable Task Scheduler" den Standardmäßigen Aufgabenhub aus der Liste aus.

  4. Wählen Sie oben auf der Aufgabenhubseite " Dashboard öffnen" aus, um das Überwachungsdashboard zu öffnen.

  5. Betrachten Sie die Unterhaltungen Ihres Agents genau wie mit dem lokalen Emulator.

Das von Azure gehostete Dashboard bietet die gleichen Debugging- und Überwachungsfunktionen wie der lokale Emulator, sodass Sie den Gesprächsverlauf betrachten, Aufrufe von Ablaufverfolgungstools einsehen und die Leistung in Ihrer Produktionsumgebung analysieren zu können.

Lernprogramm: Orchestrieren dauerhafter Agenten

In diesem Lernprogramm erfahren Sie, wie Sie mehrere dauerhafte KI-Agents mithilfe des Fan-out-/Fan-In-Musters orchestrieren. Sie erweitern den dauerhaften Agent aus dem vorherigen Lernprogramm , um ein Multi-Agent-System zu erstellen, das die Frage eines Benutzers verarbeitet, und übersetzt dann die Antwort gleichzeitig in mehrere Sprachen.

Grundlegendes zum Orchestrierungsmuster

Die Orchestrierung, die Sie erstellen, folgt diesem Fluss:

  1. Benutzereingabe – Eine Frage oder Nachricht des Benutzers
  2. Hauptagent - Der MyDurableAgent aus dem ersten Tutorial verarbeitet die Frage
  3. Fan-out – Die Antwort des Hauptagenten wird parallel an beide Übersetzungsagenten gesendet.
  4. Übersetzungsmitarbeiter - Zwei spezialisierte Agenten übersetzen die Antwort (Französisch und Spanisch)
  5. Fan-In - Ergebnisse werden in einer einzigen JSON-Antwort mit der ursprünglichen Antwort und Übersetzungen aggregiert.

Dieses Muster ermöglicht die gleichzeitige Verarbeitung, wodurch die Gesamtantwortzeit im Vergleich zur sequenziellen Übersetzung reduziert wird.

Agents beim Start registrieren

Um Agents ordnungsgemäß in dauerhaften Orchestrierungen zu verwenden, registrieren Sie sie beim Starten der Anwendung. Sie können für alle Orchestrierungsausführungen verwendet werden.

Aktualisieren Sie Ihre Program.cs, um die Übersetzungsagenten zusammen mit den vorhandenen MyDurableAgent zu registrieren.

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

Aktualisieren Sie Ihre function_app.py, um die Übersetzungsagenten zusammen mit den vorhandenen MyDurableAgent zu registrieren.

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

Erstellen einer Orchestrierungsfunktion

Eine Orchestrierungsfunktion koordiniert den Workflow über mehrere Agents hinweg. Sie ruft registrierte Agenten aus dem dauerhaften Kontext ab und koordiniert deren Ausführung, wobei sie zuerst den Hauptagenten aufruft und dann parallel Übersetzungsagenten aktiviert.

Erstellen Sie eine neue Datei mit dem Namen AgentOrchestration.cs in Ihrem Projektverzeichnis:

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;
    }
}

Fügen Sie die Orchestrierungsfunktion Ihrer function_app.py Datei hinzu.

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

Testen Sie die Orchestrierung

Stellen Sie sicher, dass Ihre lokalen Entwicklungsabhängigkeiten aus dem ersten Tutorial weiterhin ausgeführt werden:

  • Azurite in einem Terminalfenster
  • Emulator für dauerhafte Aufgabenplanung in einem anderen Terminalfenster

Während Ihre lokalen Entwicklungsabhängigkeiten laufen:

  1. Starten Sie Ihre Azure Functions-App in einem neuen Terminalfenster:

    func start
    
  2. Die Erweiterung "Durable Functions" erstellt automatisch integrierte HTTP-Endpunkte für die Verwaltung von Orchestrierungen. Starten Sie die Orchestrierung mithilfe der integrierten API:

    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. Die Antwort enthält URLs zum Verwalten der Orchestrierungsinstanz:

    {
      "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. Abfragen des Orchestrierungsstatus mithilfe des statusQueryGetUri (Ersetzen abc123def456 durch Ihre tatsächliche Instanz-ID):

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

  1. Abfragen des Statusendpunkts, bis runtimeStatusCompleted ist. Nach Abschluss sehen Sie die Orchestrierungsausgabe mit der Antwort des Hauptagenten und deren Übersetzungen.

    {
      "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..."
      }
    }
    

Überwachen Sie die Orchestrierung im Dashboard

Das Dashboard "Durable Task Scheduler" bietet Einblicke in Ihre Orchestrierung:

  1. Öffnen Sie http://localhost:8082 in Ihrem Browser.

  2. Wählen Sie den Aufgabenhub "Standard" aus.

  3. Wählen Sie die Registerkarte "Orchestrationen" aus.

  4. Finden Sie Ihre Orchestrierungsinstanz in der Liste.

  5. Wählen Sie die Instanz aus, die angezeigt werden soll:

    • Die Zeitachse der Orchestrierung
    • Haupt-Agent-Ausführung gefolgt von gleichzeitigen Übersetzungs-Agents
    • Jede Agentenausführung (MyDurableAgent, dann Französisch- und Spanischübersetzer)
    • Fan-Out- und Fan-In-Muster visualisiert
    • Zeitplanung und Dauer für jeden Schritt

Bereitstellen der Orchestrierung in Azure

Bereitstellen der aktualisierten Anwendung mithilfe der Azure Developer CLI:

azd deploy

Dadurch wird Ihr aktualisierter Code mit der neuen Orchestrierungsfunktion und zusätzlichen Agenten für die Azure Functions-App bereitgestellt, die im ersten Tutorial erstellt wurde.

Testen der bereitgestellten Orchestrierung

Testen Sie nach der Bereitstellung Ihre Orchestrierung, die in Azure ausgeführt wird.

  1. Rufen Sie den Systemschlüssel für die dauerhafte Erweiterung ab:

    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. Starten Sie die Orchestrierung mithilfe der integrierten API:

    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. Verwenden Sie die statusQueryGetUri Antwort aus der Antwort, um die Fertigstellung abzufragen und die Ergebnisse mit Übersetzungen anzuzeigen.

Nächste Schritte

Zusätzliche Ressourcen: