Белешка
Приступ овој страници захтева ауторизацију. Можете покушати да се пријавите или промените директоријуме.
Приступ овој страници захтева ауторизацију. Можете покушати да промените директоријуме.
The Microsoft Agent Framework supports background responses for handling long-running operations that may take time to complete. This feature enables agents to start processing a request and return a continuation token that can be used to poll for results or resume interrupted streams.
Tip
For a complete working example, see the Background Responses sample.
When to Use Background Responses
Background responses are particularly useful for:
- Complex reasoning tasks that require significant processing time
- Operations that may be interrupted by network issues or client timeouts
- Scenarios where you want to start a long-running task and check back later for results
How Background Responses Work
Background responses use a continuation token mechanism to handle long-running operations. When you send a request to an agent with background responses enabled, one of two things happens:
- Immediate completion: The agent completes the task quickly and returns the final response without a continuation token
- Background processing: The agent starts processing in the background and returns a continuation token instead of the final result
The continuation token contains all necessary information to either poll for completion using the non-streaming agent API or resume an interrupted stream with streaming agent API. An absent token (null in .NET, None in Python, or an empty string in Go) means the operation has completed, failed, or can't proceed further, for example, when user input is required.
Enabling Background Responses
To enable background responses, set the AllowBackgroundResponses property to true in the AgentRunOptions:
using Microsoft.Agents.AI;
AgentRunOptions options = new()
{
AllowBackgroundResponses = true
};
Note
Currently, only agents that use the OpenAI Responses API support background responses: OpenAI Responses Agent and Azure OpenAI Responses Agent.
Some agents may not allow explicit control over background responses. These agents can decide autonomously whether to initiate a background response based on the complexity of the operation, regardless of the AllowBackgroundResponses setting.
Non-Streaming Background Responses
For non-streaming scenarios, when you initially run an agent, it may or may not return a continuation token. If no continuation token is returned, it means the operation has completed. If a continuation token is returned, it indicates that the agent has initiated a background response that is still processing and will require polling to retrieve the final result:
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 is convenient for development but requires careful consideration in production. In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
Key Points:
- The initial call may complete immediately (no continuation token) or start a background operation (with continuation token)
- If no continuation token is returned, the operation is complete and the response contains the final result
- If a continuation token is returned, the agent has started a background process that requires polling
- Use the continuation token from the previous response in subsequent polling calls
- When
ContinuationTokenisnull, the operation is complete
Streaming Background Responses
In streaming scenarios, background responses work much like regular streaming responses - the agent streams all updates back to consumers in real-time. However, the key difference is that if the original stream gets interrupted, agents support stream resumption through continuation tokens. Each update includes a continuation token that captures the current state, allowing the stream to be resumed from exactly where it left off by passing this token to subsequent streaming API calls:
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);
}
Key Points:
- Each
AgentResponseUpdatecontains a continuation token that can be used for resumption - Store the continuation token from the last received update before interruption
- Use the stored continuation token to resume the stream from the interruption point
Tip
See the .NET samples for complete runnable examples.
Tip
For a complete working example, see the Background Responses sample.
Enabling Background Responses
To enable background responses, pass the background option when calling agent.run():
session = agent.create_session()
response = await agent.run(
messages="Your prompt here",
session=session,
options={"background": True},
)
Note
Python agents backed by the OpenAI Responses API, Azure OpenAI Responses API, or Microsoft Foundry support background responses.
With FoundryChatClient, background responses can run local function tools with either provider-side response storage (store=True) or stateless replay (store=False). Keep the same session while polling so the resumed response can continue the local tool loop.
Non-Streaming Background Responses
For non-streaming scenarios, when you initially run an agent with background=True, it may return immediately with a continuation_token. If continuation_token is None, the operation has completed. Otherwise, poll by passing the token back in subsequent calls:
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)
Key Points
- The initial call may complete immediately (no continuation token) or start a background operation (with continuation token)
- Use the
continuation_tokenfrom the previous response in subsequent polling calls - When
continuation_tokenisNone, the operation is complete
Streaming Background Responses
In streaming scenarios, background responses work like regular streaming — the agent streams updates back in real time. The key difference is that each update includes a continuation_token, enabling stream resumption if the connection is interrupted:
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
Resuming an Interrupted Stream
If the stream is interrupted, use the last continuation_token to resume from where it left off:
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)
Key Points
- Each
AgentResponseUpdatecontains acontinuation_tokenfor resumption - Store the token from the last received update before interruption
- Pass the stored token via
options={"continuation_token": token}to resume
Enable background responses
Pass agent.AllowBackgroundResponses(true) when starting a run, and reuse an explicit session through agent.WithSession(session). The provider and deployment must support background execution; setting the option doesn't make every agent asynchronous.
Non-streaming background responses
Start the operation, then poll while response.ContinuationToken isn't empty. Continue with a.Run(ctx, nil, ...), not RunText: continuation calls must not contain new messages.
The maintained Azure OpenAI Responses sample bounds the operation with a timeout, waits between polls, and stops promptly on cancellation:
// 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)
}
Set AZURE_OPENAI_ENDPOINT and AZURE_OPENAI_DEPLOYMENT_NAME, and authenticate with an Azure credential before running this sample. It prints the completed response after polling finishes. An immediately completed response has no continuation token and doesn't need polling.
Streaming background responses
Start a streaming run with agent.Stream(true) and agent.AllowBackgroundResponses(true). Retain the continuation token from the last update you receive. If the connection is interrupted, resume without new messages:
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())
}
Resume only when the saved token isn't empty. Preserve both the session and token in application storage if the operation must survive a process restart.
Use background responses with Harness Agent
A Harness Agent remains a standard Agent Framework agent, so provider background responses use the same per-run options documented above. Harness construction doesn't enable provider background responses automatically: set AllowBackgroundResponses in .NET, options={"background": True} in Python, or agent.AllowBackgroundResponses(true) in Go when starting the run. Keep the session and persist continuation tokens when the operation must survive a process restart.
This is separate from background agents, which delegate work to child agents rather than continuing one provider request.
Best Practices
When working with background responses, consider the following best practices:
- Implement appropriate polling intervals to avoid overwhelming the service
- Use exponential backoff for polling intervals if the operation is taking longer than expected
- Check for an absent continuation token (
null,None, or an empty Go string) to determine when processing is complete - Consider storing continuation tokens persistently for operations that may span user sessions
Limitations and Considerations
- Background responses are dependent on the underlying AI service supporting long-running operations
- Not all agent types may support background responses
- Network interruptions or client restarts may require special handling to persist continuation tokens