Agent-Hintergrundantworten

Das Microsoft Agent Framework unterstützt Hintergrundantworten für die Behandlung lang ausgeführter Vorgänge, die möglicherweise zeitverlangen. Mit diesem Feature können Agents die Verarbeitung einer Anforderung starten und ein Fortsetzungstoken zurückgeben, mit dem Ergebnisse abgerufen oder unterbrochene Datenströme fortgesetzt werden können.

Tip

Ein vollständiges Arbeitsbeispiel finden Sie im Beispiel "Hintergrundantworten".

Gründe für die Verwendung von Hintergrundantworten

Hintergrundantworten sind besonders nützlich für:

  • Komplexe Gründe für Aufgaben, die eine erhebliche Verarbeitungszeit erfordern
  • Vorgänge, die durch Netzwerkprobleme oder Clienttimeouts unterbrochen werden können
  • Szenarien, in denen Sie eine lange ausgeführte Aufgabe starten und später auf Ergebnisse zurückschauen möchten

Funktionsweise von Hintergrundantworten

Hintergrundantworten verwenden einen Fortsetzungstokenmechanismus , um lange ausgeführte Vorgänge zu verarbeiten. Wenn Sie eine Anforderung an einen Agent mit aktivierten Hintergrundantworten senden, geschieht eines von zwei Dingen:

  1. Sofortiger Abschluss: Der Agent schließt die Aufgabe schnell ab und gibt die endgültige Antwort ohne Fortsetzungstoken zurück.
  2. Hintergrundverarbeitung: Der Agent startet die Verarbeitung im Hintergrund und gibt ein Fortsetzungstoken anstelle des Endergebnisses zurück.

Das Fortsetzungstoken enthält alle erforderlichen Informationen, um entweder mithilfe der API des nicht streaming-Agents abgeschlossen zu werden oder einen unterbrochenen Stream mit der Streaming-Agent-API fortzusetzen. Ein fehlendes Token (null in .NET, None in Python oder einer leeren Zeichenfolge in Go) bedeutet, dass der Vorgang abgeschlossen, fehlgeschlagen ist oder nicht fortgesetzt werden kann, z. B. wenn Benutzereingaben erforderlich sind.

Aktivieren von Hintergrundantworten

Um Hintergrundantworten zu AllowBackgroundResponses aktivieren, legen Sie die true Eigenschaft auf folgendes festAgentRunOptions:

using Microsoft.Agents.AI;

AgentRunOptions options = new()
{
    AllowBackgroundResponses = true
};

Note

Derzeit unterstützen nur Agents, die die OpenAI-Antwort-API verwenden, Hintergrundantworten: OpenAI Responses Agent und Azure OpenAI Responses Agent.

Einige Agents erlauben möglicherweise keine explizite Kontrolle über Hintergrundantworten. Diese Agents können unabhängig von der AllowBackgroundResponses Einstellung selbst entscheiden, ob eine Hintergrundantwort basierend auf der Komplexität des Vorgangs initiiert werden soll.

Hintergrundantworten ohne Streaming

Bei Nicht-Streaming-Szenarien kann es bei der ersten Ausführung eines Agents ein Fortsetzungstoken zurückgeben oder nicht. Wenn kein Fortsetzungstoken zurückgegeben wird, bedeutet dies, dass der Vorgang abgeschlossen wurde. Wenn ein Fortsetzungstoken zurückgegeben wird, gibt es an, dass der Agent eine Hintergrundantwort initiiert hat, die noch verarbeitet wird, und erfordert eine Abfrage zum Abrufen des Endergebnisses:

using System;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;

AIAgent agent = new AIProjectClient(
    new Uri("<your-foundry-project-endpoint>"),
    new DefaultAzureCredential())
    .AsAIAgent(
        model: "<deployment-name>",
        instructions: "You are a helpful assistant.");

AgentRunOptions options = new()
{
    AllowBackgroundResponses = true
};

AgentSession session = await agent.CreateSessionAsync();

// Get initial response - may return with or without a continuation token.
AgentResponse response = await agent.RunAsync(
    "Write a very long novel about otters in space.",
    session,
    options);

// Continue to poll until the final response is received
while (response.ContinuationToken is not null)
{
    // Wait before polling again.
    await Task.Delay(TimeSpan.FromSeconds(2));

    options.ContinuationToken = response.ContinuationToken;
    response = await agent.RunAsync(session, options);
}

Console.WriteLine(response.Text);

Warnung

DefaultAzureCredential ist praktisch für die Entwicklung, erfordert aber sorgfältige Überlegungen in der Produktion. Berücksichtigen Sie in der Produktion die Verwendung bestimmter Anmeldeinformationen (z. B. ManagedIdentityCredential), um Latenzprobleme, unbeabsichtigte Abfragen von Anmeldeinformationen und potenzielle Sicherheitsrisiken durch Ausweichmechanismen zu vermeiden.

Wichtige Punkte:

  • Der anfängliche Aufruf kann sofort abgeschlossen werden (kein Fortsetzungstoken) oder einen Hintergrundvorgang (mit Fortsetzungstoken) starten.
  • Wenn kein Fortsetzungstoken zurückgegeben wird, ist der Vorgang abgeschlossen, und die Antwort enthält das endgültige Ergebnis.
  • Wenn ein Fortsetzungstoken zurückgegeben wird, hat der Agent einen Hintergrundprozess gestartet, der Abfragen erfordert.
  • Verwenden des Fortsetzungstokens aus der vorherigen Antwort in nachfolgenden Abrufaufrufen
  • Ist ContinuationToken dies nullder Zeitpunkt, ist der Vorgang abgeschlossen

Streaming von Hintergrundantworten

In Streamingszenarien funktionieren Hintergrundantworten ähnlich wie normale Streamingantworten – der Agent streamt alle Updates in Echtzeit an Verbraucher zurück. Der Hauptunterschied besteht jedoch darin, dass Agents die Stream-Wiederaufnahme über Fortsetzungstoken unterstützen, wenn der ursprüngliche Datenstrom unterbrochen wird. Jedes Update enthält ein Fortsetzungstoken, das den aktuellen Zustand erfasst, sodass der Datenstrom von genau der Stelle fortgesetzt werden kann, an der es unterbrochen wurde, indem es dieses Token an nachfolgende Streaming-API-Aufrufe übergibt:

using System;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;

AIAgent agent = new AIProjectClient(
    new Uri("<your-foundry-project-endpoint>"),
    new DefaultAzureCredential())
    .AsAIAgent(
        model: "<deployment-name>",
        instructions: "You are a helpful assistant.");

AgentRunOptions options = new()
{
    AllowBackgroundResponses = true
};

AgentSession session = await agent.CreateSessionAsync();

AgentResponseUpdate? latestReceivedUpdate = null;

await foreach (var update in agent.RunStreamingAsync(
    "Write a very long novel about otters in space.",
    session,
    options))
{
    Console.Write(update.Text);

    latestReceivedUpdate = update;

    // Simulate an interruption
    break;
}

// Resume from interruption point captured by the continuation token
options.ContinuationToken = latestReceivedUpdate?.ContinuationToken;
await foreach (var update in agent.RunStreamingAsync(session, options))
{
    Console.Write(update.Text);
}

Wichtige Punkte:

  • Jedes AgentResponseUpdate enthält ein Fortsetzungstoken, das für die Wiederaufnahme verwendet werden kann
  • Speichern des Fortsetzungstokens aus dem letzten empfangenen Update vor Unterbrechung
  • Verwenden des gespeicherten Fortsetzungstokens zum Fortsetzen des Datenstroms vom Unterbrechungspunkt

Tip

In den .NET-Beispielen finden Sie vollständige ausführbare Beispiele.

Tip

Ein vollständiges Arbeitsbeispiel finden Sie im Beispiel "Hintergrundantworten".

Aktivieren von Hintergrundantworten

Um Hintergrundantworten zu aktivieren, übergeben Sie die background Option beim Aufrufen agent.run():

session = agent.create_session()
response = await agent.run(
    messages="Your prompt here",
    session=session,
    options={"background": True},
)

Note

Python Agents, die von der OpenAI-Antwort-API unterstützt werden, Azure OpenAI-Antwort-API oder Microsoft Foundry Hintergrundantworten unterstützen.

Mithilfe FoundryChatClientvon Hintergrundantworten können lokale Funktionstools entweder mit anbieterseitigem Antwortspeicher (store=True) oder zustandsloser Wiedergabe (store=False) ausgeführt werden. Behalten Sie dieselbe Sitzung bei der Abfrage bei, damit die fortgesetzte Antwort die lokale Toolschleife fortsetzen kann.

Hintergrundantworten ohne Streaming

Bei Nicht-Streaming-Szenarien kann der Agent bei der ersten Ausführung eines Agents background=Truesofort mit einem continuation_token. Wenn continuation_token ja None, wurde der Vorgang abgeschlossen. Andernfalls rufen Sie das Token ab, indem Sie das Token in nachfolgenden Aufrufen zurückgibt:

import asyncio
from agent_framework import Agent
from agent_framework.openai import OpenAIChatClient

agent = Agent(
    name="researcher",
    instructions="You are a helpful research assistant.",
    client=OpenAIChatClient(model="o3"),
)

session = agent.create_session()

# Start a background run — returns immediately
response = await agent.run(
    messages="Briefly explain the theory of relativity in two sentences.",
    session=session,
    options={"background": True},
)

# Poll until the operation completes
while response.continuation_token is not None:
    await asyncio.sleep(2)
    response = await agent.run(
        session=session,
        options={"continuation_token": response.continuation_token},
    )

# Done — response.text contains the final result
print(response.text)

Die wichtigsten Punkte

  • Der anfängliche Aufruf kann sofort abgeschlossen werden (kein Fortsetzungstoken) oder einen Hintergrundvorgang (mit Fortsetzungstoken) starten.
  • Verwenden der continuation_token vorherigen Antwort in nachfolgenden Abrufaufrufen
  • Ist continuation_token dies Noneder Zeitpunkt, ist der Vorgang abgeschlossen

Streaming von Hintergrundantworten

In Streamingszenarien funktionieren Hintergrundantworten wie normales Streaming – der Agent streamt Aktualisierungen in Echtzeit zurück. Der Hauptunterschied besteht darin, dass jedes Update eine continuation_tokenAktivierung der Datenstromaufnahme enthält, wenn die Verbindung unterbrochen wird:

session = agent.create_session()

# Start a streaming background run
last_token = None
stream = agent.run(
    messages="Briefly list three benefits of exercise.",
    stream=True,
    session=session,
    options={"background": True},
)

# Read chunks — each update carries a continuation_token
async for update in stream:
    last_token = update.continuation_token
    if update.text:
        print(update.text, end="", flush=True)
    # If interrupted (e.g., network issue), break and resume later

Fortsetzen eines unterbrochenen Datenstroms

Wenn der Datenstrom unterbrochen wird, verwenden Sie den letzten continuation_token , um den Vorgang fortzusetzen, von dem er unterbrochen wurde:

if last_token is not None:
    stream = agent.run(
        stream=True,
        session=session,
        options={"continuation_token": last_token},
    )
    async for update in stream:
        if update.text:
            print(update.text, end="", flush=True)

Die wichtigsten Punkte

  • Jede AgentResponseUpdate enthält eine continuation_token Fortsetzung
  • Speichern des Tokens aus dem letzten empfangenen Update vor Unterbrechung
  • Übergeben des gespeicherten Tokens options={"continuation_token": token} zum Fortsetzen

Aktivieren von Hintergrundantworten

Übergeben Sie agent.AllowBackgroundResponses(true) beim Starten einer Ausführung, und verwenden Sie eine explizite Sitzung über agent.WithSession(session). Der Anbieter und die Bereitstellung müssen die Hintergrundausführung unterstützen; Wenn Sie die Option festlegen, wird nicht jeder Agent asynchron.

Hintergrundantworten ohne Streaming

Starten Sie den Vorgang, und führen Sie dann eine Abfrage aus, während response.ContinuationToken sie nicht leer ist. Weiter mit , nichtRunText: a.Run(ctx, nil, ...)Fortsetzungsaufrufe dürfen keine neuen Nachrichten enthalten.

Das verwaltete Azure OpenAI-Antwortbeispiel begrenzt den Vorgang mit einem Timeout, wartet zwischen Umfragen und stoppt umgehend beim Abbruch:

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

// This sample demonstrates long-running agent operations using the OpenAI
// Responses API "background" option. A background run returns quickly with a
// continuation token instead of the final answer; the caller then polls with
// that token until the operation completes.
//
// Ported from the Python getting-started "background responses" sample.
package main

import (
    "context"
    "time"

    "github.com/microsoft/agent-framework-go/agent"
    "github.com/microsoft/agent-framework-go/examples/internal/demo"
    "github.com/microsoft/agent-framework-go/provider/openaiprovider"
    "github.com/openai/openai-go/v3"
    "github.com/openai/openai-go/v3/azure"
    "github.com/openai/openai-go/v3/option"
)

var logger = demo.NewLogger(
    "Background Responses",
    "Starts a background Responses run and polls with the continuation token until it completes.",
    "Model", demo.Deployment,
)

func main() {
    // Bound the whole sample so a run that never completes (stuck queued, a bad
    // continuation token, etc.) cannot hang indefinitely.
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
    defer cancel()

    token := demo.AzureTokenCredential()

    client := openai.NewClient(
        option.WithBaseURL(demo.Endpoint),
        azure.WithTokenCredential(token),
    )

    researcher := openaiprovider.NewResponsesAgent(
        client,
        openaiprovider.AgentConfig{
            Model:        demo.Deployment,
            Instructions: "You are a helpful research assistant. Be concise.",
            Config: agent.Config{
                Name:        "Researcher",
                Middlewares: []agent.Middleware{logger},
            },
        },
    )

    // Background runs are tied to a session so that follow-up polls target the
    // same operation.
    session, err := researcher.CreateSession(ctx)
    if err != nil {
        demo.Panic(err)
    }

    // Start a background run. It returns quickly with a continuation token
    // rather than the final answer. (If the model or endpoint does not support
    // background execution, the run simply completes inline with no token.)
    resp, err := researcher.RunText(ctx,
        "Briefly explain the theory of relativity in two sentences.",
        agent.WithSession(session),
        agent.AllowBackgroundResponses(true),
    ).Collect()
    if err != nil {
        demo.Panic(err)
    }

    // Poll until the operation completes — i.e. until a run no longer returns a
    // continuation token. Continuation runs must not carry any messages, so use
    // Run with a nil message slice.
    for resp.ContinuationToken != "" {
        // Wait between polls, but stop promptly if the context is cancelled or
        // its deadline is reached rather than sleeping through it.
        select {
        case <-ctx.Done():
            demo.Panic(ctx.Err())
        case <-time.After(2 * time.Second):
        }
        resp, err = researcher.Run(ctx, nil,
            agent.WithSession(session),
            agent.WithContinuationToken(resp.ContinuationToken),
        ).Collect()
        if err != nil {
            demo.Panic(err)
        }
    }

    // The final response holds the completed result.
    demo.Response(resp, nil)
}

Legen Sie AZURE_OPENAI_ENDPOINT vor dem Ausführen dieses Beispiels eine Azure Anmeldeinformationen fest und AZURE_OPENAI_DEPLOYMENT_NAMEauthentifizieren Sie sie. Sie druckt die abgeschlossene Antwort, nachdem die Abfrage abgeschlossen wurde. Eine sofort abgeschlossene Antwort hat kein Fortsetzungstoken und benötigt keine Abfrage.

Streaming von Hintergrundantworten

Starten Sie eine Streamingausführung mit agent.Stream(true) und agent.AllowBackgroundResponses(true). Behalten Sie das Fortsetzungstoken von der letzten aktualisierung bei, die Sie erhalten haben. Wenn die Verbindung unterbrochen wird, setzen Sie sie ohne neue Nachrichten fort:

for update, err := range a.Run(
    ctx,
    nil,
    agent.WithSession(session),
    agent.WithContinuationToken(lastToken),
    agent.Stream(true),
) {
    if err != nil {
        panic(err)
    }
    lastToken = update.ContinuationToken
    fmt.Print(update.String())
}

Wird nur fortgesetzt, wenn das gespeicherte Token nicht leer ist. Bewahren Sie sowohl die Sitzung als auch das Token im Anwendungsspeicher auf, wenn der Vorgang einen Prozessneustart überleben muss.

Verwenden von Hintergrundantworten mit dem Nutzungs-Agent

Ein Benutzerfreundlichkeits-Agent bleibt ein Standardmäßiger Agent-Framework-Agent, sodass Die Hintergrundantworten des Anbieters die gleichen Pro-Run-Optionen verwenden, die oben dokumentiert sind. Die Erstellung von Nutzungsfunktionen ermöglicht keine automatischen Hintergrundantworten des Anbieters: Festlegen AllowBackgroundResponses in .NET, options={"background": True} in Python oder agent.AllowBackgroundResponses(true) in "Go" beim Starten der Ausführung. Behalten Sie die Sitzung bei, und speichern Sie Fortsetzungstoken, wenn der Vorgang einen Prozessneustart überleben muss.

Dies unterscheidet sich von Hintergrund-Agents, die Arbeit an untergeordnete Agents delegieren, anstatt eine Anbieteranforderung fortzusetzen.

Bewährte Methoden

Berücksichtigen Sie beim Arbeiten mit Hintergrundantworten die folgenden bewährten Methoden:

  • Implementieren sie geeignete Abrufintervalle , um zu vermeiden, dass der Dienst überwältigend ist
  • Exponentielles Backoff für Abrufintervalle verwenden, wenn der Vorgang länger dauert als erwartet
  • Überprüfen Sie, ob ein fehlendes Fortsetzungstoken (null, oder eine leere Go-Zeichenfolge) vorhanden ist, um festzustellen, Nonewann die Verarbeitung abgeschlossen ist.
  • Erwägen Sie, Fortsetzungstoken dauerhaft für Vorgänge zu speichern, die Benutzersitzungen umfassen können.

Einschränkungen und Überlegungen

  • Hintergrundantworten sind vom zugrunde liegenden KI-Dienst abhängig, der lange ausgeführte Vorgänge unterstützt
  • Nicht alle Agenttypen unterstützen möglicherweise Hintergrundantworten
  • Netzwerkunterbrechungen oder Clientneustarts erfordern möglicherweise eine spezielle Behandlung, um Fortsetzungstoken beizubehalten.

Nächste Schritte

RAG