Ciclo dell'agente

Il ciclo dell'agente chiama nuovamente un agente fino a quando non viene soddisfatta una condizione di completamento. Usalo per il miglioramento iterativo, per completare attività da svolgere, per attendere attività in background o per valutare se una risposta soddisfa criteri espliciti.

Cicli autonomi sempre associati. Una condizione di completamento può avere esito negativo, un modello può bloccarsi e un analizzatore può essere probabilistico.

Importante

Il ciclo dell'agente è sperimentale.

Configura manualmente il loop

Usare l'API di composizione diretta quando si vuole eseguire un ciclo senza le altre impostazioni predefinite dell'agente Harness.

Importare i tipi di ciclo e avvolgere qualsiasi AIAgent con LoopAgent. Il valore massimo predefinito è 10 chiamate dell'agente:

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

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

Importare AgentLoopMiddleware e aggiungerlo a un normale oggetto Agent. Il valore massimo predefinito è 10 esecuzioni dell'agente:

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

Il predicato può essere sincrono o asincrono. Invio True per continuare, False per interrompere o (continue, feedback) per trasmettere il feedback all'iterazione successiva.

Go fornisce la reinvocazione limitata tramite agent/harness/loop. Eseguire la registrazione loop.New(loop.Config{...}) in agent.Config.Middlewares. Il middleware esegue l'agente, valuta la risposta e, facoltativamente, invia feedback in un'altra iterazione.

Nell'esempio Foundry seguente viene usato un marcatore di completamento. Richiede FOUNDRY_PROJECT_ENDPOINT, FOUNDRY_MODEL e una credenziale 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 è un *int facoltativo e il valore predefinito è 10. Impostare un limite esplicito per l'attività pianificata. Con più valutatori, il primo valutatore che richiede un'altra iterazione fornisce il proprio feedback; il ciclo si arresta solo quando tutti i valutatori si arrestano o viene raggiunto il limite di iterazione.

Per un esempio senza credenziali, vedere l'esempio di ciclo con script. Illustra il completamento del marker, un valutatore personalizzato e il limite di sicurezza dell'iterazione.

Scegliere una condizione di completamento

LoopAgent accetta un valutatore o una raccolta ordinata:

Valutatore Continua mentre
CompletionMarkerLoopEvaluator La risposta più recente non contiene il marcatore configurato.
TodoCompletionLoopEvaluator Un TodoProvider risolto presenta ancora elementi non completati, facoltativamente nelle modalità agente selezionate.
BackgroundTaskCompletionLoopEvaluator Un oggetto risolto BackgroundAgentsProvider ha ancora attività in esecuzione.
AIJudgeLoopEvaluator Un client giudice separato dice che alla richiesta originale non è stata fornita una risposta completa.
DelegateLoopEvaluator Il callback restituisce LoopEvaluation.Continue(...).

Quando sono configurati più valutatori, vengono eseguiti in ordine. Il primo analizzatore che richiede un'altra iterazione fornisce il proprio feedback; il ciclo si arresta solo quando tutti gli analizzatori rifiutano di continuare.

Usare un giudice di intelligenza artificiale

Il giudice riceve la richiesta originale e l'ultima risposta dell'agente. Se rileva un gap, l'analisi diventa feedback per l'iterazione successiva:

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

Affidare la richiesta originale e la risposta generata solo a un endpoint di valutazione affidabile.

Contesto di controllo e output

Per impostazione predefinita, LoopAgent riutilizza una sessione e invia il feedback più recente dell'analizzatore vincente come input successivo. FreshContextPerIteration = true ricompila invece ogni passaggio dalla richiesta originale e un log di feedback aggregato e reimposta o ripristina la sessione.

Le esecuzioni non di streaming restituiscono una trascrizione aggregata per impostazione predefinita. Impostare NonStreamingReturnsLastResponseOnly = true per restituire solo la risposta finale. La modalità di streaming restituisce sempre ogni iterazione e qualsiasi messaggio di feedback visibile inviato per conto dell'utente.

Il predicato riceve argomenti di parole chiave, tra cui iteration, last_resultmessages, original_messages, sessionagent, progress, e feedback. Gli helper todos_remaining() e background_tasks_running() forniscono condizioni predefinite per attività in background e da fare. Abbinali a todos_remaining_message o background_tasks_running_message per generare un input successivo mirato.

Usare un giudice di intelligenza artificiale

AgentLoopMiddleware.with_judge costruisce un ciclo guidato da un giudice. I cicli di giudici includono per impostazione predefinita cinque iterazioni:

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

Il ragionamento del giudice viene restituito all'agente quando è necessario ulteriore lavoro. Affidare la richiesta originale e la risposta generata solo a un endpoint di valutazione affidabile.

Controlla il contesto, l'avanzamento e l'output

Per i loop avanzati, costruisci AgentLoopMiddleware direttamente:

  • record_feedback crea una voce di avanzamento concisa dopo ogni iterazione di lavoro.
  • progress espone le voci accumulate ai callback.
  • inject_progress=True aggiunge lo stato di avanzamento all'input dell'iterazione successiva.
  • fresh_context=True riavvia dall'attività originale e dal log di avanzamento e ripristina una sessione collegata allo snapshot precedente al ciclo.
  • return_final_only=True restituisce solo l'ultima risposta per le esecuzioni non in streaming.

Passare max_iterations=None solo quando il predicato di completamento ha la garanzia di terminare.

Usare loop.NewCompletionMarkerEvaluator per arrestare quando la risposta più recente contiene un marcatore configurato. Per il completamento specifico dell'applicazione, implementare loop.Evaluator o usare loop.EvaluatorFunc, restituendo loop.Stop(), loop.Continue(feedback)o loop.ContinueWithMessages(messages).

FreshContextPerIteration viene riavviato dall'input originale più il feedback accumulato. NonStreamingReturnsLastResponseOnly limita un risultato non di streaming all'iterazione finale.

Go non include il valutatore AI-judge predefinito integrato mostrato negli esempi C#. Fornire un valutatore personalizzato se il completamento richiede un altro modello o un controllo esterno.

Usare un ciclo con l'agente di infrastruttura

Usa la configurazione di Harness Agent se vuoi anche le sue funzionalità preconfigurate di cronologia, pianificazione, memoria, approvazione e la pipeline di osservabilità.

Imposta HarnessAgentOptions.LoopEvaluators. L'infrastruttura usa LoopAgent come decorator più esterno dell'agente:

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

Una raccolta nullLoopEvaluators o vuota lascia l'infrastruttura singola.

Autorizzazione e comportamento della sessione

LoopAgent si interrompe prima di valutare la condizione di completamento quando un'iterazione restituisce una richiesta di approvazione dello strumento in sospeso. Restituisce la richiesta al chiamante anziché nasconderla dietro un'altra iterazione autonoma. Dopo che il chiamante ha fornito la risposta di approvazione tramite il normale flusso di approvazione dello strumento , l'agente può continuare.

LoopAgent non aggiunge di per sé la gestione dell'approvazione. L'agente di infrastruttura applica il ciclo all'esterno di ToolApprovalAgent, consentendo alle richieste di approvazione in sospeso di eseguire l'escape dal ciclo.

Riutilizzare lo stesso AgentSession tra le chiamate per continuare la conversazione. Per impostazione predefinita, le iterazioni del ciclo condividono la sessione. Con FreshContextPerIteration = true, LoopAgent reimposta o ripristina lo stato della sessione fornito dal chiamante, se supportato. L'archiviazione di conversazione di proprietà del servizio può mantenere la cronologia quando la sessione serializzata contiene solo un identificatore di conversazione remota.

Fornire loop_should_continue a create_harness_agent; loop_max_iterations il valore predefinito è 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 personalizza l'input successivo. Senza loop_should_continue, la factory non aggiunge un loop e ignora gli altri argomenti del loop.

Autorizzazione e comportamento della sessione

AgentLoopMiddleware si arresta prima di valutare il predicato di continuazione quando un'iterazione restituisce una richiesta di approvazione dello strumento in sospeso. Restituisce la richiesta al chiamante anziché nasconderla dietro un'altra iterazione autonoma. Dopo che il chiamante ha fornito la risposta di approvazione tramite il normale flusso di approvazione dello strumento , l'agente può continuare.

AgentLoopMiddleware non aggiunge ToolApprovalMiddleware da solo. L'agente di infrastruttura posiziona il ciclo all'esterno del middleware di approvazione, consentendo alle richieste di approvazione in sospeso di eseguire l'escape dal ciclo. Creare e passare un AgentSession a ogni esecuzione dell'agente di infrastruttura quando l'approvazione automatica degli strumenti è abilitata.

Riutilizzare lo stesso AgentSession tra le chiamate per continuare la conversazione. Per impostazione predefinita, le iterazioni del ciclo condividono la sessione. Con fresh_context=True, il middleware ripristina la sessione collegata allo snapshot precedente al ciclo tra un’iterazione e l'altra. L'archiviazione di conversazione di proprietà del servizio può mantenere la cronologia quando la sessione serializzata contiene solo un identificatore di conversazione remota.

L'helper Go harness.AgentConfig non aggiunge un ciclo per impostazione predefinita. Includi loop.New(...) nel chiamante agent.Config.Middlewares per eseguire il wrapping dell'agente configurato con la reinvocazione limitata.

Il ciclo termina quando un'iterazione produce richieste di approvazione degli strumenti in sospeso. Non li approva automaticamente. Gestire le richieste nell'host e restituire le risposte di approvazione corrispondenti tramite la stessa sessione prima di continuare.

Passaggi successivi

Approfondimento