Erstellen von Multi-Agent-KI-Systemen mit dem Agent Framework von Microsoft

· 13 Min. Lesezeit

Einführung

Wir sind in die Ära der Multiagenten-KI-Systeme eingetreten. Anstelle einer einzigen monolithischen KI, die alles erledigt, setzt die Branche auf spezialisierte Agenten, die zusammenarbeiten, um komplexe Probleme zu lösen – ähnlich wie ein gut organisiertes Expertenteam. Ein Agent recherchiert, ein anderer analysiert, ein dritter schreibt und ein Koordinator hält alle auf dem Laufenden.

Wenn Sie mit großen Sprachmodellen gearbeitet haben, haben Sie wahrscheinlich die Grenze dessen erreicht, was eine einzelne Eingabeaufforderung leisten kann. Kontextfenster füllen sich, Anweisungen geraten durcheinander und die Qualität nimmt ab. Multi-Agenten-Architekturen lösen dieses Problem, indem sie komplexe Aufgaben in gezielte Verantwortlichkeiten zerlegen, wobei jeder Agent ein Experte für eine Sache ist.

Das Agent Framework von Microsoft, Teil des umfassenderen Semantic-Kernel-Ökosystems, bietet .NET-Entwicklern ein erstklassiges Toolkit zum Aufbau genau dieser Art von Systemen. In diesem Beitrag gehen wir von Null auf eine voll funktionsfähige Multi-Agent-Pipeline über und behandeln dabei die Kernkonzepte, Orchestrierungsmuster und den praktischen Code, den Sie für den Einstieg benötigen.

Was ist das Agent Framework von Microsoft?

Das Agent Framework ist Microsofts Antwort auf die Erstellung, Orchestrierung und Bereitstellung von KI-Agenten und Multiagentensystemen in .NET. Es liegt neben dem Semantic Kernel, der seit 2023 das Open-Source-SDK von Microsoft für die KI-Orchestrierung ist, und ist tief in diesen integriert.

Stellen Sie sich das so vor: Semantic Kernel stellt Ihnen die Grundelemente (Kernel, Plugins, Speicher, Planer) zur Verfügung, während das Agent Framework Ihnen Abstraktionen auf höherer Ebene bietet, die speziell für die Kommunikation und Koordination zwischen Agenten entwickelt wurden.

Das Framework unterstützt mehrere Modellanbieter, darunter Azure OpenAI, OpenAI und auf Azure AI Foundry gehostete Modelle. Das Design ist modellunabhängig, aber tief in das Azure-Ökosystem integriert, was es besonders für Unternehmensszenarien attraktiv macht.

Zu den wichtigsten Fähigkeiten gehören:

  • Mehrere Agententypen: ChatCompletionAgent, OpenAIAssistantAgent und AzureAIAgent für verschiedene Backends
  • Orchestrierungsmuster: Sequentielle, gleichzeitige, Übergabe- und Gruppenchat-Workflows
  • Plugin-Ökosystem: Erweitern Sie Agenten mit nativen C#-Funktionen, OpenAPI-Spezifikationen und Model Context Protocol (MCP)-Tools
  • Konversationsmanagement: Integrierte Threading-, Verlaufsverwaltungs- und Beendigungsstrategien
  • Beobachtbarkeit: Integration mit OpenTelemetry zur Verfolgung von Agenteninteraktionen

Schlüsselkonzepte

Bevor wir Code schreiben, legen wir das Vokabular fest. Das Agent Framework dreht sich um einige Kernabstraktionen.

Agenten

Ein Agent ist eine Entität, die von einem KI-Modell unterstützt wird und mit spezifischen Anweisungen (einer Systemaufforderung), einem Namen und optional einer Reihe von Plugins oder Tools konfiguriert ist. Jeder Agent ist ein Spezialist – Sie definieren, was er weiß, was er kann und wie er sich verhalten soll.

ChatCompletionAgentDer einfachste Agententyp. Es umschließt einen Chat-Abschlussendpunkt (Azure OpenAI, OpenAI usw.) und verwaltet eine Konversation. Zwischen Aufrufen ist es zustandslos – Sie geben den Verlauf an und es antwortet. Dies macht es leicht und einfach zu überlegen.

ChatCompletionAgent agent = new()
{
    Name = "Reviewer",
    Instructions = "You are a senior code reviewer. Analyze the provided code for bugs, security issues, and style violations. Be concise and actionable.",
    Kernel = kernel
};

OpenAIAssistantAgent

Dieser Agententyp nutzt die OpenAI Assistants-API, die den serverseitigen Konversationsstatus, die Dateiverwaltung und die Codeinterpretation bereitstellt. Es ist umfangreicher, bietet Ihnen aber persistente Threads und integrierte Tools wie Code-Interpreter und Dateisuche.

OpenAIAssistantAgent agent = await OpenAIAssistantAgent.CreateAsync(
    clientProvider: clientProvider,
    definition: new OpenAIAssistantDefinition("gpt-4o")
    {
        Name = "DataAnalyst",
        Instructions = "You analyze datasets and produce statistical summaries."
    }
);

###AgentGroupChat

Das ist der Orchestrator. AgentGroupChat verwaltet Multi-Runden-Gespräche zwischen mehreren Agenten und steuert, wer als nächstes spricht, wann das Gespräch endet und wie der Verlauf geteilt wird. Hier entsteht die Magie der Multi-Agenten-Zusammenarbeit.

Orchestrierungsmuster

Das Framework unterstützt vier primäre Orchestrierungsmuster, die jeweils für unterschiedliche Probleme geeignet sind.

Sequentiell

Agenten werden nacheinander in einer definierten Reihenfolge ausgeführt. Die Ausgabe von Agent A wird an Agent B weitergeleitet, dessen Ausgabe an Agent C weitergeleitet wird. Dies ist ideal für Pipelines: Entwurf → Überprüfung → Bearbeiten → Veröffentlichen.

// Conceptual flow
var draft = await writerAgent.InvokeAsync("Write a blog post about .NET 9");
var reviewed = await reviewerAgent.InvokeAsync($"Review this: {draft}");
var edited = await editorAgent.InvokeAsync($"Edit based on feedback: {reviewed}");

Gleichzeitig

Mehrere Agenten arbeiten gleichzeitig an derselben Eingabe. Sie fächern die Arbeit auf und aggregieren dann die Ergebnisse. Ideal, um unterschiedliche Perspektiven zu erhalten – zum Beispiel, wenn drei Prüfer denselben Pull-Request prüfen.

Übergabe

Ein Agent entscheidet basierend auf dem Gesprächskontext, die Kontrolle an einen anderen Agenten zu übertragen. Dies ähnelt der Arbeitsweise eines Kundendienstteams: Der Mitarbeiter an der Front bearbeitet grundlegende Fragen und leitet sie bei Bedarf an Spezialisten weiter.

Gruppenchat

Mehrere Agenten nehmen an einem offenen Gespräch teil und wechseln sich auf der Grundlage einer Auswahlstrategie ab. Die Klasse AgentGroupChat implementiert dieses Muster mit konfigurierbarer Turn-Taking- und Beendigungslogik.

Aufbau Ihres ersten Agenten

Lassen Sie uns praktisch werden. Hier erfahren Sie Schritt für Schritt, wie Sie Ihren ersten Agenten aufbauen.

Voraussetzungen

Sie benötigen:

  • .NET 9 SDK – Eine Azure OpenAI-Ressource mit einem bereitgestellten Modell (z. B. gpt-4o)
  • Visual Studio oder VS Code

Einrichten des Projekts

Erstellen Sie eine neue Konsolenanwendung und installieren Sie die erforderlichen Pakete:

dotnet new console -n AgentDemo
cd AgentDemo
dotnet add package Microsoft.SemanticKernel --prerelease
dotnet add package Microsoft.SemanticKernel.Agents.Core --prerelease
dotnet add package Azure.AI.OpenAI
dotnet add package Azure.Identity

Erstellen eines einfachen Agenten

Richten Sie zunächst den Kernel mit Ihrer Azure OpenAI-Konfiguration ein:

using Azure.Identity;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.ChatCompletion;

var builder = Kernel.CreateBuilder();

builder.AddAzureOpenAIChatCompletion(
    deploymentName: "gpt-4o",
    endpoint: "https://your-resource.openai.azure.com/",
    credentials: new DefaultAzureCredential()
);

Kernel kernel = builder.Build();

Erstellen Sie nun einen Agenten und rufen Sie ihn auf:

ChatCompletionAgent agent = new()
{
    Name = "TechWriter",
    Instructions = """
        You are a technical writer specializing in software documentation.
        Write clear, concise content aimed at experienced developers.
        Use code examples when appropriate.
        Always structure your output with headings and bullet points.
        """,
    Kernel = kernel
};

ChatHistory history = new();
history.AddUserMessage("Explain dependency injection in .NET in 200 words.");

await foreach (ChatMessageContent response in agent.InvokeAsync(history))
{
    Console.WriteLine(response.Content);
}

Das ist es. Sie haben einen Arbeitsagenten. Doch die wahre Stärke entfaltet sich, wenn Agenten zusammenarbeiten.

Multi-Agent-Orchestrierung mit AgentGroupChat

Lassen Sie uns etwas Interessanteres erstellen – einen Gruppenchat, in dem mehrere Agenten zusammenarbeiten. Die Klasse AgentGroupChat verwaltet den Gesprächsablauf, einschließlich der Frage, wer als nächstes spricht und wann aufgehört werden soll.

Definieren der Agenten

Wir erstellen drei Agenten: einen Autor, einen Rezensenten und einen Herausgeber.

ChatCompletionAgent writer = new()
{
    Name = "Writer",
    Instructions = """
        You are a content writer. When given a topic, produce a well-structured
        draft. Focus on clarity and technical accuracy.
        When you receive feedback from the Reviewer, incorporate it into a
        revised draft.
        """,
    Kernel = kernel
};

ChatCompletionAgent reviewer = new()
{
    Name = "Reviewer",
    Instructions = """
        You are a content reviewer. Analyze drafts for technical accuracy,
        clarity, and completeness. Provide specific, actionable feedback.
        Do NOT rewrite the content  only provide feedback.
        When the content meets your standards, respond with: APPROVED
        """,
    Kernel = kernel
};

ChatCompletionAgent editor = new()
{
    Name = "Editor",
    Instructions = """
        You are an editor. Once content is approved by the Reviewer,
        polish it for grammar, tone, and formatting.
        Output only the final polished version.
        When you have produced the final version, respond with: COMPLETE
        """,
    Kernel = kernel
};

Einrichten des Gruppenchats

Das AgentGroupChat benötigt zwei Schlüsselkonfigurationen: eine Auswahlstrategie (wer als nächstes spricht) und eine Beendigungsstrategie (wann soll aufgehört werden).

AgentGroupChat chat = new(writer, reviewer, editor)
{
    ExecutionSettings = new()
    {
        SelectionStrategy = new SequentialSelectionStrategy(),
        TerminationStrategy = new ApprovalTerminationStrategy()
        {
            Agents = [editor],
            MaximumIterations = 12
        }
    }
};

Benutzerdefinierte KündigungsstrategieDie Beendigungsstrategie definiert, wann das Gespräch endet. Hier ist ein benutzerdefiniertes, das nach dem Schlüsselwort „COMPLETE“ sucht:

class ApprovalTerminationStrategy : TerminationStrategy
{
    protected override Task<bool> ShouldAgentTerminateAsync(
        Agent agent,
        IReadOnlyList<ChatMessageContent> history,
        CancellationToken cancellationToken = default)
    {
        bool isComplete = history
            .Last()
            .Content?
            .Contains("COMPLETE", StringComparison.OrdinalIgnoreCase) ?? false;

        return Task.FromResult(isComplete);
    }
}

Das Gespräch führen

Beginnen Sie das Gespräch mit einer Benutzernachricht und lassen Sie die Agenten zusammenarbeiten:

chat.AddChatMessage(
    new ChatMessageContent(AuthorRole.User,
        "Write a 300-word technical overview of gRPC vs REST for microservices.")
);

await foreach (ChatMessageContent message in chat.InvokeAsync())
{
    Console.WriteLine($"[{message.AuthorName}]: {message.Content}");
    Console.WriteLine("---");
}

Der Ablauf sieht etwa so aus:

  1. Autor erstellt einen Entwurf
  2. Rezensent gibt Feedback
  3. Der Autor überarbeitet basierend auf dem Feedback
  4. Rezensent sagt „GENEHMIGT“
  5. Redakteur poliert und sagt „VOLLSTÄNDIG“
  6. Das Gespräch wird beendet

Dieses Hin und Her wird automatisch fortgesetzt, bis die Abbruchbedingung erfüllt ist oder MaximumIterations erreicht ist.

Plugins und Tools

Wirklich mächtig werden Agenten dann, wenn sie mit externen Systemen interagieren können. Das Agent Framework unterstützt drei Haupterweiterungsmechanismen.

Native Funktionen (Kernel-Plugins)

Sie können Agenten Zugriff auf C#-Methoden als Tools gewähren. Der Agent ruft diese Funktionen auf, wenn er feststellt, dass sie benötigt werden:

public class ContentToolsPlugin
{
    [KernelFunction("word_count")]
    [Description("Counts the number of words in the provided text.")]
    public int WordCount([Description("The text to count words in")] string text)
    {
        return text.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
    }

    [KernelFunction("check_readability")]
    [Description("Calculates a readability score for the given text.")]
    public string CheckReadability([Description("The text to analyze")] string text)
    {
        var words = text.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
        var sentences = text.Split(['.', '!', '?'], StringSplitOptions.RemoveEmptyEntries).Length;

        if (sentences == 0) return "Unable to calculate — no sentences found.";

        double avgWordsPerSentence = (double)words / sentences;

        return avgWordsPerSentence switch
        {
            < 15 => $"Easy to read (avg {avgWordsPerSentence:F1} words/sentence)",
            < 25 => $"Moderate difficulty (avg {avgWordsPerSentence:F1} words/sentence)",
            _ => $"Difficult to read (avg {avgWordsPerSentence:F1} words/sentence). Consider shorter sentences."
        };
    }
}

Registrieren Sie das Plugin im Kernel, bevor Sie den Agenten erstellen:

kernel.Plugins.AddFromType<ContentToolsPlugin>();

ChatCompletionAgent analyst = new()
{
    Name = "ContentAnalyst",
    Instructions = "Analyze content using available tools. Report word count and readability.",
    Kernel = kernel,
    Arguments = new KernelArguments(
        new PromptExecutionSettings
        {
            FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
        })
};

Model Context Protocol (MCP)

MCP ist ein offener Standard zur Anbindung von KI-Modellen an externe Tools und Datenquellen. Das Agent Framework unterstützt MCP, was bedeutet, dass Ihre Agenten Tools verwenden können, die von jedem MCP-kompatiblen Server bereitgestellt werden. Dies öffnet die Tür zu Dateisystemen, Datenbanken, APIs und mehr – alles über eine standardisierte Schnittstelle.

// Example: Adding an MCP server for file operations
kernel.Plugins.AddFromMcpServer("filesystem",
    new Uri("http://localhost:3000/mcp"));

Das ist besonders spannend, weil es bedeutet, dass Ihre Agenten nicht auf das beschränkt sind, was Sie erstellen – sie können auf ein Ökosystem von MCP-Tools zugreifen, die andere entwickeln und teilen.

Beispiel aus der Praxis: Content-Review-Pipeline

Lassen Sie uns alles mit einem praktischen Szenario zusammenstellen. Stellen Sie sich vor, Sie entwickeln ein internes Tool, das die Inhaltsüberprüfung für ein Dokumentationsteam automatisiert. Die Pipeline besteht aus vier Phasen:

  1. Forscher – Sammelt relevante technische Informationen
  2. Autor – Erstellt einen Entwurf basierend auf Recherchen
  3. Prüfer – Überprüft die Richtigkeit und Vollständigkeit
  4. Publisher – Formatiert und bereitet die endgültige Ausgabe vor

Hier ist eine komprimierte Implementierung:

using Azure.Identity;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.ChatCompletion;

// Build the kernel
var builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(
    deploymentName: "gpt-4o",
    endpoint: "https://your-resource.openai.azure.com/",
    credentials: new DefaultAzureCredential()
);
Kernel kernel = builder.Build();

// Define specialized agents
ChatCompletionAgent researcher = new()
{
    Name = "Researcher",
    Instructions = """
        You are a technical researcher. Given a topic, identify the key
        concepts, recent developments, and important details that should
        be covered. Output a structured research brief.
        """,
    Kernel = kernel
};

ChatCompletionAgent writer = new()
{
    Name = "Writer",
    Instructions = """
        You are a technical writer. Using the research brief provided,
        write a comprehensive, well-structured article. Include code
        examples where relevant. Target audience: experienced developers.
        """,
    Kernel = kernel
};

ChatCompletionAgent reviewer = new()
{
    Name = "Reviewer",
    Instructions = """
        You are a senior technical reviewer. Check the article for:
        - Technical accuracy
        - Completeness relative to the research brief
        - Code correctness
        - Clarity and structure
        If everything looks good, respond with APPROVED.
        Otherwise, provide specific feedback for revision.
        """,
    Kernel = kernel
};

ChatCompletionAgent publisher = new()
{
    Name = "Publisher",
    Instructions = """
        You are a content publisher. Once the article is approved,
        format it with proper markdown, add a summary at the top,
        and ensure consistent formatting throughout.
        End your response with COMPLETE.
        """,
    Kernel = kernel
};

// Configure the group chat
AgentGroupChat chat = new(researcher, writer, reviewer, publisher)
{
    ExecutionSettings = new()
    {
        SelectionStrategy = new SequentialSelectionStrategy(),
        TerminationStrategy = new ApprovalTerminationStrategy()
        {
            Agents = [publisher],
            MaximumIterations = 15
        }
    }
};

// Start the pipeline
chat.AddChatMessage(new ChatMessageContent(
    AuthorRole.User,
    "Create a technical article about implementing health checks in ASP.NET Core microservices."
));

await foreach (ChatMessageContent message in chat.InvokeAsync())
{
    Console.ForegroundColor = message.AuthorName switch
    {
        "Researcher" => ConsoleColor.Cyan,
        "Writer" => ConsoleColor.Green,
        "Reviewer" => ConsoleColor.Yellow,
        "Publisher" => ConsoleColor.Magenta,
        _ => ConsoleColor.White
    };

    Console.WriteLine($"\n{'='new string('=', 60)}");
    Console.WriteLine($"[{message.AuthorName}]");
    Console.WriteLine(new string('=', 60));
    Console.WriteLine(message.Content);
}

Console.ResetColor();

Diese Pipeline erzeugt einen vollständig recherchierten, geschriebenen, überprüften und formatierten Artikel – alles durch die Zusammenarbeit der Agenten. Jeder Agent konzentriert sich auf das, was er am besten kann, und der AgentGroupChat koordiniert den Arbeitsablauf.

Best Practices

Nachdem ich mehrere Multiagentensysteme erstellt habe, sind hier die Muster und Praktiken aufgeführt, die ich am wertvollsten gefunden habe.

Fehlerbehandlung

Legen Sie bei Ihrer Kündigungsstrategie immer MaximumIterations fest. Ohne sie können Agenten in Endlosschleifen geraten – insbesondere, wenn ein Prüfer weiterhin Probleme findet und ein Autor ständig Überarbeitungen ohne Verbesserung durchführt.

TerminationStrategy = new ApprovalTerminationStrategy()
{
    MaximumIterations = 12 // Safety net
}

Wickeln Sie Ihre Agentenaufrufe in Try-Catch-Blöcke ein. API-Ratenbegrenzungen, Netzwerkprobleme und Modellfehler sind Realitäten von Produktionssystemen:

try
{
    await foreach (var message in chat.InvokeAsync(cancellationToken))
    {
        // Process messages
    }
}
catch (HttpOperationException ex) when (ex.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
{
    // Implement retry with exponential backoff
    await Task.Delay(TimeSpan.FromSeconds(30), cancellationToken);
}

BeobachtbarkeitDas Agent Framework lässt sich in OpenTelemetry integrieren, was bedeutet, dass Sie jede Agenteninteraktion, jeden Tool-Aufruf und jede Token-Nutzung verfolgen können. Dies ist wichtig für das Debuggen von Multi-Agent-Workflows, bei denen nicht immer offensichtlich ist, welcher Agent ein Problem verursacht hat.

Richten Sie grundlegende Telemetriedaten ein, indem Sie die Semantic Kernel-Telemetriepakete hinzufügen und Ihren bevorzugten Exporter (Application Insights, Jaeger usw.) konfigurieren:

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing =>
    {
        tracing.AddSource("Microsoft.SemanticKernel*");
        tracing.AddOtlpExporter();
    });

Kostenmanagement

Multi-Agenten-Systeme vervielfachen Ihre API-Kosten – jede Agentenrunde ist ein API-Aufruf, und Gruppenchats können viele Runden generieren. Einige Strategien, um die Kosten unter Kontrolle zu halten:

  • Günstigere Modelle für einfachere Agenten verwenden: Nicht jeder Agent benötigt GPT-4o. Ein Rezensent könnte mit einem kleineren Modell gut zurechtkommen, während nur der Autor das starke Modell braucht.
  • Verlauf begrenzen: Verwenden Sie ReducedHistoryCount in Ihren Ausführungseinstellungen, um zu begrenzen, wie viel Konversationskontext jeder Agent erhält.
  • Strikte Iterationsgrenzen festlegen: Verhindern Sie außer Kontrolle geratene Gespräche mit angemessenen MaximumIterations-Werten.
  • Wenn möglich zwischenspeichern: Wenn ein Agent dieselbe Suche wiederholt durchführt, speichern Sie die Ergebnisse in einem Plugin zwischen.

Agentendesign

  • Anweisungen fokussiert halten: Jeder Agent sollte eine einzige, klare Verantwortung haben. Breite Anweisungen führen bei allen Aufgaben zu einer mittelmäßigen Leistung.
  • Machen Sie Angaben zum Ausgabeformat: Teilen Sie den Agenten genau mit, wie sie ihre Antworten strukturieren sollen. Dies macht das Downstream-Parsing zuverlässig.
  • Beendigungsschlüsselwörter verwenden: Definieren Sie eindeutige Signale (wie „GENEHMIGT“ oder „ABGESCHLOSSEN“), mit denen Agenten angeben, dass sie fertig sind. Dies macht Kündigungsstrategien einfach und vorhersehbar.

Fazit

Multiagenten-KI-Systeme stellen einen grundlegenden Wandel in der Art und Weise dar, wie wir intelligente Anwendungen erstellen. Anstatt sich mit einer einzigen Eingabeaufforderung herumschlagen zu müssen, die alles erledigt, können wir Probleme in spezialisierte Rollen zerlegen und Agenten zusammenarbeiten lassen.

Das Agent Framework von Microsoft macht dies für .NET-Entwickler praktisch. Die Abstraktionen sind sauber – Agenten, Gruppenchats, Auswahl- und Kündigungsstrategien – und sie komponieren natürlich. In Kombination mit dem Plugin-Ökosystem des Semantic Kernels und dem Modellhosting von Azure verfügen Sie über einen vollständigen Stack für den Aufbau produktionstauglicher Multi-Agent-Systeme.

Das Framework befindet sich noch in der Entwicklung (viele Pakete befinden sich in der Vorschau), aber die Kernmuster sind solide und die Richtung ist klar. Wenn Sie KI-gestützte Anwendungen in .NET erstellen, ist es jetzt an der Zeit, mit Multi-Agent-Architekturen zu experimentieren.

Fangen Sie klein an – stellen Sie zwei Agenten zusammen, die bei einer einfachen Aufgabe zusammenarbeiten. Sobald Sie die Qualitätsverbesserung gegenüber Einzelagenten-Ansätzen sehen, sollten Sie alles in Agententeams aufteilen.

Viel Spaß beim Codieren!