mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
* .NET: Delete AgentResponse.{Try}Deserialize<T> methods (#3518)
* delete deserialize method of agent response
* order usings
* Update dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/Program.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/samples/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/Program.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/SharedStateAgent.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/samples/AGUIClientServer/AGUIDojoServer/SharedState/SharedStateAgent.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/samples/M365Agent/Agents/WeatherForecastAgent.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* .NET:[Breaking] Add support for structured output (#3658)
* add support for so
* restore lost xml comment part
* fix using ordering
* Update dotnet/src/Microsoft.Agents.AI.Abstractions/AIAgentStructuredOutput.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/src/Microsoft.Agents.AI.Abstractions/AIAgentStructuredOutput.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgent_SO_WithFormatResponseTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* addressw pr review comments
* address pr review feedback
* address pr review comments
* fix compilation issues after the latest merge with main
* remove unnecessry options
* remove RunAsync<object> methods
* address code review feedback
* address pr review feedback
* make copy constructor protected
* address pr review feedback
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* .NET: Add decorator for structured output support (#3694)
* add decorator that adds structured output support to agents that don't natively support it.
* Update dotnet/src/Microsoft.Agents.AI/StructuredOutput/StructuredOutputAgentResponse.cs
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
* Update dotnet/samples/GettingStarted/Agents/Agent_Step05_StructuredOutput/Program.cs
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
* address pr review feedback
---------
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
* .NET: Support primitives and arrays for SO (#3696)
* wrap primitives and arrays
* fix file encoding
* address review comments
* add adr
* add missed change
* fix compilation issue
* address review comments
* rename adr file name
* reflect decision to have SO decorator as a reference implementation in samples
* .NET: Move SO agent to samples (#3820)
* move SO agent to samples
* change file encoding
* fix files encoding
* .NET: Preserve caller context (#3803)
* fix stuck orchestration
* add previously removed RunAsync<T> method to DurableAIAgent
* suppress IDE0005 warning
* update changelog and remove unused constructor of AgentResponse<T>
* updatge the changelog
* address PR review feedback
* .NET: Disable irrelevant integration test (#3913)
* disable irrelevant integration test
* Update dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentStructuredOutputRunTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* forgotten change
* address pr review feedback
* disable intermittently failing integration test.
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
474 lines
28 KiB
C#
474 lines
28 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text.Json;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Extensions.AI;
|
|
using Microsoft.Shared.Diagnostics;
|
|
|
|
namespace Microsoft.Agents.AI;
|
|
|
|
/// <summary>
|
|
/// Provides the base abstraction for all AI agents, defining the core interface for agent interactions and conversation management.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <see cref="AIAgent"/> serves as the foundational class for implementing AI agents that can participate in conversations
|
|
/// and process user requests. An agent instance may participate in multiple concurrent conversations, and each conversation
|
|
/// may involve multiple agents working together.
|
|
/// </remarks>
|
|
[DebuggerDisplay("{DebuggerDisplay,nq}")]
|
|
public abstract partial class AIAgent
|
|
{
|
|
private static readonly AsyncLocal<AgentRunContext?> s_currentContext = new();
|
|
|
|
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
|
private string DebuggerDisplay =>
|
|
this.Name is { } name ? $"Id = {this.Id}, Name = {name}" : $"Id = {this.Id}";
|
|
|
|
/// <summary>
|
|
/// Gets the unique identifier for this agent instance.
|
|
/// </summary>
|
|
/// <value>
|
|
/// A unique string identifier for the agent. For in-memory agents, this defaults to a randomly-generated ID,
|
|
/// while service-backed agents typically use the identifier assigned by the backing service.
|
|
/// </value>
|
|
/// <remarks>
|
|
/// Agent identifiers are used for tracking, telemetry, and distinguishing between different
|
|
/// agent instances in multi-agent scenarios. They should remain stable for the lifetime
|
|
/// of the agent instance.
|
|
/// </remarks>
|
|
public string Id { get => this.IdCore ?? field; } = Guid.NewGuid().ToString("N");
|
|
|
|
/// <summary>
|
|
/// Gets a custom identifier for the agent, which can be overridden by derived classes.
|
|
/// </summary>
|
|
/// <value>
|
|
/// A string representing the agent's identifier, or <see langword="null"/> if the default ID should be used.
|
|
/// </value>
|
|
/// <remarks>
|
|
/// Derived classes can override this property to provide a custom identifier.
|
|
/// When <see langword="null"/> is returned, the <see cref="Id"/> property will use the default randomly-generated identifier.
|
|
/// </remarks>
|
|
protected virtual string? IdCore => null;
|
|
|
|
/// <summary>
|
|
/// Gets the human-readable name of the agent.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The agent's name, or <see langword="null"/> if no name has been assigned.
|
|
/// </value>
|
|
/// <remarks>
|
|
/// The agent name is typically used for display purposes and to help users identify
|
|
/// the agent's purpose or capabilities in user interfaces.
|
|
/// </remarks>
|
|
public virtual string? Name { get; }
|
|
|
|
/// <summary>
|
|
/// Gets a description of the agent's purpose, capabilities, or behavior.
|
|
/// </summary>
|
|
/// <value>
|
|
/// A descriptive text explaining what the agent does, or <see langword="null"/> if no description is available.
|
|
/// </value>
|
|
/// <remarks>
|
|
/// The description helps models and users understand the agent's intended purpose and capabilities,
|
|
/// which is particularly useful in multi-agent systems.
|
|
/// </remarks>
|
|
public virtual string? Description { get; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the <see cref="AgentRunContext"/> for the current agent run.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This value flows across async calls.
|
|
/// </remarks>
|
|
public static AgentRunContext? CurrentRunContext
|
|
{
|
|
get => s_currentContext.Value;
|
|
protected set => s_currentContext.Value = value;
|
|
}
|
|
|
|
/// <summary>Asks the <see cref="AIAgent"/> for an object of the specified type <paramref name="serviceType"/>.</summary>
|
|
/// <param name="serviceType">The type of object being requested.</param>
|
|
/// <param name="serviceKey">An optional key that can be used to help identify the target service.</param>
|
|
/// <returns>The found object, otherwise <see langword="null"/>.</returns>
|
|
/// <exception cref="ArgumentNullException"><paramref name="serviceType"/> is <see langword="null"/>.</exception>
|
|
/// <remarks>
|
|
/// The purpose of this method is to allow for the retrieval of strongly-typed services that might be provided by the <see cref="AIAgent"/>,
|
|
/// including itself or any services it might be wrapping. For example, to access the <see cref="AIAgentMetadata"/> for the instance,
|
|
/// <see cref="GetService"/> may be used to request it.
|
|
/// </remarks>
|
|
public virtual object? GetService(Type serviceType, object? serviceKey = null)
|
|
{
|
|
_ = Throw.IfNull(serviceType);
|
|
|
|
return serviceKey is null && serviceType.IsInstanceOfType(this)
|
|
? this
|
|
: null;
|
|
}
|
|
|
|
/// <summary>Asks the <see cref="AIAgent"/> for an object of type <typeparamref name="TService"/>.</summary>
|
|
/// <typeparam name="TService">The type of the object to be retrieved.</typeparam>
|
|
/// <param name="serviceKey">An optional key that can be used to help identify the target service.</param>
|
|
/// <returns>The found object, otherwise <see langword="null"/>.</returns>
|
|
/// <remarks>
|
|
/// The purpose of this method is to allow for the retrieval of strongly typed services that may be provided by the <see cref="AIAgent"/>,
|
|
/// including itself or any services it might be wrapping.
|
|
/// </remarks>
|
|
public TService? GetService<TService>(object? serviceKey = null)
|
|
=> this.GetService(typeof(TService), serviceKey) is TService service ? service : default;
|
|
|
|
/// <summary>
|
|
/// Creates a new conversation session that is compatible with this agent.
|
|
/// </summary>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>A value task that represents the asynchronous operation. The task result contains a new <see cref="AgentSession"/> instance ready for use with this agent.</returns>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// This method creates a fresh conversation session that can be used to maintain state
|
|
/// and context for interactions with this agent. Each session represents an independent
|
|
/// conversation session.
|
|
/// </para>
|
|
/// <para>
|
|
/// If the agent supports multiple session types, this method returns the default or
|
|
/// configured session type. For service-backed agents, the actual session creation
|
|
/// may be deferred until first use to optimize performance.
|
|
/// </para>
|
|
/// </remarks>
|
|
public ValueTask<AgentSession> CreateSessionAsync(CancellationToken cancellationToken = default)
|
|
=> this.CreateSessionCoreAsync(cancellationToken);
|
|
|
|
/// <summary>
|
|
/// Core implementation of session creation logic.
|
|
/// </summary>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>A value task that represents the asynchronous operation. The task result contains a new <see cref="AgentSession"/> instance ready for use with this agent.</returns>
|
|
/// <remarks>
|
|
/// This is the primary session creation method that implementations must override.
|
|
/// </remarks>
|
|
protected abstract ValueTask<AgentSession> CreateSessionCoreAsync(CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Serializes an agent session to its JSON representation.
|
|
/// </summary>
|
|
/// <param name="session">The <see cref="AgentSession"/> to serialize.</param>
|
|
/// <param name="jsonSerializerOptions">Optional settings to customize the serialization process.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>A value task that represents the asynchronous operation. The task result contains a <see cref="JsonElement"/> with the serialized session state.</returns>
|
|
/// <exception cref="ArgumentNullException"><paramref name="session"/> is <see langword="null"/>.</exception>
|
|
/// <exception cref="InvalidOperationException">The type of <paramref name="session"/> is not supported by this agent.</exception>
|
|
/// <remarks>
|
|
/// This method enables saving conversation sessions to persistent storage,
|
|
/// allowing conversations to resume across application restarts or be migrated between
|
|
/// different agent instances. Use <see cref="DeserializeSessionAsync"/> to restore the session.
|
|
/// </remarks>
|
|
public ValueTask<JsonElement> SerializeSessionAsync(AgentSession session, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default)
|
|
=> this.SerializeSessionCoreAsync(session, jsonSerializerOptions, cancellationToken);
|
|
|
|
/// <summary>
|
|
/// Core implementation of session serialization logic.
|
|
/// </summary>
|
|
/// <param name="session">The <see cref="AgentSession"/> to serialize.</param>
|
|
/// <param name="jsonSerializerOptions">Optional settings to customize the serialization process.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>A value task that represents the asynchronous operation. The task result contains a <see cref="JsonElement"/> with the serialized session state.</returns>
|
|
/// <remarks>
|
|
/// This is the primary session serialization method that implementations must override.
|
|
/// </remarks>
|
|
protected abstract ValueTask<JsonElement> SerializeSessionCoreAsync(AgentSession session, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Deserializes an agent session from its JSON serialized representation.
|
|
/// </summary>
|
|
/// <param name="serializedState">A <see cref="JsonElement"/> containing the serialized session state.</param>
|
|
/// <param name="jsonSerializerOptions">Optional settings to customize the deserialization process.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>A value task that represents the asynchronous operation. The task result contains a restored <see cref="AgentSession"/> instance with the state from <paramref name="serializedState"/>.</returns>
|
|
/// <exception cref="ArgumentException">The <paramref name="serializedState"/> is not in the expected format.</exception>
|
|
/// <exception cref="JsonException">The serialized data is invalid or cannot be deserialized.</exception>
|
|
/// <remarks>
|
|
/// This method enables restoration of conversation sessions from previously saved state,
|
|
/// allowing conversations to resume across application restarts or be migrated between
|
|
/// different agent instances.
|
|
/// </remarks>
|
|
public ValueTask<AgentSession> DeserializeSessionAsync(JsonElement serializedState, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default)
|
|
=> this.DeserializeSessionCoreAsync(serializedState, jsonSerializerOptions, cancellationToken);
|
|
|
|
/// <summary>
|
|
/// Core implementation of session deserialization logic.
|
|
/// </summary>
|
|
/// <param name="serializedState">A <see cref="JsonElement"/> containing the serialized session state.</param>
|
|
/// <param name="jsonSerializerOptions">Optional settings to customize the deserialization process.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>A value task that represents the asynchronous operation. The task result contains a restored <see cref="AgentSession"/> instance with the state from <paramref name="serializedState"/>.</returns>
|
|
/// <remarks>
|
|
/// This is the primary session deserialization method that implementations must override.
|
|
/// </remarks>
|
|
protected abstract ValueTask<AgentSession> DeserializeSessionCoreAsync(JsonElement serializedState, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Run the agent with no message assuming that all required instructions are already provided to the agent or on the session.
|
|
/// </summary>
|
|
/// <param name="session">
|
|
/// The conversation session to use for this invocation. If <see langword="null"/>, a new session will be created.
|
|
/// The session will be updated with any response messages generated during invocation.
|
|
/// </param>
|
|
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
|
/// <remarks>
|
|
/// This overload is useful when the agent has sufficient context from previous messages in the session
|
|
/// or from its initial configuration to generate a meaningful response without additional input.
|
|
/// </remarks>
|
|
public Task<AgentResponse> RunAsync(
|
|
AgentSession? session = null,
|
|
AgentRunOptions? options = null,
|
|
CancellationToken cancellationToken = default) =>
|
|
this.RunAsync([], session, options, cancellationToken);
|
|
|
|
/// <summary>
|
|
/// Runs the agent with a text message from the user.
|
|
/// </summary>
|
|
/// <param name="message">The user message to send to the agent.</param>
|
|
/// <param name="session">
|
|
/// The conversation session to use for this invocation. If <see langword="null"/>, a new session will be created.
|
|
/// The session will be updated with the input message and any response messages generated during invocation.
|
|
/// </param>
|
|
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
|
/// <exception cref="ArgumentException"><paramref name="message"/> is <see langword="null"/>, empty, or contains only whitespace.</exception>
|
|
/// <remarks>
|
|
/// The provided text will be wrapped in a <see cref="ChatMessage"/> with the <see cref="ChatRole.User"/> role
|
|
/// before being sent to the agent. This is a convenience method for simple text-based interactions.
|
|
/// </remarks>
|
|
public Task<AgentResponse> RunAsync(
|
|
string message,
|
|
AgentSession? session = null,
|
|
AgentRunOptions? options = null,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
_ = Throw.IfNullOrWhitespace(message);
|
|
|
|
return this.RunAsync(new ChatMessage(ChatRole.User, message), session, options, cancellationToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Runs the agent with a single chat message.
|
|
/// </summary>
|
|
/// <param name="message">The chat message to send to the agent.</param>
|
|
/// <param name="session">
|
|
/// The conversation session to use for this invocation. If <see langword="null"/>, a new session will be created.
|
|
/// The session will be updated with the input message and any response messages generated during invocation.
|
|
/// </param>
|
|
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
|
/// <exception cref="ArgumentNullException"><paramref name="message"/> is <see langword="null"/>.</exception>
|
|
public Task<AgentResponse> RunAsync(
|
|
ChatMessage message,
|
|
AgentSession? session = null,
|
|
AgentRunOptions? options = null,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
_ = Throw.IfNull(message);
|
|
|
|
return this.RunAsync([message], session, options, cancellationToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Runs the agent with a collection of chat messages, providing the core invocation logic that all other overloads delegate to.
|
|
/// </summary>
|
|
/// <param name="messages">The collection of messages to send to the agent for processing.</param>
|
|
/// <param name="session">
|
|
/// The conversation session to use for this invocation. If <see langword="null"/>, a new session will be created.
|
|
/// The session will be updated with the input messages and any response messages generated during invocation.
|
|
/// </param>
|
|
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// This method delegates to <see cref="RunCoreAsync"/> to perform the actual agent invocation. It handles collections of messages,
|
|
/// allowing for complex conversational scenarios including multi-turn interactions, function calls, and
|
|
/// context-rich conversations.
|
|
/// </para>
|
|
/// <para>
|
|
/// The messages are processed in the order provided and become part of the conversation history.
|
|
/// The agent's response will also be added to <paramref name="session"/> if one is provided.
|
|
/// </para>
|
|
/// </remarks>
|
|
public Task<AgentResponse> RunAsync(
|
|
IEnumerable<ChatMessage> messages,
|
|
AgentSession? session = null,
|
|
AgentRunOptions? options = null,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
CurrentRunContext = new(this, session, messages as IReadOnlyCollection<ChatMessage> ?? messages.ToList(), options);
|
|
return this.RunCoreAsync(messages, session, options, cancellationToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Core implementation of the agent invocation logic with a collection of chat messages.
|
|
/// </summary>
|
|
/// <param name="messages">The collection of messages to send to the agent for processing.</param>
|
|
/// <param name="session">
|
|
/// The conversation session to use for this invocation. If <see langword="null"/>, a new session will be created.
|
|
/// The session will be updated with the input messages and any response messages generated during invocation.
|
|
/// </param>
|
|
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// This is the primary invocation method that implementations must override. It handles collections of messages,
|
|
/// allowing for complex conversational scenarios including multi-turn interactions, function calls, and
|
|
/// context-rich conversations.
|
|
/// </para>
|
|
/// <para>
|
|
/// The messages are processed in the order provided and become part of the conversation history.
|
|
/// The agent's response will also be added to <paramref name="session"/> if one is provided.
|
|
/// </para>
|
|
/// </remarks>
|
|
protected abstract Task<AgentResponse> RunCoreAsync(
|
|
IEnumerable<ChatMessage> messages,
|
|
AgentSession? session = null,
|
|
AgentRunOptions? options = null,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Runs the agent in streaming mode without providing new input messages, relying on existing context and instructions.
|
|
/// </summary>
|
|
/// <param name="session">
|
|
/// The conversation session to use for this invocation. If <see langword="null"/>, a new session will be created.
|
|
/// The session will be updated with any response messages generated during invocation.
|
|
/// </param>
|
|
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>An asynchronous enumerable of <see cref="AgentResponseUpdate"/> instances representing the streaming response.</returns>
|
|
public IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
|
|
AgentSession? session = null,
|
|
AgentRunOptions? options = null,
|
|
CancellationToken cancellationToken = default) =>
|
|
this.RunStreamingAsync([], session, options, cancellationToken);
|
|
|
|
/// <summary>
|
|
/// Runs the agent in streaming mode with a text message from the user.
|
|
/// </summary>
|
|
/// <param name="message">The user message to send to the agent.</param>
|
|
/// <param name="session">
|
|
/// The conversation session to use for this invocation. If <see langword="null"/>, a new session will be created.
|
|
/// The session will be updated with the input message and any response messages generated during invocation.
|
|
/// </param>
|
|
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>An asynchronous enumerable of <see cref="AgentResponseUpdate"/> instances representing the streaming response.</returns>
|
|
/// <exception cref="ArgumentException"><paramref name="message"/> is <see langword="null"/>, empty, or contains only whitespace.</exception>
|
|
/// <remarks>
|
|
/// The provided text will be wrapped in a <see cref="ChatMessage"/> with the <see cref="ChatRole.User"/> role.
|
|
/// Streaming invocation provides real-time updates as the agent generates its response.
|
|
/// </remarks>
|
|
public IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
|
|
string message,
|
|
AgentSession? session = null,
|
|
AgentRunOptions? options = null,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
_ = Throw.IfNullOrWhitespace(message);
|
|
|
|
return this.RunStreamingAsync(new ChatMessage(ChatRole.User, message), session, options, cancellationToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Runs the agent in streaming mode with a single chat message.
|
|
/// </summary>
|
|
/// <param name="message">The chat message to send to the agent.</param>
|
|
/// <param name="session">
|
|
/// The conversation session to use for this invocation. If <see langword="null"/>, a new session will be created.
|
|
/// The session will be updated with the input message and any response messages generated during invocation.
|
|
/// </param>
|
|
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>An asynchronous enumerable of <see cref="AgentResponseUpdate"/> instances representing the streaming response.</returns>
|
|
/// <exception cref="ArgumentNullException"><paramref name="message"/> is <see langword="null"/>.</exception>
|
|
public IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
|
|
ChatMessage message,
|
|
AgentSession? session = null,
|
|
AgentRunOptions? options = null,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
_ = Throw.IfNull(message);
|
|
|
|
return this.RunStreamingAsync([message], session, options, cancellationToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Runs the agent in streaming mode with a collection of chat messages, providing the core streaming invocation logic.
|
|
/// </summary>
|
|
/// <param name="messages">The collection of messages to send to the agent for processing.</param>
|
|
/// <param name="session">
|
|
/// The conversation session to use for this invocation. If <see langword="null"/>, a new session will be created.
|
|
/// The session will be updated with the input messages and any response updates generated during invocation.
|
|
/// </param>
|
|
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>An asynchronous enumerable of <see cref="AgentResponseUpdate"/> instances representing the streaming response.</returns>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// This method delegates to <see cref="RunCoreStreamingAsync"/> to perform the actual streaming invocation. It provides real-time
|
|
/// updates as the agent processes the input and generates its response, enabling more responsive user experiences.
|
|
/// </para>
|
|
/// <para>
|
|
/// Each <see cref="AgentResponseUpdate"/> represents a portion of the complete response, allowing consumers
|
|
/// to display partial results, implement progressive loading, or provide immediate feedback to users.
|
|
/// </para>
|
|
/// </remarks>
|
|
public async IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
|
|
IEnumerable<ChatMessage> messages,
|
|
AgentSession? session = null,
|
|
AgentRunOptions? options = null,
|
|
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
|
{
|
|
AgentRunContext context = new(this, session, messages as IReadOnlyCollection<ChatMessage> ?? messages.ToList(), options);
|
|
CurrentRunContext = context;
|
|
await foreach (var update in this.RunCoreStreamingAsync(messages, session, options, cancellationToken).ConfigureAwait(false))
|
|
{
|
|
yield return update;
|
|
|
|
// Restore context again when resuming after the caller code executes.
|
|
CurrentRunContext = context;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Core implementation of the agent streaming invocation logic with a collection of chat messages.
|
|
/// </summary>
|
|
/// <param name="messages">The collection of messages to send to the agent for processing.</param>
|
|
/// <param name="session">
|
|
/// The conversation session to use for this invocation. If <see langword="null"/>, a new session will be created.
|
|
/// The session will be updated with the input messages and any response updates generated during invocation.
|
|
/// </param>
|
|
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>An asynchronous enumerable of <see cref="AgentResponseUpdate"/> instances representing the streaming response.</returns>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// This is the primary streaming invocation method that implementations must override. It provides real-time
|
|
/// updates as the agent processes the input and generates its response, enabling more responsive user experiences.
|
|
/// </para>
|
|
/// <para>
|
|
/// Each <see cref="AgentResponseUpdate"/> represents a portion of the complete response, allowing consumers
|
|
/// to display partial results, implement progressive loading, or provide immediate feedback to users.
|
|
/// </para>
|
|
/// </remarks>
|
|
protected abstract IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
|
|
IEnumerable<ChatMessage> messages,
|
|
AgentSession? session = null,
|
|
AgentRunOptions? options = null,
|
|
CancellationToken cancellationToken = default);
|
|
}
|