Agent-Schleifen

Die Agent-Schleife ruft einen Agent erneut auf, bis eine Abschlussbedingung erfüllt ist. Verwenden Sie sie für die iterative Verfeinerung, das Erledigen von To-dos, das Warten auf Hintergrundaufgaben oder zur Bewertung, ob eine Antwort die expliziten Kriterien erfüllt.

Begrenzen Sie autonome Schleifen immer. Eine Abschlussbedingung kann fehlschlagen, ein Modell kann hängen und ein Evaluator kann probabilistisch sein.

Important

Agent-Schleifen sind experimentell.

Manuelles Einrichten von Schleifen

Verwenden Sie die Direct-Composition-API, wenn Sie Schleifen ohne die sonstigen Standardeinstellungen von Harness Agent benötigen.

Importieren Sie die Schleifentypen und umschließen Sie jedes AIAgent mit LoopAgent. Das standardmäßige Maximum beträgt 10 Agentaufrufe:

using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

AIAgent baseAgent = chatClient.AsAIAgent();
AIAgent agent = new LoopAgent(
    baseAgent,
    new CompletionMarkerLoopEvaluator("DONE"),
    new LoopAgentOptions { MaxIterations = 5 });

Importieren Sie AgentLoopMiddleware und fügen Sie es zu einer normalen Agent hinzu. Das Standardmaximum beträgt 10 Agent-Ausführungen:

from agent_framework import Agent, AgentLoopMiddleware


def needs_more_work(*, last_result, **kwargs):
    return "DONE" not in last_result.text


agent = Agent(
    client=client,
    middleware=[
        AgentLoopMiddleware(
            needs_more_work,
            max_iterations=5,
        )
    ],
)

Das Prädikat kann synchron oder asynchron sein. Kehren Sie True zurück, um fortzufahren, False zu beenden oder (continue, feedback) Feedback an die nächste Iteration zu übergeben.

Go bietet einen gebundenen erneuten Aufruf über agent/harness/loop. Registrieren Sie loop.New(loop.Config{...}) in agent.Config.Middlewares. Die Middleware führt den Agent aus, wertet seine Antwort aus und sendet optional Feedback an eine andere Iteration.

Im folgenden Foundry-Beispiel wird eine Vervollständigungsmarkierung verwendet. Sie erfordert FOUNDRY_PROJECT_ENDPOINT, FOUNDRY_MODEL und eine Azure-Anmeldeinformation:

// Copyright (c) Microsoft. All rights reserved.

package main

import (
    "context"

    "github.com/microsoft/agent-framework-go/agent"
    "github.com/microsoft/agent-framework-go/agent/harness/loop"
    "github.com/microsoft/agent-framework-go/examples/internal/demo"
    "github.com/microsoft/agent-framework-go/provider/foundryprovider"
)

var logger = demo.NewLogger(
    "Loop Harness",
    "This sample shows how the loop harness keeps re-invoking an agent until it "+
        "signals completion with a marker, so the agent can work across several turns "+
        "on its own before returning.",
    "Model", demo.FoundryModel,
)

// completionMarker is the token the agent is asked to emit once the task is
// fully done; the loop stops as soon as it appears in a response.
const completionMarker = "TASK COMPLETE"

func main() {
    token := demo.FoundryTokenCredential()

    // Wrap the agent with the loop harness: after each iteration the
    // completion-marker evaluator decides whether to run the agent again.
    a := foundryprovider.NewAgent(
        demo.FoundryProjectEndpoint,
        token,
        foundryprovider.ModelDeployment(demo.FoundryModel),
        foundryprovider.AgentConfig{
            Instructions: "You are a diligent assistant. Work on the request step by step across " +
                "multiple turns. End your final message with the marker '" + completionMarker +
                "' once, and only once, the request is fully complete.",
            Config: agent.Config{
                Name: "Worker",
                Middlewares: []agent.Middleware{
                    // The loop re-invokes the agent (and everything below it,
                    // including the logger) until an evaluator stops the loop.
                    loop.New(loop.Config{
                        Evaluators: []loop.Evaluator{
                            loop.NewCompletionMarkerEvaluator(loop.CompletionMarkerConfig{Marker: completionMarker}),
                        },
                    }),
                    logger, // for logging each agent iteration
                },
            },
        },
    )

    ctx := context.Background()
    resp, err := a.RunText(ctx, "Draft a short checklist for planning a small birthday party, "+
        "then review it once for anything missing, and finish.").Collect()
    demo.Response(resp, err)
}

MaxIterations ist ein optionales *int und hat standardmäßig den Wert 10. Legen Sie eine explizite Grenze für Ihre Aufgabe fest. Bei mehreren Bewertern liefert der erste Bewerter, der eine weitere Iteration anfordert, sein Feedback; die Schleife wird nur beendet, wenn alle Bewerter aufhören oder die Iterationsgrenze erreicht ist.

Ein Beispiel ohne Anmeldeinformationen finden Sie im Beispiel für eine Skriptschleife. Es veranschaulicht die Markierungsvervollständigung, einen benutzerdefinierten Evaluator und die Iterationssicherheitsgrenze.

Auswählen einer Abschlussbedingung

LoopAgent akzeptiert einen Evaluator oder eine sortierte Sammlung:

Auswerter Wird fortgesetzt, solange
CompletionMarkerLoopEvaluator Die neueste Antwort enthält nicht die konfigurierte Markierung.
TodoCompletionLoopEvaluator Ein aufgelöstes TodoProvider Element verfügt weiterhin über unvollständige Elemente, optional in ausgewählten Agentmodi.
BackgroundTaskCompletionLoopEvaluator Ein gelöstes BackgroundAgentsProvider hat noch laufende Aufgaben.
AIJudgeLoopEvaluator Ein separater Richter-Kunde sagt, dass die ursprüngliche Anfrage nicht vollständig beantwortet wird.
DelegateLoopEvaluator Ihre Callback-Funktion gibt LoopEvaluation.Continue(...) zurück.

Wenn mehrere Bewerter konfiguriert sind, werden sie in der Reihenfolge ausgeführt. Der erste Evaluator, der eine weitere Iteration anfordert, gibt seine Rückmeldung; die Schleife wird erst dann beendet, wenn alle Evaluatoren eine Fortsetzung ablehnen.

Verwenden eines KI-Richters

Der Richter erhält die ursprüngliche Anfrage und die neueste Agentantwort. Wenn sie eine Lücke findet, dient ihre Analyse als Feedback für die nächste Iteration:

var evaluator = new AIJudgeLoopEvaluator(
    judgeClient,
    new AIJudgeLoopEvaluatorOptions
    {
        Criteria =
        [
            "Answer every part of the request.",
            "Support conclusions with evidence.",
        ],
    });

AIAgent loopAgent = new LoopAgent(
    agent,
    evaluator,
    new LoopAgentOptions { MaxIterations = 4 });

Verwenden Sie nur einen Richterendpunkt, dem Sie vertrauen, mit der ursprünglichen Anforderung und der generierten Antwort.

Steuern des Kontexts und der Ausgabe

Standardmäßig verwendet LoopAgent dieselbe Sitzung weiter und sendet das neueste Feedback des erfolgreichen Evaluators als nächste Eingabe. FreshContextPerIteration = true erstellt stattdessen jeden Durchlauf anhand der ursprünglichen Anfrage und eines aggregierten Feedbackprotokolls neu und setzt die Sitzung zurück oder stellt sie wieder her.

Wenn kein Streaming ausgeführt wird, wird standardmäßig ein aggregiertes Transkript zurückgegeben. Legen Sie fest NonStreamingReturnsLastResponseOnly = true , dass nur die endgültige Antwort zurückgegeben wird. Streaming sendet immer jede Iteration und alle sichtbaren Im-Auftrag-von-Feedback-Nachrichten.

Das Prädikat erhält Schlüsselwortargumente, einschließlich iteration, last_result, messages, original_messages, session, agent, progress und feedback. Die Helfer todos_remaining() und background_tasks_running() stellen integrierte To-do- und Hintergrundaufgabenbedingungen bereit. Koppeln Sie sie mit todos_remaining_message oder background_tasks_running_message, um eine gezielte nächste Eingabe zu generieren.

Verwenden eines KI-Richters

AgentLoopMiddleware.with_judge erstellt eine richtergesteuerte Schleife. Judge-Loops sind standardmäßig auf fünf Iterationen eingestellt:

from agent_framework import Agent, AgentLoopMiddleware

loop = AgentLoopMiddleware.with_judge(
    judge_client,
    criteria=[
        "Answer every part of the request.",
        "Support conclusions with evidence.",
    ],
    max_iterations=4,
)

agent = Agent(
    client=client,
    middleware=[loop],
)

Die Begründung des Richters wird an den Agenten zurückgespeist, wenn mehr Arbeit erforderlich ist. Verwenden Sie nur einen Richterendpunkt, dem Sie vertrauen, mit der ursprünglichen Anforderung und der generierten Antwort.

Steuern des Kontexts, des Fortschritts und der Ausgabe

Erstellen Sie AgentLoopMiddleware für erweiterte Schleifen direkt:

  • record_feedback erstellt nach jeder Arbeitsiteration einen knappen Fortschrittseintrag.
  • progress macht gesammelte Einträge für Rückrufe verfügbar.
  • inject_progress=True fügt der Eingabe der nächsten Iteration den Fortschritt hinzu.
  • fresh_context=True startet aus dem ursprünglichen Vorgangs- und Statusprotokoll neu und stellt eine angefügte Sitzung in seiner Vorabschleifenmomentaufnahme wieder her.
  • return_final_only=True liefert für nicht-streamende Ausführungen nur die letzte Antwort zurück.

Übergeben Sie max_iterations=None nur, wenn das Vervollständigungs-Prädikat garantiert beendet wird.

Verwenden Sie loop.NewCompletionMarkerEvaluator, um anzuhalten, wenn die neueste Antwort eine konfigurierte Markierung enthält. Implementieren Sie für die anwendungsspezifische Vervollständigung loop.Evaluator oder verwenden Sie loop.EvaluatorFunc und geben Sie loop.Stop(), loop.Continue(feedback) oder loop.ContinueWithMessages(messages) zurück.

FreshContextPerIteration startet von der ursprünglichen Eingabe neu, plus akkumuliertes Feedback. NonStreamingReturnsLastResponseOnly beschränkt ein Nicht-Streaming-Ergebnis auf die letzte Iteration.

Go enthält nicht den integrierten KI-Richter-Evaluator, der in den C#-Beispielen gezeigt wird. Geben Sie Ihren eigenen Evaluator an, wenn die Vervollständigung ein anderes Modell oder eine externe Prüfung erfordert.

Schleifen mit dem Harness Agent verwenden

Verwenden Sie die Einrichtung des Harness Agent, wenn Sie zudem dessen vorkonfigurierten Verlauf, die Planung, den Speicher, die Freigabe und die Observability-Pipeline nutzen möchten.

Legen Sie HarnessAgentOptions.LoopEvaluators fest. Das Harness verwendet LoopAgent als seinen äußersten Agent-Dekorator:

using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

var options = new HarnessAgentOptions
{
    LoopEvaluators =
    [
        new CompletionMarkerLoopEvaluator("DONE"),
    ],
    LoopAgentOptions = new LoopAgentOptions
    {
        MaxIterations = 5,
    },
};

HarnessAgent agent = chatClient.AsHarnessAgent(options);
// Equivalent construction: new HarnessAgent(chatClient, options)
AgentSession session = await agent.CreateSessionAsync();

Eine leere oder nullLoopEvaluators-Sammlung belässt das Harness im Single-Shot-Modus.

Genehmigungs- und Sitzungsverhalten

LoopAgent wird vor der Auswertung seiner Abschlussbedingung beendet, wenn eine Iteration eine ausstehende Toolgenehmigungsanforderung zurückgibt. Sie gibt die Anfrage an den Aufrufer zurück, anstatt sie hinter einer weiteren eigenständigen Iteration zu verbergen. Nachdem der Anrufer die Genehmigungsantwort über den normalen Genehmigungsfluss des Tools bereitstellt, kann der Agent fortfahren.

LoopAgent fügt selbst keine Genehmigungsverarbeitung hinzu. Der Harness Agent wendet die Schleife außerhalb von ToolApprovalAgent an, sodass ausstehende Genehmigungsanfragen der Schleife entkommen können.

Verwenden Sie über mehrere Aufrufe hinweg dasselbe AgentSession, um die Konversation fortzusetzen. Schleifeniterationen teilen diese Sitzung standardmäßig. Mit FreshContextPerIteration = true, LoopAgent wird der vom Aufrufer bereitgestellte Sitzungszustand zurückgesetzt oder wiederhergestellt, sofern unterstützt. Der dienstseitige Konversationsspeicher kann den Verlauf beibehalten, wenn die serialisierte Sitzung nur eine Remote-Konversationskennung enthält.

Geben Sie loop_should_continue für create_harness_agent an; loop_max_iterations ist standardmäßig 10:

from agent_framework import create_harness_agent


def needs_more_work(*, last_result, **kwargs):
    return "DONE" not in last_result.text


agent = create_harness_agent(
    client=client,
    loop_should_continue=needs_more_work,
    loop_max_iterations=5,
)
session = agent.create_session()

loop_next_message passt die nächste Eingabe an. Ohne loop_should_continue fügt die Factory keine Schleife hinzu und ignoriert die anderen Schleifenargumente.

Genehmigungs- und Sitzungsverhalten

AgentLoopMiddleware wird vor der Auswertung seines Fortsetzungsprädikats beendet, wenn eine Iteration eine ausstehende Toolgenehmigungsanforderung zurückgibt. Sie gibt die Anfrage an den Aufrufer zurück, anstatt sie hinter einer weiteren eigenständigen Iteration zu verbergen. Nachdem der Anrufer die Genehmigungsantwort über den normalen Genehmigungsfluss des Tools bereitstellt, kann der Agent fortfahren.

AgentLoopMiddleware fügt ToolApprovalMiddleware nicht selbst hinzu. Der Harness Agent platziert die Schleife außerhalb seiner Freigabe-Middleware, sodass ausstehende Freigabeanfragen der Schleife entkommen können. Erstellen und übergeben Sie bei jeder Ausführung des Harness Agent eine AgentSession, während die automatische Genehmigung des Tools aktiviert ist.

Verwenden Sie über mehrere Aufrufe hinweg dasselbe AgentSession, um die Konversation fortzusetzen. Schleifeniterationen teilen diese Sitzung standardmäßig. Mit fresh_context=True stellt die Middleware die zugeordnete Sitzung zwischen den Iterationen auf die Momentaufnahme vor der Schleife zurück. Der dienstseitige Konversationsspeicher kann den Verlauf beibehalten, wenn die serialisierte Sitzung nur eine Remote-Konversationskennung enthält.

Das Go-harness.AgentConfig-Hilfsprogramm fügt standardmäßig keine Schleife hinzu. Schließen Sie loop.New(...) in agent.Config.Middlewares des Aufrufers ein, um den konfigurierten Agent mit einem gebundenen erneuten Aufruf zu umschließen.

Die Schleife wird zurückgegeben, wenn eine Iteration ausstehende Toolgenehmigungsanforderungen erzeugt. Es genehmigt Tools nicht automatisch. Behandeln Sie die Anfragen im Host, und geben Sie die übereinstimmenden Genehmigungsantworten über dieselbe Sitzung zurück, bevor Sie fortfahren.

Nächste Schritte

Mehr erfahren