Pętla agenta

Zapętlenie agenta powoduje ponowne wywoływanie agenta do momentu spełnienia warunku zakończenia. Używaj tego do iteracyjnego dopracowywania, realizacji zadań z listy rzeczy do zrobienia, oczekiwania na zakończenie zadań w tle lub oceny, czy odpowiedź spełnia określone kryteria.

Zawsze ograniczaj autonomiczne pętle. Warunek zakończenia może zawieść, model może utknąć, a oceniający może być probabilistyczny.

Important

Zapętlanie agenta jest eksperymentalne.

Ręczne konfigurowanie pętli

Użyj interfejsu Direct Composition API, jeśli chcesz używać pętli bez pozostałych domyślnych ustawień Harness Agent.

Zaimportuj typy pętli i opakuj dowolny element AIAgent elementem LoopAgent. Jego domyślna maksymalna wartość to 10 wywołań agenta:

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

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

Zaimportuj AgentLoopMiddleware i dodaj go do zwykłego Agentelementu . Domyślny maksymalny limit to 10 uruchomień agenta:

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

Predykat może być synchroniczny lub asynchroniczny. Wróć do True, aby kontynuować, do False, aby zatrzymać, lub do (continue, feedback), aby przekazać opinię do następnej iteracji.

Go zapewnia ograniczone ponowne wywołanie poprzez agent/harness/loop. Zarejestruj loop.New(loop.Config{...}) w agent.Config.Middlewares. Oprogramowanie pośredniczące uruchamia agenta, ocenia jego odpowiedź i opcjonalnie wysyła opinię do innej iteracji.

Poniższy przykład rozwiązania Foundry używa znacznika zakończenia. Wymaga to FOUNDRY_PROJECT_ENDPOINT, FOUNDRY_MODEL i poświadczenia Azure:

// 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 jest opcjonalnym *int i domyślnie ma wartość 10. Ustaw jawny limit zadania. W przypadku wielu ewaluatorów pierwszy ewaluator żądający innej iteracji dostarcza swoją opinię; pętla zatrzymuje się tylko po zatrzymaniu wszystkich ewaluatorów lub osiągnięciu limitu iteracji.

Aby zapoznać się z przykładem bez poświadczeń, zobacz przykład pętli skryptowej. Demonstruje uzupełnianie znaczników, niestandardowy ewaluator i limit bezpieczeństwa iteracji.

Wybieranie warunku ukończenia

LoopAgent przyjmuje jeden moduł oceniający lub uporządkowaną kolekcję:

Oceniacz Kontynuuje, gdy
CompletionMarkerLoopEvaluator Najnowsza odpowiedź nie zawiera skonfigurowanego znacznika.
TodoCompletionLoopEvaluator Rozwiązany element TodoProvider nadal ma niekompletne elementy, opcjonalnie w wybranych trybach agenta.
BackgroundTaskCompletionLoopEvaluator Rozwiązane BackgroundAgentsProvider nadal ma uruchomione zadania.
AIJudgeLoopEvaluator Oddzielny klient sędziego mówi, że oryginalne żądanie nie jest w pełni odpowiedzi.
DelegateLoopEvaluator Funkcja wywołania zwrotnego zwraca LoopEvaluation.Continue(...).

Po skonfigurowaniu wielu ewaluatorów są one uruchamiane w kolejności. Pierwszy ewaluator, który żąda innej iteracji dostarcza swoją opinię; pętla zatrzymuje się tylko wtedy, gdy wszyscy ewaluatorzy odmawiają kontynuowania.

Korzystanie z sędziego sztucznej inteligencji

Sędzia otrzymuje oryginalne żądanie i najnowszą odpowiedź agenta. Jeśli znajdzie lukę, jej analiza stanie się opinią na potrzeby następnej iteracji:

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

Korzystaj wyłącznie z endpointu oceniającego, któremu ufasz, przekazując do niego oryginalne żądanie i wygenerowaną odpowiedź.

Sterowanie kontekstem i danymi wyjściowymi

Domyślnie LoopAgent ponownie wykorzystuje tę samą sesję i wysyła najnowsze informacje zwrotne zwycięskiego ewaluatora jako kolejne dane wejściowe. FreshContextPerIteration = true zamiast tego odtwarza każdy przebieg na podstawie oryginalnego żądania i zagregowanego dziennika informacji zwrotnych oraz resetuje lub przywraca sesję.

Uruchomienia bez przesyłania strumieniowego domyślnie zwracają zbiorczą transkrypcję. Ustaw NonStreamingReturnsLastResponseOnly = true, aby zwracał tylko odpowiedź końcową. Transmisja strumieniowa zawsze zwraca wynik każdej iteracji oraz wszelkie widoczne komunikaty zwrotne typu „on-behalf-of”.

Predykat odbiera argumenty słów kluczowych, w tym iteration, , last_resultmessagesoriginal_messagessessionagentprogress, i .feedback Pomocnicy todos_remaining() i background_tasks_running() zapewniają wbudowane warunki zadań do wykonania i zadań w tle. Połącz je z todos_remaining_message lub background_tasks_running_message, aby wygenerować ukierunkowane kolejne dane wejściowe.

Korzystanie z sędziego sztucznej inteligencji

AgentLoopMiddleware.with_judge tworzy pętlę sterowaną przez sędziego. Pętle oceniające domyślnie mają pięć iteracji:

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

Uzasadnienie sędziego jest przekazywane z powrotem agentowi, gdy konieczna jest dalsza praca. Korzystaj wyłącznie z endpointu oceniającego, któremu ufasz, przekazując do niego oryginalne żądanie i wygenerowaną odpowiedź.

Kontrolowanie kontekstu, postępu i danych wyjściowych

W przypadku pętli zaawansowanych skonstruuj AgentLoopMiddleware bezpośrednio:

  • record_feedback tworzy zwięzły wpis o postępach po każdej iteracji pracy.
  • progress uwidacznia skumulowane wpisy w wywołaniach zwrotnych.
  • inject_progress=True dodaje informacje o postępie do danych wejściowych następnej iteracji.
  • fresh_context=True jest ponownie uruchamiane na podstawie oryginalnego zadania i dziennika postępu oraz przywraca dołączoną sesję do stanu z migawki sprzed pętli.
  • return_final_only=True zwraca tylko ostatnią odpowiedź dla uruchomień bez strumieniowania.

Przekaż max_iterations=None tylko wtedy, gdy predykat ukończenia ma gwarancję zakończenia.

Użyj polecenia loop.NewCompletionMarkerEvaluator , aby zatrzymać, gdy najnowsza odpowiedź zawiera skonfigurowany znacznik. W przypadku uzupełniania specyficznego dla aplikacji zaimplementuj loop.Evaluator lub użyj metody loop.EvaluatorFunc, zwracając wartość loop.Stop(), loop.Continue(feedback)lub loop.ContinueWithMessages(messages).

FreshContextPerIteration zaczyna od nowa od oryginalnych danych wejściowych i skumulowanych opinii. NonStreamingReturnsLastResponseOnly ogranicza wynik bez przesyłania strumieniowego tylko w końcowej iteracji.

Język Go nie zawiera wbudowanego ewaluatora AI-judge pokazanego w przykładach języka C#. Podaj własny ewaluator, jeśli ukończenie wymaga innego modelu lub kontroli zewnętrznej.

Używanie pętli z Harness Agent

Użyj konfiguracji agenta Harness, jeśli chcesz także skorzystać z jego wstępnie skonfigurowanych funkcji historii, planowania, pamięci, zatwierdzeń i pipeline’u observability.

Ustaw wartość HarnessAgentOptions.LoopEvaluators. Mechanizm testowy stosuje LoopAgent jako najbardziej zewnętrzny dekorator agenta:

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

Pusta lub nullLoopEvaluators kolekcja pozostawia uprzężę jednostrzeliwą.

Zatwierdzanie i działanie sesji

LoopAgent zatrzymuje się przed oceną warunku ukończenia, gdy iteracja zwraca oczekujące żądanie zatwierdzenia narzędzia. Zwraca żądanie do wywołującego, zamiast ukrywać je za inną samodzielną iteracją. Gdy wywołujący przekaże odpowiedź zatwierdzającą za pośrednictwem normalnego przepływu zatwierdzania narzędzia, agent może kontynuować.

LoopAgent samo w sobie nie dodaje funkcji zatwierdzania. Agent Harness stosuje pętlę poza ToolApprovalAgent, umożliwiając oczekującym żądaniom zatwierdzenia wyjście poza pętlę.

Użyj ponownie tego samego elementu AgentSession w kolejnych wywołaniach, aby kontynuować rozmowę. Iteracje pętli domyślnie współdzielą tę sesję. Za pomocą FreshContextPerIteration = trueLoopAgent resetuje lub przywraca stan sesji dostarczony przez wywołującego, jeśli jest to obsługiwane. Magazyn konwersacji należących do usługi może zachować historię, gdy serializowana sesja zawiera tylko identyfikator konwersacji zdalnej.

Przekaż loop_should_continue do create_harness_agent; loop_max_iterations ma domyślną wartość 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 dostosowuje kolejne dane wejściowe. Bez elementu loop_should_continue fabryka nie dodaje pętli i ignoruje pozostałe argumenty pętli.

Zatwierdzanie i działanie sesji

AgentLoopMiddleware zatrzymuje się przed sprawdzeniem warunku kontynuacji, gdy iteracja zwraca żądanie zatwierdzenia narzędzia oczekujące na rozpatrzenie. Zwraca żądanie do wywołującego, zamiast ukrywać je za inną samodzielną iteracją. Gdy wywołujący przekaże odpowiedź zatwierdzającą za pośrednictwem normalnego przepływu zatwierdzania narzędzia, agent może kontynuować.

AgentLoopMiddleware samo nie dodaje ToolApprovalMiddleware. Agent Harness umieszcza pętlę poza warstwą pośrednią obsługującą zatwierdzanie, co pozwala oczekującym żądaniom zatwierdzenia wydostać się z pętli. Utwórz i przekaż element AgentSession przy każdym uruchomieniu Harness Agent, gdy włączone jest automatyczne zatwierdzanie narzędzi.

Użyj ponownie tego samego elementu AgentSession w kolejnych wywołaniach, aby kontynuować rozmowę. Iteracje pętli domyślnie współdzielą tę sesję. Przy użyciu fresh_context=True warstwa pośrednia przywraca dołączoną sesję do stanu z migawki sprzed pętli między iteracjami. Magazyn konwersacji należących do usługi może zachować historię, gdy serializowana sesja zawiera tylko identyfikator konwersacji zdalnej.

Pomocnik języka Go harness.AgentConfig domyślnie nie dodaje pętli. Dołącz loop.New(...) w elemencie agent.Config.Middlewares elementu wywołującego, aby opakować skonfigurowanego agenta z ograniczonym ponownym wywołaniem.

Pętla kończy się, gdy iteracja generuje oczekujące żądania zatwierdzenia narzędzi. Nie zatwierdza narzędzi automatycznie. Przed kontynuowaniem obsłuż żądania na hoście i zwróć pasujące odpowiedzi akceptacji za pośrednictwem tej samej sesji.

Następne kroki

Głębiej