代理后台响应

Microsoft Agent Framework 支持后台响应来处理长时间运行的作,这些作可能需要一段时间才能完成。 此功能使代理能够开始处理请求并返回一个延续令牌,该标记可用于轮询结果或恢复中断的流。

Tip

有关完整的工作示例,请参阅 后台响应示例。

何时使用后台响应

后台响应特别适用于:

  • 需要大量处理时间的复杂推理任务
  • 网络问题或客户端超时可能会中断的作
  • 想要启动长时间运行的任务并稍后查看结果的方案

后台响应的工作原理

后台响应使用 延续令牌 机制来处理长时间运行的作。 向启用了后台响应的代理发送请求时,会发生以下两种情况之一:

  1. 立即完成:代理快速完成任务并返回最终响应,无需继续标记
  2. 后台处理:代理开始在后台进行处理,并返回延续标记而不是最终结果

延续令牌包含使用非流式处理代理 API 轮询完成的所有必要信息,或者使用流式处理代理 API 恢复中断的流。 缺少的令牌(null在 .NET、 None Python 或 Go 中的空字符串中)表示操作已完成、失败或无法进一步执行,例如,需要用户输入时。

启用后台响应

若要启用后台响应,请将AllowBackgroundResponses属性设置为 true :AgentRunOptions

using Microsoft.Agents.AI;

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

注释

目前,只有使用 OpenAI 响应 API 的代理支持后台响应: OpenAI 响应代理 和 Azure OpenAI 响应代理。

某些代理可能不允许显式控制后台响应。 无论设置如何, AllowBackgroundResponses 这些代理都可以根据作的复杂性自主决定是否启动后台响应。

非流式处理后台响应

对于非流式处理方案,当你最初运行代理时,它可能会或可能不会返回延续令牌。 如果未返回延续标记,则表示作已完成。 如果返回延续令牌,则表示代理已启动仍在处理的后台响应,并且需要轮询才能检索最终结果:

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

Warning

DefaultAzureCredential 对于开发来说很方便,但在生产中需要仔细考虑。 在生产环境中,请考虑使用特定凭据(例如), ManagedIdentityCredential以避免延迟问题、意外凭据探测以及回退机制的潜在安全风险。

要点:

  • 初始调用可能立即完成(无继续标记)或启动后台作(带有继续标记)
  • 如果未返回延续标记,则作已完成,响应包含最终结果
  • 如果返回延续令牌,代理已启动需要轮询的后台进程
  • 在后续轮询调用中使用上一响应中的延续标记
  • ContinuationToken何时null完成作

流式处理后台响应

在流式处理方案中,后台响应的工作方式非常类似于常规流式处理响应 - 代理实时将所有更新流式传输到使用者。 但是,主要区别在于,如果原始流中断,代理支持通过延续令牌恢复流。 每个更新都包含一个延续令牌,该标记捕获当前状态,允许通过将此令牌传递给后续流 API 调用,从其离开的位置完全恢复流式处理:

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

要点:

  • 每个 AgentResponseUpdate 标记都包含可用于恢复的延续标记
  • 在中断之前存储上次收到的更新中的延续令牌
  • 使用存储的继续标记从中断点恢复流

Tip

有关完整的可运行示例,请参阅 .NET 示例 。

Tip

有关完整的工作示例,请参阅 后台响应示例。

启用后台响应

若要启用后台响应,请 background 传递调用 agent.run()时的选项:

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

注释

Python OpenAI 响应 API、Azure OpenAI 响应 API 或 Microsoft Foundry 支持的代理支持后台响应。

使用FoundryChatClient后台响应可以使用提供程序端响应存储()或无状态重播(store=Truestore=False)运行本地函数工具。 轮询时保留相同的会话,以便恢复的响应可以继续本地工具循环。

非流式处理后台响应

对于非流式处理方案,当你最初运行 background=True代理时,它可能会立即使用 a continuation_token. continuation_token如果是None,该作已完成。 否则,通过在后续调用中传递令牌来轮询:

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)

要点

  • 初始调用可能立即完成(无继续标记)或启动后台作(带有继续标记)
  • continuation_token在后续轮询调用中使用上一个响应中的响应
  • continuation_token何时None完成作

流式处理后台响应

在流式处理方案中,后台响应的工作方式类似于常规流式处理 , 代理流会实时更新。 主要区别在于,每个更新都包含一个 continuation_token,如果连接中断,则启用流恢复:

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

恢复中断的流

如果流中断,请使用最后 continuation_token 一个从中断位置恢复:

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)

要点

  • 每个AgentResponseUpdate项都包含一个用于恢复的continuation_token
  • 在中断之前存储上次收到的更新中的令牌
  • 传递存储的令牌 options={"continuation_token": token} 以恢复

启用后台响应

启动运行时传递agent.AllowBackgroundResponses(true),并重复使用显式会话。agent.WithSession(session) 提供程序和部署必须支持后台执行;设置选项不会使每个代理都异步。

非流式处理后台响应

启动该操作,然后在不为空的情况下 response.ContinuationToken 轮询。 继续操作 a.Run(ctx, nil, ...),而不是 RunText:继续调用不得包含新消息。

维护的 Azure OpenAI 响应示例将操作限制为超时、在轮询之间等待,并在取消时立即停止:

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

在运行此示例之前,设置AZURE_OPENAI_ENDPOINT并使用AZURE_OPENAI_DEPLOYMENT_NAMEAzure凭据进行身份验证。 它在轮询完成后打印已完成的响应。 立即完成的响应没有继续标记,不需要轮询。

流式处理后台响应

使用和 agent.AllowBackgroundResponses(true). 启动流式处理运行agent.Stream(true)。 保留你收到的上次更新中的延续令牌。 如果连接中断,请继续不显示新消息:

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

仅当保存的令牌不为空时恢复。 如果操作必须继续执行进程重启,则保留应用程序存储中的会话和令牌。

将后台响应与 Harness 代理配合使用

Harness 代理仍然是标准 Agent Framework 代理,因此提供程序后台响应使用上面记录的相同每运行选项。 Harness 构造不会自动启用提供程序后台响应:在.NET、 options={"background": True} Python或agent.AllowBackgroundResponses(true)启动运行时在 Go 中设置AllowBackgroundResponses。 当操作必须在进程重启后保留会话并保留继续标记。

这独立于 后台代理,后者将工作委托给子代理,而不是继续一个提供程序请求。

最佳做法

使用后台响应时,请考虑以下最佳做法:

  • 实现适当的轮询间隔 以避免服务压倒性
  • 如果作花费的时间超过预期,则对轮询间隔使用指数回退
  • 检查不存在的继续标记 (null或 None空 Go 字符串)以确定处理何时完成
  • 考虑将延续令牌持久存储 为可能跨越用户会话的作

限制和注意事项

  • 后台响应依赖于支持长时间运行的作的基础 AI 服务
  • 并非所有代理类型都支持后台响应
  • 网络中断或客户端重启可能需要特殊处理才能保留延续令牌

后续步骤

RAG