mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET: Use copilot to improve XML docs for M.Agents.AI{.Abstractions} (#1042)
* Use copilot to improve XML docs for M.Agents.AI{.Abstractions}
Asked copilot to help improve some of the docs, then I reviewed them.
I also cleaned up a few things along the way, like a couple of extension method types that should be combined.
* Update dotnet/src/Microsoft.Agents.AI.Abstractions/InMemoryChatMessageStore.cs
---------
Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
5c0bea12e3
commit
f21b9d14f8
@@ -11,32 +11,66 @@ using Microsoft.Shared.Diagnostics;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Base abstraction for all agents. An agent instance may participate in one or more conversations.
|
||||
/// A conversation may include one or more agents.
|
||||
/// 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>
|
||||
public abstract class AIAgent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the identifier of the agent.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The identifier of the agent. The default is a random GUID value, but for service agents, it will match the id of the agent in the service.
|
||||
/// </value>
|
||||
public virtual string Id { get; } = Guid.NewGuid().ToString("N");
|
||||
/// <summary>Default ID of this agent instance.</summary>
|
||||
private readonly string _id = Guid.NewGuid().ToString("N");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the agent (optional).
|
||||
/// 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 virtual string Id => _id;
|
||||
|
||||
/// <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 display name for the agent, which is either the <see cref="Name"/> or <see cref="Id"/> if the name is not set.
|
||||
/// Gets a display-friendly name for the agent.
|
||||
/// </summary>
|
||||
public virtual string DisplayName => this.Name ?? this.Id;
|
||||
/// <value>
|
||||
/// The agent's <see cref="Name"/> if available, otherwise the <see cref="Id"/>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This property provides a guaranteed non-null string suitable for display in user interfaces,
|
||||
/// logs, or other contexts where a readable identifier is needed.
|
||||
/// </remarks>
|
||||
public virtual string DisplayName => this.Name ?? this.Id ?? this._id; // final fallback to _id in case Id override returns null
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of the agent (optional).
|
||||
/// 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>Asks the <see cref="AIAgent"/> for an object of the specified type <paramref name="serviceType"/>.</summary>
|
||||
@@ -70,38 +104,52 @@ public abstract class AIAgent
|
||||
=> this.GetService(typeof(TService), serviceKey) is TService service ? service : default;
|
||||
|
||||
/// <summary>
|
||||
/// Get a new <see cref="AgentThread"/> instance that is compatible with the agent.
|
||||
/// Creates a new conversation thread that is compatible with this agent.
|
||||
/// </summary>
|
||||
/// <returns>A new <see cref="AgentThread"/> instance.</returns>
|
||||
/// <returns>A new <see cref="AgentThread"/> instance ready for use with this agent.</returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// If an agent supports multiple thread types, this method should return the default thread
|
||||
/// type for the agent or whatever the agent was configured to use.
|
||||
/// This method creates a fresh conversation thread that can be used to maintain state
|
||||
/// and context for interactions with this agent. Each thread represents an independent
|
||||
/// conversation session.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If the thread needs to be created via a service call it would be created on first use.
|
||||
/// If the agent supports multiple thread types, this method returns the default or
|
||||
/// configured thread type. For service-backed agents, the actual thread creation
|
||||
/// may be deferred until first use to optimize performance.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public abstract AgentThread GetNewThread();
|
||||
|
||||
/// <summary>
|
||||
/// Deserialize the thread from JSON.
|
||||
/// Deserializes an agent thread from its JSON serialized representation.
|
||||
/// </summary>
|
||||
/// <param name="serializedThread">The <see cref="JsonElement"/> representing the thread state.</param>
|
||||
/// <param name="jsonSerializerOptions">Optional <see cref="JsonSerializerOptions"/> to use for deserializing the thread state.</param>
|
||||
/// <returns>The deserialized <see cref="AgentThread"/> instance.</returns>
|
||||
/// <param name="serializedThread">A <see cref="JsonElement"/> containing the serialized thread state.</param>
|
||||
/// <param name="jsonSerializerOptions">Optional settings to customize the deserialization process.</param>
|
||||
/// <returns>A restored <see cref="AgentThread"/> instance with the state from <paramref name="serializedThread"/>.</returns>
|
||||
/// <exception cref="ArgumentException">The <paramref name="serializedThread"/> 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 threads from previously saved state,
|
||||
/// allowing conversations to resume across application restarts or be migrated between
|
||||
/// different agent instances.
|
||||
/// </remarks>
|
||||
public abstract AgentThread DeserializeThread(JsonElement serializedThread, JsonSerializerOptions? jsonSerializerOptions = null);
|
||||
|
||||
/// <summary>
|
||||
/// Run the agent with no message assuming that all required instructions are already provided to the agent or on the thread.
|
||||
/// </summary>
|
||||
/// <param name="thread">
|
||||
/// The conversation thread to continue with this invocation. If not provided, creates a new thread.
|
||||
/// The thread will be mutated with the provided messages and agent response.
|
||||
/// The conversation thread to use for this invocation. If <see langword="null"/>, a new thread will be created.
|
||||
/// The thread will be updated with any response messages generated during invocation.
|
||||
/// </param>
|
||||
/// <param name="options">Optional parameters for agent 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 <see cref="AgentRunResponse"/> containing the list of <see cref="ChatMessage"/> items.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
/// <remarks>
|
||||
/// This overload is useful when the agent has sufficient context from previous messages in the thread
|
||||
/// or from its initial configuration to generate a meaningful response without additional input.
|
||||
/// </remarks>
|
||||
public Task<AgentRunResponse> RunAsync(
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -109,18 +157,20 @@ public abstract class AIAgent
|
||||
this.RunAsync([], thread, options, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Run the agent with the provided message and arguments.
|
||||
/// Runs the agent with a text message from the user.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to pass to the agent.</param>
|
||||
/// <param name="message">The user message to send to the agent.</param>
|
||||
/// <param name="thread">
|
||||
/// The conversation thread to continue with this invocation. If not provided, creates a new thread.
|
||||
/// The thread will be mutated with the provided messages and agent response.
|
||||
/// The conversation thread to use for this invocation. If <see langword="null"/>, a new thread will be created.
|
||||
/// The thread will be updated with the input message and any response messages generated during invocation.
|
||||
/// </param>
|
||||
/// <param name="options">Optional parameters for agent 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 <see cref="AgentRunResponse"/> containing the list of <see cref="ChatMessage"/> items.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> 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 message string will be treated as a user message.
|
||||
/// 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<AgentRunResponse> RunAsync(
|
||||
string message,
|
||||
@@ -134,16 +184,17 @@ public abstract class AIAgent
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run the agent with the provided message and arguments.
|
||||
/// Runs the agent with a single chat message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to pass to the agent.</param>
|
||||
/// <param name="message">The chat message to send to the agent.</param>
|
||||
/// <param name="thread">
|
||||
/// The conversation thread to continue with this invocation. If not provided, creates a new thread.
|
||||
/// The thread will be mutated with the provided messages and agent response.
|
||||
/// The conversation thread to use for this invocation. If <see langword="null"/>, a new thread will be created.
|
||||
/// The thread will be updated with the input message and any response messages generated during invocation.
|
||||
/// </param>
|
||||
/// <param name="options">Optional parameters for agent 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 <see cref="AgentRunResponse"/> containing the list of <see cref="ChatMessage"/> items.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="message"/> is <see langword="null"/>.</exception>
|
||||
public Task<AgentRunResponse> RunAsync(
|
||||
ChatMessage message,
|
||||
AgentThread? thread = null,
|
||||
@@ -156,16 +207,27 @@ public abstract class AIAgent
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run the agent with the provided message and arguments.
|
||||
/// 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 messages to pass to the agent.</param>
|
||||
/// <param name="messages">The collection of messages to send to the agent for processing.</param>
|
||||
/// <param name="thread">
|
||||
/// The conversation thread to continue with this invocation. If not provided, creates a new thread.
|
||||
/// The thread will be mutated with the provided messages and agent response.
|
||||
/// The conversation thread to use for this invocation. If <see langword="null"/>, a new thread will be created.
|
||||
/// The thread will be updated with the input messages and any response messages generated during invocation.
|
||||
/// </param>
|
||||
/// <param name="options">Optional parameters for agent 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 <see cref="AgentRunResponse"/> containing the list of <see cref="ChatMessage"/> items.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> 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="thread"/> if one is provided.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public abstract Task<AgentRunResponse> RunAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
@@ -173,15 +235,15 @@ public abstract class AIAgent
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Run the agent with no message assuming that all required instructions are already provided to the agent or on the thread.
|
||||
/// Runs the agent in streaming mode without providing new input messages, relying on existing context and instructions.
|
||||
/// </summary>
|
||||
/// <param name="thread">
|
||||
/// The conversation thread to continue with this invocation. If not provided, creates a new thread.
|
||||
/// The thread will be mutated with the provided messages and agent response.
|
||||
/// The conversation thread to use for this invocation. If <see langword="null"/>, a new thread will be created.
|
||||
/// The thread will be updated with any response messages generated during invocation.
|
||||
/// </param>
|
||||
/// <param name="options">Optional parameters for agent 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 async list of response items that each contain a <see cref="AgentRunResponseUpdate"/>.</returns>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentRunResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
public IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -189,18 +251,20 @@ public abstract class AIAgent
|
||||
this.RunStreamingAsync([], thread, options, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Run the agent with the provided message and arguments.
|
||||
/// Runs the agent in streaming mode with a text message from the user.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to pass to the agent.</param>
|
||||
/// <param name="message">The user message to send to the agent.</param>
|
||||
/// <param name="thread">
|
||||
/// The conversation thread to continue with this invocation. If not provided, creates a new thread.
|
||||
/// The thread will be mutated with the provided messages and agent response.
|
||||
/// The conversation thread to use for this invocation. If <see langword="null"/>, a new thread will be created.
|
||||
/// The thread will be updated with the input message and any response messages generated during invocation.
|
||||
/// </param>
|
||||
/// <param name="options">Optional parameters for agent 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 async list of response items that each contain a <see cref="AgentRunResponseUpdate"/>.</returns>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentRunResponseUpdate"/> 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 message string will be treated as a user message.
|
||||
/// 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<AgentRunResponseUpdate> RunStreamingAsync(
|
||||
string message,
|
||||
@@ -214,16 +278,17 @@ public abstract class AIAgent
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run the agent with the provided message and arguments.
|
||||
/// Runs the agent in streaming mode with a single chat message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to pass to the agent.</param>
|
||||
/// <param name="message">The chat message to send to the agent.</param>
|
||||
/// <param name="thread">
|
||||
/// The conversation thread to continue with this invocation. If not provided, creates a new thread.
|
||||
/// The thread will be mutated with the provided messages and agent response.
|
||||
/// The conversation thread to use for this invocation. If <see langword="null"/>, a new thread will be created.
|
||||
/// The thread will be updated with the input message and any response messages generated during invocation.
|
||||
/// </param>
|
||||
/// <param name="options">Optional parameters for agent 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 async list of response items that each contain a <see cref="AgentRunResponseUpdate"/>.</returns>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentRunResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="message"/> is <see langword="null"/>.</exception>
|
||||
public IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
|
||||
ChatMessage message,
|
||||
AgentThread? thread = null,
|
||||
@@ -236,16 +301,26 @@ public abstract class AIAgent
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run the agent with the provided message and arguments.
|
||||
/// Runs the agent in streaming mode with a collection of chat messages, providing the core streaming invocation logic.
|
||||
/// </summary>
|
||||
/// <param name="messages">The messages to pass to the agent.</param>
|
||||
/// <param name="messages">The collection of messages to send to the agent for processing.</param>
|
||||
/// <param name="thread">
|
||||
/// The conversation thread to continue with this invocation. If not provided, creates a new thread.
|
||||
/// The thread will be mutated with the provided messages and agent response.
|
||||
/// The conversation thread to use for this invocation. If <see langword="null"/>, a new thread will be created.
|
||||
/// The thread will be updated with the input messages and any response updates generated during invocation.
|
||||
/// </param>
|
||||
/// <param name="options">Optional parameters for agent 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 async list of response items that each contain a <see cref="AgentRunResponseUpdate"/>.</returns>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentRunResponseUpdate"/> 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="AgentRunResponseUpdate"/> 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 abstract IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
@@ -253,29 +328,21 @@ public abstract class AIAgent
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Notfiy the given thread that new messages are available.
|
||||
/// Notifies the specified thread about new messages that have been added to the conversation.
|
||||
/// </summary>
|
||||
/// <param name="thread">The conversation thread to notify about the new messages.</param>
|
||||
/// <param name="messages">The collection of new messages to report to the thread.</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 notification operation.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="thread"/> or <paramref name="messages"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Note that while all agents should notify their threads of new messages,
|
||||
/// not all threads will necessarily take action. For some treads, this may be
|
||||
/// the only way that they would know that a new message is available to be added
|
||||
/// to their history.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// For other thread types, where history is managed by the service, the thread may
|
||||
/// not need to take any action.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Where threads manage other memory components that need access to new messages,
|
||||
/// notifying the thread will be important, even if the thread itself does not
|
||||
/// require the message.
|
||||
/// This method ensures that conversation threads are kept informed about message additions, which
|
||||
/// is important for threads that manage their own state, memory components, or derived context.
|
||||
/// While all agent implementations should notify their threads, the specific actions taken by
|
||||
/// each thread type may vary.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="thread">The thread to notify of the new messages.</param>
|
||||
/// <param name="messages">The messages to pass to the thread.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>An async task that completes once the notification is complete.</returns>
|
||||
protected static async Task NotifyThreadOfNewMessagesAsync(AgentThread thread, IEnumerable<ChatMessage> messages, CancellationToken cancellationToken)
|
||||
{
|
||||
_ = Throw.IfNull(thread);
|
||||
|
||||
@@ -2,10 +2,18 @@
|
||||
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>Provides metadata about an <see cref="AIAgent"/>.</summary>
|
||||
/// <summary>
|
||||
/// Provides metadata information about an <see cref="AIAgent"/> instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class contains descriptive information about an agent that can be used for identification,
|
||||
/// telemetry, and logging purposes.
|
||||
/// </remarks>
|
||||
public class AIAgentMetadata
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="AIAgentMetadata"/> class.</summary>
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AIAgentMetadata"/> class.
|
||||
/// </summary>
|
||||
/// <param name="providerName">
|
||||
/// The name of the agent provider, if applicable. Where possible, this should map to the
|
||||
/// appropriate name defined in the OpenTelemetry Semantic Conventions for Generative AI systems.
|
||||
@@ -15,7 +23,12 @@ public class AIAgentMetadata
|
||||
ProviderName = providerName;
|
||||
}
|
||||
|
||||
/// <summary>Gets the name of the chat provider.</summary>
|
||||
/// <summary>
|
||||
/// Gets the name of the agent provider.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The provider name that identifies the underlying service or implementation powering the agent.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// Where possible, this maps to the appropriate name defined in the
|
||||
/// OpenTelemetry Semantic Conventions for Generative AI systems.
|
||||
|
||||
@@ -6,39 +6,101 @@ using Microsoft.Extensions.AI;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// A class containing any context that should be provided to the AI model
|
||||
/// as supplied by an <see cref="AIContextProvider"/>.
|
||||
/// Represents additional context information that can be dynamically provided to AI models during agent invocations.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Each <see cref="AIContextProvider"/> has the ability to provide its own context for each invocation.
|
||||
/// The <see cref="AIContext"/> class contains the additional context supplied by the <see cref="AIContextProvider"/>.
|
||||
/// This context will be combined with context supplied by other providers before being passed to the AI model.
|
||||
/// <para>
|
||||
/// <see cref="AIContext"/> serves as a container for contextual information that <see cref="AIContextProvider"/> instances
|
||||
/// can supply to enhance AI model interactions. This context is combined across multiple providers and merged with
|
||||
/// the agent's base configuration before being passed to the underlying AI model.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The context system enables dynamic, runtime-specific enhancements to agent capabilities including:
|
||||
/// <list type="bullet">
|
||||
/// <item><description>Adding relevant background information from knowledge bases</description></item>
|
||||
/// <item><description>Injecting task-specific instructions or guidelines</description></item>
|
||||
/// <item><description>Providing specialized tools or functions for the current interaction</description></item>
|
||||
/// <item><description>Including contextual messages that inform the AI about the current situation</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Context information is transient by default and applies only to the current invocation, though messages
|
||||
/// added through the <see cref="Messages"/> property will be permanently incorporated into the conversation history.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed class AIContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets any instructions to pass to the AI model in addition to any other prompts
|
||||
/// that it may already have (in the case of an agent), or chat history that may
|
||||
/// already exist.
|
||||
/// Gets or sets additional instructions to provide to the AI model for the current invocation.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Instructions text that will be combined with any existing agent instructions or system prompts,
|
||||
/// or <see langword="null"/> if no additional instructions should be provided.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// These instructions will be transient and only apply to the current invocation.
|
||||
/// <para>
|
||||
/// These instructions are transient and apply only to the current AI model invocation. They are combined
|
||||
/// with any existing agent instructions, system prompts, and conversation history to provide comprehensive
|
||||
/// context to the AI model.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Instructions can be used to:
|
||||
/// <list type="bullet">
|
||||
/// <item><description>Provide context-specific behavioral guidance</description></item>
|
||||
/// <item><description>Add domain-specific knowledge or constraints</description></item>
|
||||
/// <item><description>Modify the agent's persona or response style for the current interaction</description></item>
|
||||
/// <item><description>Include situational awareness information</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public string? Instructions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a list of messages to add to the chat history.
|
||||
/// Gets or sets a collection of messages to add to the conversation history.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A list of <see cref="ChatMessage"/> instances to be permanently added to the conversation history,
|
||||
/// or <see langword="null"/> if no messages should be added.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// These messages will permanently be added to the chat history.
|
||||
/// <para>
|
||||
/// Unlike <see cref="Instructions"/> and <see cref="Tools"/>, messages added through this property become
|
||||
/// permanent additions to the conversation history. They will persist beyond the current invocation and
|
||||
/// will be available in future interactions within the same conversation thread.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This property is useful for:
|
||||
/// <list type="bullet">
|
||||
/// <item><description>Injecting relevant historical context or background information</description></item>
|
||||
/// <item><description>Adding system messages that provide ongoing context</description></item>
|
||||
/// <item><description>Including retrieved information that should be part of the conversation record</description></item>
|
||||
/// <item><description>Inserting contextual exchanges that inform the current conversation</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public IList<ChatMessage>? Messages { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a list of functions/tools to make available to the AI model for the current invocation.
|
||||
/// Gets or sets a collection of tools or functions to make available to the AI model for the current invocation.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A list of <see cref="AITool"/> instances that will be available to the AI model during the current invocation,
|
||||
/// or <see langword="null"/> if no additional tools should be provided.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// These functions/tools will be transient and only apply to the current invocation.
|
||||
/// <para>
|
||||
/// These tools are transient and apply only to the current AI model invocation. They are combined with any
|
||||
/// tools already configured for the agent to provide an expanded set of capabilities for the specific interaction.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Context-specific tools enable:
|
||||
/// <list type="bullet">
|
||||
/// <item><description>Providing specialized functions based on user intent or conversation context</description></item>
|
||||
/// <item><description>Adding domain-specific capabilities for particular types of queries</description></item>
|
||||
/// <item><description>Enabling access to external services or data sources relevant to the current task</description></item>
|
||||
/// <item><description>Offering interactive capabilities tailored to the current conversation state</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public IList<AITool>? Tools { get; set; }
|
||||
}
|
||||
|
||||
@@ -11,37 +11,68 @@ using Microsoft.Shared.Diagnostics;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for all AI context providers.
|
||||
/// Provides an abstract base class for components that enhance AI context management during agent invocations.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// An AI context provider is a component that can be used to enhance the AI's context management.
|
||||
/// It can listen to changes in the conversation, provide additional context to
|
||||
/// the Model/Agent/etc. just before invocation and supply additional function tools.
|
||||
/// <para>
|
||||
/// An AI context provider is a component that participates in the agent invocation lifecycle by:
|
||||
/// <list type="bullet">
|
||||
/// <item><description>Listening to changes in conversations</description></item>
|
||||
/// <item><description>Providing additional context to AI models or agents before invocation</description></item>
|
||||
/// <item><description>Supplying additional function tools for enhanced capabilities</description></item>
|
||||
/// <item><description>Processing invocation results for state management or learning</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Context providers operate through a two-phase lifecycle: they are called before invocation via
|
||||
/// <see cref="InvokingAsync"/> to provide context, and optionally called after invocation via
|
||||
/// <see cref="InvokedAsync"/> to process results.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public abstract class AIContextProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Called just before the Model/Agent/etc. is invoked.
|
||||
/// Implementers can load any additional context required at this time,
|
||||
/// and they should return any context that should be passed to the Model/Agent/etc.
|
||||
/// Called immediately before an AI model or agent is invoked to provide additional context.
|
||||
/// </summary>
|
||||
/// <param name="context">Contains the event context.</param>
|
||||
/// <param name="context">Contains the request context including the messages that will be sent to the AI model or agent.</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 completes when the context has been rendered and returned.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains the <see cref="AIContext"/> with additional context to be provided to the AI model or agent.</returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Implementers can load any additional context required at this time, such as:
|
||||
/// <list type="bullet">
|
||||
/// <item><description>Retrieving relevant information from knowledge bases</description></item>
|
||||
/// <item><description>Adding system instructions or prompts</description></item>
|
||||
/// <item><description>Providing function tools for the current invocation</description></item>
|
||||
/// <item><description>Injecting contextual messages from conversation history</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The returned context will be combined with context from other providers before being passed to the AI model or agent.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public abstract ValueTask<AIContext> InvokingAsync(InvokingContext context, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Called just after the Model/Agent/etc. is invoked.
|
||||
/// Implementers can use the request and response messages in the provided <paramref name="context"/> to update
|
||||
/// any internal state or perform any necessary actions based on the outcome of the invocation.
|
||||
/// E.g. extracting memories from the user messages to remember a user preference.
|
||||
/// Called immediately after an AI model or agent has been invoked to process the results.
|
||||
/// </summary>
|
||||
/// <param name="context">Contains the event context.</param>
|
||||
/// <param name="context">Contains the invocation context including request messages, response messages, and any exception that occurred.</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 completes when the context has been rendered and returned.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Implementers can use the request and response messages in the provided <paramref name="context"/> to:
|
||||
/// <list type="bullet">
|
||||
/// <item><description>Update internal state based on conversation outcomes</description></item>
|
||||
/// <item><description>Extract and store memories or preferences from user messages</description></item>
|
||||
/// <item><description>Log or audit conversation details</description></item>
|
||||
/// <item><description>Perform cleanup or finalization tasks</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This method is called regardless of whether the invocation succeeded or failed.
|
||||
/// To check if the invocation was successful, you can inspect the <see cref="InvokedContext.InvokeException"/> property.
|
||||
/// To check if the invocation was successful, inspect the <see cref="InvokedContext.InvokeException"/> property.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public virtual ValueTask InvokedAsync(InvokedContext context, CancellationToken cancellationToken = default)
|
||||
=> default;
|
||||
@@ -49,8 +80,12 @@ public abstract class AIContextProvider
|
||||
/// <summary>
|
||||
/// Serializes the current object's state to a <see cref="JsonElement"/> using the specified serialization options.
|
||||
/// </summary>
|
||||
/// <param name="jsonSerializerOptions">The JSON serialization options to use.</param>
|
||||
/// <returns>A <see cref="JsonElement"/> representation of the object's state.</returns>
|
||||
/// <param name="jsonSerializerOptions">The JSON serialization options to use for the serialization process.</param>
|
||||
/// <returns>A <see cref="JsonElement"/> representation of the object's state, or a default <see cref="JsonElement"/> if the provider has no serializable state.</returns>
|
||||
/// <remarks>
|
||||
/// The default implementation returns a default <see cref="JsonElement"/>. Override this method if the provider
|
||||
/// maintains state that should be preserved across sessions or distributed scenarios.
|
||||
/// </remarks>
|
||||
public virtual JsonElement Serialize(JsonSerializerOptions? jsonSerializerOptions = null)
|
||||
=> default;
|
||||
|
||||
@@ -61,7 +96,8 @@ public abstract class AIContextProvider
|
||||
/// <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="AIContextProvider"/>,
|
||||
/// including itself or any services it might be wrapping.
|
||||
/// including itself or any services it might be wrapping. This enables advanced scenarios where consumers need access to
|
||||
/// specific provider implementations or their internal services.
|
||||
/// </remarks>
|
||||
public virtual object? GetService(Type serviceType, object? serviceKey = null)
|
||||
{
|
||||
@@ -78,60 +114,85 @@ public abstract class AIContextProvider
|
||||
/// <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="AIContextProvider"/>,
|
||||
/// including itself or any services it might be wrapping.
|
||||
/// including itself or any services it might be wrapping. This is a convenience overload of <see cref="GetService(Type, object?)"/>.
|
||||
/// </remarks>
|
||||
public TService? GetService<TService>(object? serviceKey = null)
|
||||
=> this.GetService(typeof(TService), serviceKey) is TService service ? service : default;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the event context provided to <see cref="InvokingAsync(InvokingContext, CancellationToken)"/>.
|
||||
/// Contains the context information provided to <see cref="InvokingAsync(InvokingContext, CancellationToken)"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class provides context about the upcoming AI model or agent invocation, including the messages
|
||||
/// that will be sent. Context providers can use this information to determine what additional context
|
||||
/// should be provided for the invocation.
|
||||
/// </remarks>
|
||||
public class InvokingContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InvokingContext"/> class.
|
||||
/// Initializes a new instance of the <see cref="InvokingContext"/> class with the specified request messages.
|
||||
/// </summary>
|
||||
/// <param name="requestMessages">The messages to be sent to the Model/Agent/etc. for this invocation.</param>
|
||||
/// <exception cref="ArgumentNullException">Thrown if <paramref name="requestMessages"/> is <see langword="null"/>.</exception>
|
||||
/// <param name="requestMessages">The messages to be sent to the AI model or agent for this invocation.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="requestMessages"/> is <see langword="null"/>.</exception>
|
||||
public InvokingContext(IEnumerable<ChatMessage> requestMessages)
|
||||
{
|
||||
RequestMessages = requestMessages ?? throw new ArgumentNullException(nameof(requestMessages));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the messages that will be sent to the Model/Agent/etc. for this invocation.
|
||||
/// Gets the messages that will be sent to the AI model or agent for this invocation.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A collection of <see cref="ChatMessage"/> instances representing the conversation history
|
||||
/// and new messages that will be processed by the AI model or agent.
|
||||
/// </value>
|
||||
public IEnumerable<ChatMessage> RequestMessages { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains the event conext provided to <see cref="InvokedAsync(InvokedContext, CancellationToken)"/>.
|
||||
/// Contains the context information provided to <see cref="InvokedAsync(InvokedContext, CancellationToken)"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class provides context about a completed AI model or agent invocation, including both the
|
||||
/// request messages that were sent and the response messages that were generated. It also indicates
|
||||
/// whether the invocation succeeded or failed.
|
||||
/// </remarks>
|
||||
public class InvokedContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InvokedContext"/> class with the specified request messages.
|
||||
/// </summary>
|
||||
/// <param name="requestMessages">The messages that were sent to the Model/Agent/etc. for this invocation.</param>
|
||||
/// <exception cref="ArgumentNullException">Thrown if <paramref name="requestMessages"/> is <see langword="null"/>.</exception>
|
||||
/// <param name="requestMessages">The messages that were sent to the AI model or agent for this invocation.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="requestMessages"/> is <see langword="null"/>.</exception>
|
||||
public InvokedContext(IEnumerable<ChatMessage> requestMessages)
|
||||
{
|
||||
RequestMessages = requestMessages ?? throw new ArgumentNullException(nameof(requestMessages));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the messages that were sent to the Model/Agent/etc. for this invocation.
|
||||
/// Gets the messages that were sent to the AI model or agent for this invocation.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A collection of <see cref="ChatMessage"/> instances representing the conversation history
|
||||
/// and new messages that were processed by the AI model or agent.
|
||||
/// </value>
|
||||
public IEnumerable<ChatMessage> RequestMessages { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of response messages generated by Model/Agent/etc. if the invocation succeeded.
|
||||
/// Gets the collection of response messages generated by the AI model or agent if the invocation succeeded.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A collection of <see cref="ChatMessage"/> instances representing the response from the AI model or agent,
|
||||
/// or <see langword="null"/> if the invocation failed or did not produce response messages.
|
||||
/// </value>
|
||||
public IEnumerable<ChatMessage>? ResponseMessages { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Exception"/> that was thrown during the invocation, if the invocation failed.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The exception that caused the invocation to fail, or <see langword="null"/> if the invocation succeeded.
|
||||
/// </value>
|
||||
public Exception? InvokeException { get; init; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,13 @@ using Microsoft.Extensions.AI;
|
||||
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>Provides a collection of utility methods for working with JSON data in the context of agents.</summary>
|
||||
/// <summary>
|
||||
/// Provides utility methods and configurations for JSON serialization operations within the Microsoft Agent Framework.
|
||||
/// </summary>
|
||||
public static partial class AgentAbstractionsJsonUtilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="JsonSerializerOptions"/> singleton used as the default in JSON serialization operations.
|
||||
/// Gets the default <see cref="JsonSerializerOptions"/> instance used for JSON serialization operations of agent abstraction types.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
@@ -30,7 +32,7 @@ public static partial class AgentAbstractionsJsonUtilities
|
||||
public static JsonSerializerOptions DefaultOptions { get; } = CreateDefaultOptions();
|
||||
|
||||
/// <summary>
|
||||
/// Creates default options to use for agents-related serialization.
|
||||
/// Creates and configures the default JSON serialization options for agent abstraction types.
|
||||
/// </summary>
|
||||
/// <returns>The configured options.</returns>
|
||||
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:RequiresDynamicCode", Justification = "Converter is guarded by IsReflectionEnabledByDefault check.")]
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Optional parameters when running an agent.
|
||||
/// Provides optional parameters and configuration settings for controlling agent run behavior.
|
||||
/// </summary>
|
||||
public class AgentRunOptions
|
||||
{
|
||||
@@ -17,9 +18,10 @@ public class AgentRunOptions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AgentRunOptions"/> class by cloning the provided options.
|
||||
/// Initializes a new instance of the <see cref="AgentRunOptions"/> class by copying values from the specified options.
|
||||
/// </summary>
|
||||
/// <param name="options">The options to clone.</param>
|
||||
/// <param name="options">The options instance from which to copy values.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="options"/> is <see langword="null"/>.</exception>
|
||||
public AgentRunOptions(AgentRunOptions options)
|
||||
{
|
||||
_ = Throw.IfNull(options);
|
||||
|
||||
@@ -22,7 +22,9 @@ using Microsoft.Extensions.AI;
|
||||
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>Represents the response to an Agent run request.</summary>
|
||||
/// <summary>
|
||||
/// Represents the response to an <see cref="AIAgent"/> run request, containing messages and metadata about the interaction.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="AgentRunResponse"/> provides one or more response messages and metadata about the response.
|
||||
/// A typical response will contain a single message, however a response may contain multiple messages
|
||||
@@ -41,7 +43,7 @@ public class AgentRunResponse
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentRunResponse"/> class.</summary>
|
||||
/// <param name="message">The response message.</param>
|
||||
/// <param name="message">The response message to include in this response.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="message"/> is <see langword="null"/>.</exception>
|
||||
public AgentRunResponse(ChatMessage message)
|
||||
{
|
||||
@@ -50,9 +52,16 @@ public class AgentRunResponse
|
||||
this.Messages.Add(message);
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentRunResponse"/> class.</summary>
|
||||
/// <param name="response">The <see cref="ChatResponse"/> from which to seed this <see cref="AgentRunResponse"/>.</param>
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AgentRunResponse"/> class from an existing <see cref="ChatResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="response">The <see cref="ChatResponse"/> from which to populate this <see cref="AgentRunResponse"/>.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="response"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// This constructor creates an agent response that wraps an existing <see cref="ChatResponse"/>, preserving all
|
||||
/// metadata and storing the original response in <see cref="RawRepresentation"/> for access to
|
||||
/// the underlying implementation details.
|
||||
/// </remarks>
|
||||
public AgentRunResponse(ChatResponse response)
|
||||
{
|
||||
_ = Throw.IfNull(response);
|
||||
@@ -65,14 +74,33 @@ public class AgentRunResponse
|
||||
this.Usage = response.Usage;
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentRunResponse"/> class.</summary>
|
||||
/// <param name="messages">The response messages.</param>
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AgentRunResponse"/> class with the specified collection of messages.
|
||||
/// </summary>
|
||||
/// <param name="messages">The collection of response messages, or <see langword="null"/> to create an empty response.</param>
|
||||
public AgentRunResponse(IList<ChatMessage>? messages)
|
||||
{
|
||||
this._messages = messages;
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the agent response messages.</summary>
|
||||
/// <summary>
|
||||
/// Gets or sets the collection of messages to be represented by this response.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A collection of <see cref="ChatMessage"/> instances representing the agent's response.
|
||||
/// If the backing collection is <see langword="null"/>, accessing this property will create an empty list.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This property provides access to all messages generated during the agent's execution. While most
|
||||
/// responses contain a single assistant message, complex agent behaviors may produce multiple messages
|
||||
/// showing intermediate steps, function calls, or different types of content.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The collection is mutable and can be modified after creation. Setting this property to <see langword="null"/>
|
||||
/// will cause subsequent access to return an empty list.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[AllowNull]
|
||||
public IList<ChatMessage> Messages
|
||||
{
|
||||
@@ -80,35 +108,75 @@ public class AgentRunResponse
|
||||
set => this._messages = value;
|
||||
}
|
||||
|
||||
/// <summary>Gets the text of the response.</summary>
|
||||
/// <summary>
|
||||
/// Gets the concatenated text content of all messages in this response.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A string containing the combined text from all <see cref="TextContent"/> instances
|
||||
/// across all messages in <see cref="Messages"/>, or an empty string if no text content is present.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This property concatenates the <see cref="ChatMessage.Text"/> of all <see cref="ChatMessage"/>
|
||||
/// instances in <see cref="Messages"/>.
|
||||
/// This property provides a convenient way to access the textual response without needing to
|
||||
/// iterate through individual messages and content items. Non-text content is ignored.
|
||||
/// </remarks>
|
||||
[JsonIgnore]
|
||||
public string Text => this._messages?.ConcatText() ?? string.Empty;
|
||||
|
||||
/// <summary>Gets the user input requests associated with the response.</summary>
|
||||
/// <summary>
|
||||
/// Gets all user input requests present in the response messages.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// An enumerable collection of <see cref="UserInputRequestContent"/> instances found
|
||||
/// across all messages in the response.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This property concatenates all <see cref="UserInputRequestContent"/> instances in the response.
|
||||
/// User input requests indicate that the agent is asking for additional information
|
||||
/// from the user before it can continue processing. This property aggregates all such
|
||||
/// requests across all messages in the response.
|
||||
/// </remarks>
|
||||
[JsonIgnore]
|
||||
public IEnumerable<UserInputRequestContent> UserInputRequests => this._messages?.SelectMany(x => x.Contents).OfType<UserInputRequestContent>() ?? [];
|
||||
|
||||
/// <summary>Gets or sets the ID of the agent that produced the response.</summary>
|
||||
/// <summary>
|
||||
/// Gets or sets the identifier of the agent that generated this response.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A unique string identifier for the agent, or <see langword="null"/> if not specified.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This identifier helps track which agent generated the response in multi-agent scenarios
|
||||
/// or for debugging and telemetry purposes.
|
||||
/// </remarks>
|
||||
public string? AgentId { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the ID of the agent response.</summary>
|
||||
/// <summary>
|
||||
/// Gets or sets the unique identifier for this specific response.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A unique string identifier for this response instance, or <see langword="null"/> if not assigned.
|
||||
/// </value>
|
||||
public string? ResponseId { get; set; }
|
||||
|
||||
/// <summary>Gets or sets a timestamp for the run response.</summary>
|
||||
/// <summary>
|
||||
/// Gets or sets the timestamp indicating when this response was created.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="DateTimeOffset"/> representing when the response was generated,
|
||||
/// or <see langword="null"/> if not specified.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// The creation timestamp is useful for auditing, logging, and understanding
|
||||
/// the chronology of agentic interactions.
|
||||
/// </remarks>
|
||||
public DateTimeOffset? CreatedAt { get; set; }
|
||||
|
||||
/// <summary>Gets or sets usage details for the run response.</summary>
|
||||
/// <remarks>
|
||||
/// Where the agent run response is produced via many model invocations, this
|
||||
/// usage is an aggregation of the usage for all these model invocations.
|
||||
/// </remarks>
|
||||
/// <summary>
|
||||
/// Gets or sets the resource usage information for generating this response.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="UsageDetails"/> instance containing token counts and other usage metrics,
|
||||
/// or <see langword="null"/> if usage information is not available.
|
||||
/// </value>
|
||||
public UsageDetails? Usage { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the raw representation of the run response from an underlying implementation.</summary>
|
||||
@@ -120,14 +188,43 @@ public class AgentRunResponse
|
||||
[JsonIgnore]
|
||||
public object? RawRepresentation { get; set; }
|
||||
|
||||
/// <summary>Gets or sets any additional properties associated with the run response.</summary>
|
||||
/// <summary>
|
||||
/// Gets or sets additional properties associated with this response.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// An <see cref="AdditionalPropertiesDictionary"/> containing custom properties,
|
||||
/// or <see langword="null"/> if no additional properties are present.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// Additional properties provide a way to include custom metadata or provider-specific
|
||||
/// information that doesn't fit into the standard response schema. This is useful for
|
||||
/// preserving implementation-specific details or extending the response with custom data.
|
||||
/// </remarks>
|
||||
public AdditionalPropertiesDictionary? AdditionalProperties { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString() => this.Text;
|
||||
|
||||
/// <summary>Creates an array of <see cref="AgentRunResponseUpdate" /> instances that represent this <see cref="AgentRunResponse" />.</summary>
|
||||
/// <returns>An array of <see cref="AgentRunResponseUpdate" /> instances that may be used to represent this <see cref="AgentRunResponse" />.</returns>
|
||||
/// <summary>
|
||||
/// Converts this <see cref="AgentRunResponse"/> into a collection of <see cref="AgentRunResponseUpdate"/> instances
|
||||
/// suitable for streaming scenarios.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An array of <see cref="AgentRunResponseUpdate"/> instances that collectively represent
|
||||
/// the same information as this response.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This method is useful for converting complete responses back into streaming format,
|
||||
/// which may be needed for scenarios that require uniform handling of both streaming
|
||||
/// and non-streaming agent responses.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Each message in <see cref="Messages"/> becomes a separate update, and usage information
|
||||
/// is included as an additional update if present. The order of updates preserves the
|
||||
/// original message sequence.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public AgentRunResponseUpdate[] ToAgentRunResponseUpdates()
|
||||
{
|
||||
AgentRunResponseUpdate? extra = null;
|
||||
|
||||
@@ -19,15 +19,16 @@ namespace Microsoft.Agents.AI;
|
||||
public static class AgentRunResponseExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ChatResponse"/> from an <see cref="AgentRunResponse"/>.
|
||||
/// Creates a <see cref="ChatResponse"/> from an <see cref="AgentRunResponse"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="response">The <see cref="AgentRunResponse"/>.</param>
|
||||
/// <returns>A <see cref="ChatResponse"/> built from <paramref name="response"/>.</returns>
|
||||
/// <param name="response">The <see cref="AgentRunResponse"/> to convert.</param>
|
||||
/// <returns>A <see cref="ChatResponse"/> built from the specified <paramref name="response"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="response"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// If the <paramref name="response"/>'s <see cref="AgentRunResponse.RawRepresentation"/> is a
|
||||
/// <see cref="ChatResponse"/> instance, that instance is returned directly. Otherwise, a new
|
||||
/// <see cref="ChatResponse"/> is created and populated with the data from the <paramref name="response"/>.
|
||||
/// The instance is a shallow copy; any reference-type members (e.g. <see cref="AgentRunResponse.Messages"/>)
|
||||
/// If the <paramref name="response"/>'s <see cref="AgentRunResponse.RawRepresentation"/> is already a
|
||||
/// <see cref="ChatResponse"/> instance, that instance is returned directly.
|
||||
/// Otherwise, a new <see cref="ChatResponse"/> is created and populated with the data from the <paramref name="response"/>.
|
||||
/// The resulting instance is a shallow copy; any reference-type members (e.g. <see cref="AgentRunResponse.Messages"/>)
|
||||
/// will be shared between the two instances.
|
||||
/// </remarks>
|
||||
public static ChatResponse AsChatResponse(this AgentRunResponse response)
|
||||
@@ -48,15 +49,16 @@ public static class AgentRunResponseExtensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ChatResponseUpdate"/> from an <see cref="AgentRunResponseUpdate"/>.
|
||||
/// Creates a <see cref="ChatResponseUpdate"/> from an <see cref="AgentRunResponseUpdate"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="responseUpdate">The <see cref="AgentRunResponseUpdate"/>.</param>
|
||||
/// <returns>A <see cref="ChatResponseUpdate"/> built from <paramref name="responseUpdate"/>.</returns>
|
||||
/// <param name="responseUpdate">The <see cref="AgentRunResponseUpdate"/> to convert.</param>
|
||||
/// <returns>A <see cref="ChatResponseUpdate"/> built from the specified <paramref name="responseUpdate"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="responseUpdate"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// If the <paramref name="responseUpdate"/>'s <see cref="AgentRunResponseUpdate.RawRepresentation"/> is a
|
||||
/// <see cref="ChatResponseUpdate"/> instance, that instance is returned directly. Otherwise, a new
|
||||
/// <see cref="ChatResponseUpdate"/> is created and populated with the data from the <paramref name="responseUpdate"/>.
|
||||
/// The instance is a shallow copy; any reference-type members (e.g. <see cref="AgentRunResponseUpdate.Contents"/>)
|
||||
/// If the <paramref name="responseUpdate"/>'s <see cref="AgentRunResponseUpdate.RawRepresentation"/> is already a
|
||||
/// <see cref="ChatResponseUpdate"/> instance, that instance is returned directly.
|
||||
/// Otherwise, a new <see cref="ChatResponseUpdate"/> is created and populated with the data from the <paramref name="responseUpdate"/>.
|
||||
/// The resulting instance is a shallow copy; any reference-type members (e.g. <see cref="AgentRunResponseUpdate.Contents"/>)
|
||||
/// will be shared between the two instances.
|
||||
/// </remarks>
|
||||
public static ChatResponseUpdate AsChatResponseUpdate(this AgentRunResponseUpdate responseUpdate)
|
||||
@@ -82,8 +84,9 @@ public static class AgentRunResponseExtensions
|
||||
/// Creates an asynchronous enumerable of <see cref="ChatResponseUpdate"/> instances from an asynchronous
|
||||
/// enumerable of <see cref="AgentRunResponseUpdate"/> instances.
|
||||
/// </summary>
|
||||
/// <param name="responseUpdates">The sequence <see cref="AgentRunResponseUpdate"/>.</param>
|
||||
/// <returns>A sequence of <see cref="ChatResponseUpdate"/> instances built from <paramref name="responseUpdates"/>.</returns>
|
||||
/// <param name="responseUpdates">The sequence of <see cref="AgentRunResponseUpdate"/> instances to convert.</param>
|
||||
/// <returns>An asynchronous enumerable of <see cref="ChatResponseUpdate"/> instances built from <paramref name="responseUpdates"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="responseUpdates"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// Each <see cref="AgentRunResponseUpdate"/> is converted to a <see cref="ChatResponseUpdate"/> using
|
||||
/// <see cref="AsChatResponseUpdate"/>.
|
||||
@@ -99,9 +102,11 @@ public static class AgentRunResponseExtensions
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Combines <see cref="AgentRunResponseUpdate"/> instances into a single <see cref="AgentRunResponse"/>.</summary>
|
||||
/// <param name="updates">The updates to be combined.</param>
|
||||
/// <returns>The combined <see cref="AgentRunResponse"/>.</returns>
|
||||
/// <summary>
|
||||
/// Combines a sequence of <see cref="AgentRunResponseUpdate"/> instances into a single <see cref="AgentRunResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="updates">The sequence of updates to be combined into a single response.</param>
|
||||
/// <returns>A single <see cref="AgentRunResponse"/> that represents the combined state of all the updates.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="updates"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// As part of combining <paramref name="updates"/> into a single <see cref="AgentRunResponse"/>, the method will attempt to reconstruct
|
||||
@@ -126,16 +131,24 @@ public static class AgentRunResponseExtensions
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>Combines <see cref="AgentRunResponseUpdate"/> instances into a single <see cref="AgentRunResponse"/>.</summary>
|
||||
/// <param name="updates">The updates to be combined.</param>
|
||||
/// <summary>
|
||||
/// Asynchronously combines a sequence of <see cref="AgentRunResponseUpdate"/> instances into a single <see cref="AgentRunResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="updates">The asynchronous sequence of updates to be combined into a single response.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>The combined <see cref="AgentRunResponse"/>.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains a single <see cref="AgentRunResponse"/> that represents the combined state of all the updates.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="updates"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This is the asynchronous version of <see cref="ToAgentRunResponse(IEnumerable{AgentRunResponseUpdate})"/>.
|
||||
/// It performs the same combining logic but operates on an asynchronous enumerable of updates.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// As part of combining <paramref name="updates"/> into a single <see cref="AgentRunResponse"/>, the method will attempt to reconstruct
|
||||
/// <see cref="ChatMessage"/> instances. This includes using <see cref="AgentRunResponseUpdate.MessageId"/> to determine
|
||||
/// message boundaries, as well as coalescing contiguous <see cref="AIContent"/> items where applicable, e.g. multiple
|
||||
/// <see cref="TextContent"/> instances in a row may be combined into a single <see cref="TextContent"/>.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static Task<AgentRunResponse> ToAgentRunResponseAsync(
|
||||
this IAsyncEnumerable<AgentRunResponseUpdate> updates,
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>Provides metadata about an <see cref="AgentThread"/>.</summary>
|
||||
/// <summary>
|
||||
/// Provides metadata information about an <see cref="AgentThread"/> instance.
|
||||
/// </summary>
|
||||
public class AgentThreadMetadata
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -11,40 +11,79 @@ using Microsoft.Shared.Diagnostics;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Defines methods for storing and retrieving chat messages associated with a specific thread.
|
||||
/// Provides an abstract base class for storing and managing chat messages associated with agent conversations.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Implementations of this interface are responsible for managing the storage of chat messages,
|
||||
/// including handling large volumes of data by truncating or summarizing messages as necessary.
|
||||
/// <para>
|
||||
/// <see cref="ChatMessageStore"/> defines the contract for persistent storage of chat messages in agent conversations.
|
||||
/// Implementations are responsible for managing message persistence, retrieval, and any necessary optimization
|
||||
/// strategies such as truncation, summarization, or archival.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Key responsibilities include:
|
||||
/// <list type="bullet">
|
||||
/// <item><description>Storing chat messages with proper ordering and metadata preservation</description></item>
|
||||
/// <item><description>Retrieving messages in chronological order for agent context</description></item>
|
||||
/// <item><description>Managing storage limits through truncation, summarization, or other strategies</description></item>
|
||||
/// <item><description>Supporting serialization for thread persistence and migration</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public abstract class ChatMessageStore
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all the messages from the store that should be used for the next agent invocation.
|
||||
/// Asynchronously retrieves all messages from the store that should be provided as context for the next agent invocation.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A collection of chat messages.</returns>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous operation. The task result contains a collection of <see cref="ChatMessage"/>
|
||||
/// instances in ascending chronological order (oldest first).
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Messages are returned in ascending chronological order, with the oldest message first.
|
||||
/// Messages are returned in chronological order to maintain proper conversation flow and context for the agent.
|
||||
/// The oldest messages appear first in the collection, followed by more recent messages.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If the messages stored in the store become very large, it is up to the store to
|
||||
/// truncate, summarize or otherwise limit the number of messages returned.
|
||||
/// If the total message history becomes very large, implementations should apply appropriate strategies to manage
|
||||
/// storage constraints, such as:
|
||||
/// <list type="bullet">
|
||||
/// <item><description>Truncating older messages while preserving recent context</description></item>
|
||||
/// <item><description>Summarizing message groups to maintain essential context</description></item>
|
||||
/// <item><description>Implementing sliding window approaches for message retention</description></item>
|
||||
/// <item><description>Archiving old messages while keeping active conversation context</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// When using implementations of <see cref="ChatMessageStore"/>, a new one should be created for each thread
|
||||
/// since they may contain state that is specific to a thread.
|
||||
/// Each store instance should be associated with a single conversation thread to ensure proper message isolation
|
||||
/// and context management.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public abstract Task<IEnumerable<ChatMessage>> GetMessagesAsync(CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Adds messages to the store.
|
||||
/// Asynchronously adds new messages to the store.
|
||||
/// </summary>
|
||||
/// <param name="messages">The messages to add.</param>
|
||||
/// <param name="messages">The collection of chat messages to add to the store.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>An async task.</returns>
|
||||
/// <returns>A task that represents the asynchronous add operation.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="messages"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Messages should be added in the order they were generated to maintain proper chronological sequence.
|
||||
/// The store is responsible for preserving message ordering and ensuring that subsequent calls to
|
||||
/// <see cref="GetMessagesAsync"/> return messages in the correct chronological order.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Implementations may perform additional processing during message addition, such as:
|
||||
/// <list type="bullet">
|
||||
/// <item><description>Validating message content and metadata</description></item>
|
||||
/// <item><description>Applying storage optimizations or compression</description></item>
|
||||
/// <item><description>Triggering background maintenance operations</description></item>
|
||||
/// <item><description>Updating indices or search capabilities</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public abstract Task AddMessagesAsync(IEnumerable<ChatMessage> messages, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -11,24 +11,46 @@ using Microsoft.Shared.Diagnostics;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Provides an optional base class for an <see cref="AIAgent"/> that passes through calls to another instance.
|
||||
/// Provides an abstract base class for AI agents that delegate operations to an inner agent
|
||||
/// instance while allowing for extensibility and customization.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is recommended as a base type when building agents that can be chained around an underlying <see cref="AIAgent"/>.
|
||||
/// The default implementation simply passes each call to the inner agent instance.
|
||||
/// <para>
|
||||
/// <see cref="DelegatingAIAgent"/> implements the decorator pattern for <see cref="AIAgent"/>s, enabling the creation of agent pipelines
|
||||
/// where each layer can add functionality while delegating core operations to an underlying agent. This pattern is
|
||||
/// fundamental to building composable agent architectures.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The default implementation provides transparent pass-through behavior, forwarding all operations to the inner agent.
|
||||
/// Derived classes can override specific methods to add custom behavior while maintaining compatibility with the agent interface.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class DelegatingAIAgent : AIAgent
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DelegatingAIAgent"/> class.
|
||||
/// Initializes a new instance of the <see cref="DelegatingAIAgent"/> class with the specified inner agent.
|
||||
/// </summary>
|
||||
/// <param name="innerAgent">The wrapped agent instance.</param>
|
||||
/// <param name="innerAgent">The underlying agent instance that will handle the core operations.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="innerAgent"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// The inner agent serves as the foundation of the delegation chain. All operations not overridden by
|
||||
/// derived classes will be forwarded to this agent.
|
||||
/// </remarks>
|
||||
protected DelegatingAIAgent(AIAgent innerAgent)
|
||||
{
|
||||
this.InnerAgent = Throw.IfNull(innerAgent);
|
||||
}
|
||||
|
||||
/// <summary>Gets the inner <see cref="AIAgent" />.</summary>
|
||||
/// <summary>
|
||||
/// Gets the inner agent instance that receives delegated operations.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The underlying <see cref="AIAgent"/> instance that handles core agent operations.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// Derived classes can use this property to access the inner agent for custom delegation scenarios
|
||||
/// or to forward operations with additional processing.
|
||||
/// </remarks>
|
||||
protected AIAgent InnerAgent { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -10,36 +10,66 @@ using Microsoft.Extensions.AI;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// A base class for agent threads that operate entirely in memory without external storage.
|
||||
/// Provides an abstract base class for agent threads that maintain all conversation state in local memory.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// <see cref="InMemoryAgentThread"/> is designed for scenarios where conversation state should be stored locally
|
||||
/// rather than in external services or databases. This approach provides high performance and simplicity while
|
||||
/// maintaining full control over the conversation data.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// In-memory threads do not persist conversation data across application restarts
|
||||
/// unless explicitly serialized and restored.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public abstract class InMemoryAgentThread : AgentThread
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InMemoryAgentThread"/> class.
|
||||
/// </summary>
|
||||
/// <param name="messageStore">An optional <see cref="InMemoryChatMessageStore"/> to use for storing chat messages. If null, a new instance will be created.</param>
|
||||
/// <param name="messageStore">
|
||||
/// An optional <see cref="InMemoryChatMessageStore"/> instance to use for storing chat messages.
|
||||
/// If <see langword="null"/>, a new empty message store will be created.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// This constructor allows sharing of message stores between threads or providing pre-configured
|
||||
/// message stores with specific reduction or processing logic.
|
||||
/// </remarks>
|
||||
protected InMemoryAgentThread(InMemoryChatMessageStore? messageStore = null)
|
||||
{
|
||||
this.MessageStore = messageStore ?? [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InMemoryAgentThread"/> class with the specified initial messages.
|
||||
/// Initializes a new instance of the <see cref="InMemoryAgentThread"/> class.
|
||||
/// </summary>
|
||||
/// <param name="messages">The messages to initialize the thread with.</param>
|
||||
/// <param name="messages">The initial messages to populate the conversation history.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="messages"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// This constructor is useful for initializing threads with existing conversation history or
|
||||
/// for migrating conversations from other storage systems.
|
||||
/// </remarks>
|
||||
protected InMemoryAgentThread(IEnumerable<ChatMessage> messages)
|
||||
{
|
||||
this.MessageStore = [.. messages];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InMemoryAgentThread"/> class from serialized state.
|
||||
/// Initializes a new instance of the <see cref="InMemoryAgentThread"/> class from previously serialized state.
|
||||
/// </summary>
|
||||
/// <param name="serializedThreadState">A <see cref="JsonElement"/> representing the serialized state of the thread.</param>
|
||||
/// <param name="jsonSerializerOptions">Optional settings for customizing the JSON deserialization process.</param>
|
||||
/// <param name="messageStoreFactory">A factory function to create the <see cref="InMemoryChatMessageStore"/> from its serialized state.</param>
|
||||
/// <param name="messageStoreFactory">
|
||||
/// Optional factory function to create the <see cref="InMemoryChatMessageStore"/> from its serialized state.
|
||||
/// If not provided, a default factory will be used that creates a basic in-memory store.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentException">The <paramref name="serializedThreadState"/> is not a JSON object.</exception>
|
||||
/// <exception cref="JsonException">The <paramref name="serializedThreadState"/> is invalid or cannot be deserialized to the expected type.</exception>
|
||||
/// <remarks>
|
||||
/// This constructor enables restoration of in-memory threads from previously saved state, allowing
|
||||
/// conversations to be resumed across application restarts or migrated between different instances.
|
||||
/// </remarks>
|
||||
protected InMemoryAgentThread(
|
||||
JsonElement serializedThreadState,
|
||||
JsonSerializerOptions? jsonSerializerOptions = null,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -12,8 +13,19 @@ using Microsoft.Shared.Diagnostics;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an in-memory store for chat messages associated with a specific thread.
|
||||
/// Provides an in-memory implementation of <see cref="ChatMessageStore"/> with support for message reduction and collection semantics.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// <see cref="InMemoryChatMessageStore"/> stores chat messages entirely in local memory, providing fast access and manipulation
|
||||
/// capabilities. It implements both <see cref="ChatMessageStore"/> for agent integration and <see cref="IList{ChatMessage}"/>
|
||||
/// for direct collection manipulation.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This store maintains all messages in memory. For long-running conversations or high-volume scenarios, consider using
|
||||
/// message reduction strategies or alternative storage implementations.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed class InMemoryChatMessageStore : ChatMessageStore, IList<ChatMessage>
|
||||
{
|
||||
private List<ChatMessage> _messages;
|
||||
@@ -21,16 +33,26 @@ public sealed class InMemoryChatMessageStore : ChatMessageStore, IList<ChatMessa
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InMemoryChatMessageStore"/> class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This constructor creates a basic in-memory store without message reduction capabilities.
|
||||
/// Messages will be stored exactly as added without any automatic processing or reduction.
|
||||
/// </remarks>
|
||||
public InMemoryChatMessageStore()
|
||||
{
|
||||
this._messages = [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InMemoryChatMessageStore"/> class, with an existing state from a serialized JSON element.
|
||||
/// Initializes a new instance of the <see cref="InMemoryChatMessageStore"/> class from previously serialized state.
|
||||
/// </summary>
|
||||
/// <param name="serializedStoreState">A <see cref="JsonElement"/> representing the serialized state of the store.</param>
|
||||
/// <param name="serializedStoreState">A <see cref="JsonElement"/> representing the serialized state of the message store.</param>
|
||||
/// <param name="jsonSerializerOptions">Optional settings for customizing the JSON deserialization process.</param>
|
||||
/// <exception cref="ArgumentException">The <paramref name="serializedStoreState"/> is not a valid JSON object or cannot be deserialized.</exception>
|
||||
/// <remarks>
|
||||
/// This constructor enables restoration of message stores from previously saved state, allowing
|
||||
/// conversation history to be preserved across application restarts or migrated between instances.
|
||||
/// The store will be configured with default settings and message reduction before retrieval.
|
||||
/// </remarks>
|
||||
public InMemoryChatMessageStore(JsonElement serializedStoreState, JsonSerializerOptions? jsonSerializerOptions = null)
|
||||
: this(null, serializedStoreState, jsonSerializerOptions, ChatReducerTriggerEvent.BeforeMessagesRetrieval)
|
||||
{
|
||||
@@ -39,8 +61,19 @@ public sealed class InMemoryChatMessageStore : ChatMessageStore, IList<ChatMessa
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InMemoryChatMessageStore"/> class.
|
||||
/// </summary>
|
||||
/// <param name="chatReducer">An optional <see cref="IChatReducer"/> instance used to process or reduce chat messages. If null, no reduction logic will be applied.</param>
|
||||
/// <param name="reducerTriggerEvent">The event that should trigger the reducer invocation.</param>
|
||||
/// <param name="chatReducer">
|
||||
/// A <see cref="IChatReducer"/> instance used to process, reduce, or optimize chat messages.
|
||||
/// This can be used to implement strategies like message summarization, truncation, or cleanup.
|
||||
/// </param>
|
||||
/// <param name="reducerTriggerEvent">
|
||||
/// Specifies when the message reducer should be invoked. The default is <see cref="ChatReducerTriggerEvent.BeforeMessagesRetrieval"/>,
|
||||
/// which applies reduction logic when messages are retrieved for agent consumption.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="chatReducer"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// Message reducers enable automatic management of message storage by implementing strategies to
|
||||
/// keep memory usage under control while preserving important conversation context.
|
||||
/// </remarks>
|
||||
public InMemoryChatMessageStore(IChatReducer chatReducer, ChatReducerTriggerEvent reducerTriggerEvent = ChatReducerTriggerEvent.BeforeMessagesRetrieval)
|
||||
: this(chatReducer, default, null, reducerTriggerEvent)
|
||||
{
|
||||
|
||||
@@ -7,33 +7,47 @@ using Microsoft.Shared.Diagnostics;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// A base class for agent threads that always store conversation state in the service, and only keep an ID reference in the <see cref="AgentThread"/>.
|
||||
/// Provides a base class for agent threads that store conversation state remotely in a service and maintain only an identifier reference locally.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class is designed for scenarios where conversation state is managed by an external service (such as a cloud-based AI service)
|
||||
/// rather than being stored locally. The thread maintains only the service identifier needed to reference the remote conversation state.
|
||||
/// </remarks>
|
||||
public abstract class ServiceIdAgentThread : AgentThread
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ServiceIdAgentThread"/> class.
|
||||
/// Initializes a new instance of the <see cref="ServiceIdAgentThread"/> class without a service thread identifier.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When using this constructor, the <see cref="ServiceThreadId"/> will be <see langword="null"/> initially
|
||||
/// and should be set by derived classes when the remote conversation is created.
|
||||
/// </remarks>
|
||||
protected ServiceIdAgentThread()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ServiceIdAgentThread"/> class with the specified service thread ID.
|
||||
/// Initializes a new instance of the <see cref="ServiceIdAgentThread"/> class with the specified service thread identifier.
|
||||
/// </summary>
|
||||
/// <param name="serviceThreadId">The ID that the conversation state is stored under in the service.</param>
|
||||
/// <param name="serviceThreadId">The unique identifier that references the conversation state stored in the remote service.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="serviceThreadId"/> is <see langword="null"/>.</exception>
|
||||
/// <exception cref="ArgumentException"><paramref name="serviceThreadId"/> is empty or contains only whitespace.</exception>
|
||||
protected ServiceIdAgentThread(string serviceThreadId)
|
||||
{
|
||||
this.ServiceThreadId = Throw.IfNullOrEmpty(serviceThreadId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ServiceIdAgentThread"/> class from serialized state.
|
||||
/// Initializes a new instance of the <see cref="ServiceIdAgentThread"/> class from previously serialized state.
|
||||
/// </summary>
|
||||
/// <param name="serializedThreadState">A <see cref="JsonElement"/> representing the serialized state of the thread.</param>
|
||||
/// <param name="jsonSerializerOptions">Optional settings for customizing the JSON deserialization process.</param>
|
||||
/// <exception cref="ArgumentException">The <paramref name="serializedThreadState"/> is not a JSON object.</exception>
|
||||
/// <exception cref="JsonException">The <paramref name="serializedThreadState"/> is invalid or cannot be deserialized to the expected type.</exception>
|
||||
/// <remarks>
|
||||
/// This constructor enables restoration of a service-backed thread from serialized state, typically used
|
||||
/// when deserializing thread information that was previously saved or transmitted across application boundaries.
|
||||
/// </remarks>
|
||||
protected ServiceIdAgentThread(
|
||||
JsonElement serializedThreadState,
|
||||
JsonSerializerOptions? jsonSerializerOptions = null)
|
||||
@@ -53,15 +67,28 @@ public abstract class ServiceIdAgentThread : AgentThread
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ID that the conversation state is stored under in the service.
|
||||
/// Gets or sets the unique identifier that references the conversation state stored in the remote service.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A string identifier that uniquely identifies the conversation within the remote service,
|
||||
/// or <see langword="null"/> if no remote conversation has been established yet.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This identifier is used by derived classes to reference the remote conversation state when making
|
||||
/// API calls to the backing service. The exact format and meaning of this identifier depends on the
|
||||
/// specific service implementation.
|
||||
/// </remarks>
|
||||
protected string? ServiceThreadId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the current object's state to a <see cref="JsonElement"/> using the specified serialization options.
|
||||
/// </summary>
|
||||
/// <param name="jsonSerializerOptions">The JSON serialization options to use.</param>
|
||||
/// <returns>A <see cref="JsonElement"/> representation of the object's state.</returns>
|
||||
/// <param name="jsonSerializerOptions">The JSON serialization options to use for the serialization process.</param>
|
||||
/// <returns>A <see cref="JsonElement"/> representation of the object's state, containing the service thread identifier.</returns>
|
||||
/// <remarks>
|
||||
/// The serialized state contains only the service thread identifier, as all other conversation state
|
||||
/// is maintained remotely by the backing service. This makes the serialized representation very lightweight.
|
||||
/// </remarks>
|
||||
public override JsonElement Serialize(JsonSerializerOptions? jsonSerializerOptions = null)
|
||||
{
|
||||
var state = new ServiceIdAgentThreadState
|
||||
|
||||
@@ -10,7 +10,9 @@ using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>A builder for creating pipelines of <see cref="AIAgent"/>.</summary>
|
||||
/// <summary>
|
||||
/// Provides a builder for creating pipelines of <see cref="AIAgent"/>s.
|
||||
/// </summary>
|
||||
public sealed class AIAgentBuilder
|
||||
{
|
||||
private readonly Func<IServiceProvider, AIAgent> _innerAgentFactory;
|
||||
@@ -29,12 +31,21 @@ public sealed class AIAgentBuilder
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AIAgentBuilder"/> class.</summary>
|
||||
/// <param name="innerAgentFactory">A callback that produces the inner <see cref="AIAgent"/> that represents the underlying backend.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="innerAgentFactory"/> is <see langword="null"/>.</exception>
|
||||
public AIAgentBuilder(Func<IServiceProvider, AIAgent> innerAgentFactory)
|
||||
{
|
||||
this._innerAgentFactory = Throw.IfNull(innerAgentFactory);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <summary>Builds an <see cref="AIAgent"/> that represents the entire pipeline.</summary>
|
||||
/// <param name="services">
|
||||
/// The <see cref="IServiceProvider"/> that should provide services to the <see cref="AIAgent"/> instances.
|
||||
/// If <see langword="null"/>, an empty <see cref="IServiceProvider"/> will be used.
|
||||
/// </param>
|
||||
/// <returns>An instance of <see cref="AIAgent"/> that represents the entire pipeline.</returns>
|
||||
/// <remarks>
|
||||
/// Calls to the resulting instance will pass through each of the pipeline stages in turn.
|
||||
/// </remarks>
|
||||
public AIAgent Build(IServiceProvider? services = null)
|
||||
{
|
||||
services ??= EmptyServiceProvider.Instance;
|
||||
@@ -58,7 +69,10 @@ public sealed class AIAgentBuilder
|
||||
return agent;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <summary>Adds a factory for an intermediate agent to the agent pipeline.</summary>
|
||||
/// <param name="agentFactory">The agent factory function.</param>
|
||||
/// <returns>The updated <see cref="AIAgentBuilder"/> instance.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="agentFactory"/> is <see langword="null"/>.</exception>
|
||||
public AIAgentBuilder Use(Func<AIAgent, AIAgent> agentFactory)
|
||||
{
|
||||
_ = Throw.IfNull(agentFactory);
|
||||
@@ -66,7 +80,10 @@ public sealed class AIAgentBuilder
|
||||
return this.Use((innerAgent, _) => agentFactory(innerAgent));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <summary>Adds a factory for an intermediate agent to the agent pipeline.</summary>
|
||||
/// <param name="agentFactory">The agent factory function.</param>
|
||||
/// <returns>The updated <see cref="AIAgentBuilder"/> instance.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="agentFactory"/> is <see langword="null"/>.</exception>
|
||||
public AIAgentBuilder Use(Func<AIAgent, IServiceProvider, AIAgent> agentFactory)
|
||||
{
|
||||
_ = Throw.IfNull(agentFactory);
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>Provides extension methods for working with <see cref="AIAgent"/> in the context of <see cref="AIAgentBuilder"/>.</summary>
|
||||
public static class AIAgentBuilderAIAgentExtensions
|
||||
{
|
||||
/// <summary>Creates a new <see cref="AIAgentBuilder"/> using <paramref name="innerAgent"/> as its inner agent.</summary>
|
||||
/// <param name="innerAgent">The agent to use as the inner agent.</param>
|
||||
/// <returns>The new <see cref="AIAgentBuilder"/> instance.</returns>
|
||||
/// <remarks>
|
||||
/// This method is equivalent to using the <see cref="AIAgentBuilder"/> constructor directly,
|
||||
/// specifying <paramref name="innerAgent"/> as the inner agent.
|
||||
/// </remarks>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="innerAgent"/> is <see langword="null"/>.</exception>
|
||||
public static AIAgentBuilder AsBuilder(this AIAgent innerAgent)
|
||||
{
|
||||
_ = Throw.IfNull(innerAgent);
|
||||
|
||||
return new AIAgentBuilder(innerAgent);
|
||||
}
|
||||
}
|
||||
@@ -9,20 +9,31 @@ using Microsoft.Shared.Diagnostics;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Provides extension methods for configuring an <see cref="AIAgentBuilder"/> instance.
|
||||
/// Provides extension methods for configuring and customizing <see cref="AIAgentBuilder"/> instances.
|
||||
/// </summary>
|
||||
/// <remarks>This class contains methods that extend the functionality of the <see cref="AIAgentBuilder"/> to
|
||||
/// allow additional customization and behavior injection.</remarks>
|
||||
public static class AIAgentBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a middleware to the AI agent pipeline that intercepts and processes <see cref="AIFunction"/> invocations.
|
||||
/// Adds function invocation callbacks to the <see cref="AIAgent"/> pipeline that intercepts and processes <see cref="AIFunction"/> calls.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AIAgentBuilder"/> to which the middleware is added.</param>
|
||||
/// <param name="callback">A delegate that processes function invocations. The delegate receives the invocation context, the next
|
||||
/// middleware in the pipeline, and a cancellation token, and returns a task representing the result of the
|
||||
/// invocation.</param>
|
||||
/// <returns>The <see cref="AIAgentBuilder"/> instance with the middleware added.</returns>
|
||||
/// <param name="builder">The <see cref="AIAgentBuilder"/> to which the function invocation callback is added.</param>
|
||||
/// <param name="callback">
|
||||
/// A delegate that processes function invocations. The delegate receives the <see cref="AIAgent"/> instance,
|
||||
/// the function invocation context, and a continuation delegate representing the next callback in the pipeline.
|
||||
/// It returns a task representing the result of the function invocation.
|
||||
/// </param>
|
||||
/// <returns>The <see cref="AIAgentBuilder"/> instance with the function invocation callback added, enabling method chaining.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="builder"/> or <paramref name="callback"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The callback must call the provided continuation delegate to proceed with the function invocation,
|
||||
/// unless it intends to completely replace the function's behavior.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The inner agent or the pipeline wrapping it must include a <see cref="FunctionInvokingChatClient"/>. If one does not exist,
|
||||
/// the <see cref="AIAgent"/> added to the pipline by this method will throw an exception when it is invoked.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static AIAgentBuilder Use(this AIAgentBuilder builder, Func<AIAgent, FunctionInvocationContext, Func<FunctionInvocationContext, CancellationToken, ValueTask<object?>>, CancellationToken, ValueTask<object?>> callback)
|
||||
{
|
||||
_ = Throw.IfNull(builder);
|
||||
@@ -38,4 +49,50 @@ public static class AIAgentBuilderExtensions
|
||||
return new FunctionInvocationDelegatingAgent(innerAgent, callback);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds OpenTelemetry instrumentation to the agent pipeline, enabling comprehensive observability for agent operations.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AIAgentBuilder"/> to which OpenTelemetry support will be added.</param>
|
||||
/// <param name="sourceName">
|
||||
/// An optional source name that will be used to identify telemetry data from this agent.
|
||||
/// If not specified, a default source name will be used.
|
||||
/// </param>
|
||||
/// <param name="configure">
|
||||
/// An optional callback that provides additional configuration of the <see cref="OpenTelemetryAgent"/> instance.
|
||||
/// This allows for fine-tuning telemetry behavior such as enabling sensitive data collection.
|
||||
/// </param>
|
||||
/// <returns>The <see cref="AIAgentBuilder"/> with OpenTelemetry instrumentation added, enabling method chaining.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="builder"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This extension adds comprehensive telemetry capabilities to AI agents, including:
|
||||
/// <list type="bullet">
|
||||
/// <item><description>Distributed tracing of agent invocations</description></item>
|
||||
/// <item><description>Performance metrics and timing information</description></item>
|
||||
/// <item><description>Request and response payload logging (when enabled)</description></item>
|
||||
/// <item><description>Error tracking and exception details</description></item>
|
||||
/// <item><description>Usage statistics and token consumption metrics</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The implementation follows the OpenTelemetry Semantic Conventions for Generative AI systems as defined at
|
||||
/// <see href="https://opentelemetry.io/docs/specs/semconv/gen-ai/"/>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Note: The OpenTelemetry specification for Generative AI is still experimental and subject to change.
|
||||
/// As the specification evolves, the telemetry output from this agent may also change to maintain compliance.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static AIAgentBuilder UseOpenTelemetry(
|
||||
this AIAgentBuilder builder,
|
||||
string? sourceName = null,
|
||||
Action<OpenTelemetryAgent>? configure = null) =>
|
||||
Throw.IfNull(builder).Use((innerAgent, services) =>
|
||||
{
|
||||
var agent = new OpenTelemetryAgent(innerAgent, sourceName);
|
||||
configure?.Invoke(agent);
|
||||
|
||||
return agent;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -9,17 +10,59 @@ using Microsoft.Shared.Diagnostics;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="AIAgent"/>.
|
||||
/// Provides extensions for <see cref="AIAgent"/>.
|
||||
/// </summary>
|
||||
public static class AgentExtensions
|
||||
public static class AIAgentExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a <see cref="AIFunction"/> that will invoke the provided Agent.
|
||||
/// Creates a new <see cref="AIAgentBuilder"/> using the specified agent as the foundation for the builder pipeline.
|
||||
/// </summary>
|
||||
/// <param name="agent">The <see cref="AIAgent" /> to be represented via the created <see cref="AIFunction"/>.</param>
|
||||
/// <param name="options">Metadata to use to override defaults inferred from <paramref name="agent"/>.</param>
|
||||
/// <param name="thread">The <see cref="AgentThread"/> to use for the function.</param>
|
||||
/// <returns>The created <see cref="AIFunction"/> for invoking the <see cref="AIAgent"/>.</returns>
|
||||
/// <param name="innerAgent">The <see cref="AIAgent"/> instance to use as the inner agent.</param>
|
||||
/// <returns>A new <see cref="AIAgentBuilder"/> instance configured with the specified inner agent.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="innerAgent"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// This method provides a convenient way to convert an existing <see cref="AIAgent"/> instance into
|
||||
/// a builder pattern, enabling easily wrapping the agent in layers of additional functionality.
|
||||
/// It is functionally equivalent to using the <see cref="AIAgentBuilder(AIAgent)"/> constructor directly,
|
||||
/// but provides a more fluent API when working with existing agent instances.
|
||||
/// </remarks>
|
||||
public static AIAgentBuilder AsBuilder(this AIAgent innerAgent)
|
||||
{
|
||||
_ = Throw.IfNull(innerAgent);
|
||||
|
||||
return new AIAgentBuilder(innerAgent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="AIFunction"/> that runs the provided <see cref="AIAgent"/>.
|
||||
/// </summary>
|
||||
/// <param name="agent">The <see cref="AIAgent"/> to be represented as an invocable function.</param>
|
||||
/// <param name="options">
|
||||
/// Optional metadata to customize the function representation, such as name and description.
|
||||
/// If not provided, defaults will be inferred from the agent's properties.
|
||||
/// </param>
|
||||
/// <param name="thread">
|
||||
/// Optional <see cref="AgentThread"/> to use for function invocations. If not provided, a new thread
|
||||
/// will be created for each function call, which may not preserve conversation context.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// An <see cref="AIFunction"/> that can be used as a tool by other agents or AI models to invoke this agent.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="agent"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This extension method enables agents to participate in function calling scenarios, where they can be
|
||||
/// invoked as tools by other agents or AI models. The resulting function accepts a query string as input and
|
||||
/// returns the agent's response as a string, making it compatible with standard function calling interfaces
|
||||
/// used by AI models.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The resulting <see cref="AIFunction"/> is stateful, referencing both the <paramref name="agent"/> and the optional
|
||||
/// <paramref name="thread"/>. Especially if a specific thread is provided, avoid using the resulting function concurrently
|
||||
/// in multiple conversations or in requests where the parallel function calls may result in concurrent usage of the thread,
|
||||
/// as that could lead to undefined and unpredictable behavior.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static AIFunction AsAIFunction(this AIAgent agent, AIFunctionFactoryOptions? options = null, AgentThread? thread = null)
|
||||
{
|
||||
Throw.IfNull(agent);
|
||||
|
||||
@@ -17,7 +17,7 @@ using Microsoft.Shared.Diagnostics;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an agent that can be invoked using a chat client.
|
||||
/// Provides an <see cref="AIAgent"/> that delegates to an <see cref="IChatClient"/> implementation.
|
||||
/// </summary>
|
||||
public sealed class ChatClientAgent : AIAgent
|
||||
{
|
||||
@@ -29,13 +29,33 @@ public sealed class ChatClientAgent : AIAgent
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChatClientAgent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="chatClient">The chat client to use for invoking the agent.</param>
|
||||
/// <param name="instructions">Optional instructions for the agent.</param>
|
||||
/// <param name="name">Optional name for the agent.</param>
|
||||
/// <param name="description">Optional description for the agent.</param>
|
||||
/// <param name="tools">Optional list of tools that the agent can use during invocation.</param>
|
||||
/// <param name="loggerFactory">Optional logger factory to use for logging.</param>
|
||||
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
|
||||
/// <param name="chatClient">The chat client to use when running the agent.</param>
|
||||
/// <param name="instructions">
|
||||
/// Optional system instructions that guide the agent's behavior. These instructions are provided to the <see cref="IChatClient"/>
|
||||
/// with each invocation to establish the agent's role and behavior.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// Optional name for the agent. This name is used for identification and logging purposes.
|
||||
/// </param>
|
||||
/// <param name="description">
|
||||
/// Optional human-readable description of the agent's purpose and capabilities.
|
||||
/// This description can be useful for documentation and agent discovery scenarios.
|
||||
/// </param>
|
||||
/// <param name="tools">
|
||||
/// Optional collection of tools that the agent can invoke during conversations.
|
||||
/// These tools augment any tools that may be provided to the agent via <see cref="ChatOptions.Tools"/> when
|
||||
/// the agent is run.
|
||||
/// </param>
|
||||
/// <param name="loggerFactory">
|
||||
/// Optional logger factory for creating loggers used by the agent and its components.
|
||||
/// </param>
|
||||
/// <param name="services">
|
||||
/// Optional service provider for resolving dependencies required by AI functions and other agent components.
|
||||
/// This is particularly important when using custom tools that require dependency injection.
|
||||
/// This is only relevant when the <see cref="IChatClient"/> doesn't already contain a <see cref="FunctionInvokingChatClient"/>
|
||||
/// and the <see cref="ChatClientAgent"/> needs to insert one.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="chatClient"/> is <see langword="null"/>.</exception>
|
||||
public ChatClientAgent(IChatClient chatClient, string? instructions = null, string? name = null, string? description = null, IList<AITool>? tools = null, ILoggerFactory? loggerFactory = null, IServiceProvider? services = null)
|
||||
: this(
|
||||
chatClient,
|
||||
@@ -57,10 +77,21 @@ public sealed class ChatClientAgent : AIAgent
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChatClientAgent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="chatClient">The chat client to use for invoking the agent.</param>
|
||||
/// <param name="options">Full set of options to configure the agent.</param>
|
||||
/// <param name="loggerFactory">Optional logger factory to use for logging.</param>
|
||||
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
|
||||
/// <param name="chatClient">The chat client to use when running the agent.</param>
|
||||
/// <param name="options">
|
||||
/// Configuration options that control all aspects of the agent's behavior, including chat settings,
|
||||
/// message store factories, context provider factories, and other advanced configurations.
|
||||
/// </param>
|
||||
/// <param name="loggerFactory">
|
||||
/// Optional logger factory for creating loggers used by the agent and its components.
|
||||
/// </param>
|
||||
/// <param name="services">
|
||||
/// Optional service provider for resolving dependencies required by AI functions and other agent components.
|
||||
/// This is particularly important when using custom tools that require dependency injection.
|
||||
/// This is only relevant when the <see cref="IChatClient"/> doesn't already contain a <see cref="FunctionInvokingChatClient"/>
|
||||
/// and the <see cref="ChatClientAgent"/> needs to insert one.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="chatClient"/> is <see langword="null"/>.</exception>
|
||||
public ChatClientAgent(IChatClient chatClient, ChatClientAgentOptions? options, ILoggerFactory? loggerFactory = null, IServiceProvider? services = null)
|
||||
{
|
||||
_ = Throw.IfNull(chatClient);
|
||||
@@ -82,6 +113,13 @@ public sealed class ChatClientAgent : AIAgent
|
||||
/// <summary>
|
||||
/// Gets the underlying chat client used by the agent to invoke chat completions.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The <see cref="IChatClient"/> instance that backs this agent.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This may return the original client provided when the <see cref="ChatClientAgent"/> was constructed, or it may
|
||||
/// return a pipeline of decorating <see cref="IChatClient"/> instances applied around that inner client.
|
||||
/// </remarks>
|
||||
public IChatClient ChatClient { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -94,8 +132,17 @@ public sealed class ChatClientAgent : AIAgent
|
||||
public override string? Description => this._agentOptions?.Description;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instructions for the agent (optional).
|
||||
/// Gets the system instructions that guide the agent's behavior during conversations.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A string containing the system instructions that are provided to the underlying chat client
|
||||
/// to establish the agent's role, personality, and behavioral guidelines. May be <see langword="null"/>
|
||||
/// if no specific instructions were configured.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// These instructions are typically provided to the AI model as system messages to establish
|
||||
/// the context and expected behavior for the agent's responses.
|
||||
/// </remarks>
|
||||
public string? Instructions => this._agentOptions?.Instructions;
|
||||
|
||||
/// <summary>
|
||||
@@ -282,13 +329,21 @@ public sealed class ChatClientAgent : AIAgent
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Get a new <see cref="AgentThread"/> instance using an existing conversation id, to continue that conversation.
|
||||
/// Creates a new agent thread instance using an existing conversation identifier to continue that conversation.
|
||||
/// </summary>
|
||||
/// <param name="conversationId">The conversation id to continue.</param>
|
||||
/// <returns>A new <see cref="AgentThread"/> instance.</returns>
|
||||
/// <param name="conversationId">The identifier of an existing conversation to continue.</param>
|
||||
/// <returns>
|
||||
/// A new <see cref="AgentThread"/> instance configured to work with the specified conversation.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Note that any <see cref="AgentThread"/> created with this method will only work with <see cref="ChatClientAgent"/> instances that support storing
|
||||
/// chat history in the underlying service provided by the <see cref="IChatClient"/>.
|
||||
/// <para>
|
||||
/// This method creates threads that rely on server-side conversation storage, where the chat history
|
||||
/// is maintained by the underlying AI service rather than in local message stores.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Agent threads created with this method will only work with <see cref="ChatClientAgent"/>
|
||||
/// instances that support server-side conversation storage through their underlying <see cref="IChatClient"/>.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public AgentThread GetNewThread(string conversationId)
|
||||
=> new ChatClientAgentThread()
|
||||
|
||||
@@ -6,24 +6,48 @@ using Microsoft.Extensions.AI;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Chat client agent run options.
|
||||
/// Provides specialized run options for <see cref="ChatClientAgent"/> instances, extending the base agent run options with chat-specific configuration.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class extends <see cref="AgentRunOptions"/> to provide additional configuration options that are specific to
|
||||
/// chat client agents, in particular <see cref="ChatOptions"/>.
|
||||
/// </remarks>
|
||||
public sealed class ChatClientAgentRunOptions : AgentRunOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChatClientAgentRunOptions"/> class.
|
||||
/// </summary>
|
||||
/// <param name="chatOptions">Optional chat options to pass to the agent's invocation.</param>
|
||||
/// <param name="chatOptions">
|
||||
/// Optional chat options to customize the behavior of the chat client during this specific agent invocation.
|
||||
/// These options will be merged with the default chat options configured for the agent.
|
||||
/// </param>
|
||||
public ChatClientAgentRunOptions(ChatOptions? chatOptions = null)
|
||||
{
|
||||
this.ChatOptions = chatOptions;
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets optional chat options to pass to the agent's invocation.</summary>
|
||||
/// <summary>
|
||||
/// Gets or sets the chat options to apply to the agent invocation.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Chat options that control various aspects of the chat client's behavior, such as temperature, max tokens,
|
||||
/// tools, instructions, and other model-specific parameters. If <see langword="null"/>, the agent's default
|
||||
/// chat options will be used.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// These options are specific to this invocation and will be combined with the agent's default chat options.
|
||||
/// If both the agent and this run options specify the same option, the run options value typically takes precedence.
|
||||
/// In the case of collections, like <see cref="ChatOptions.Tools"/>, the collections will be unioned.
|
||||
/// </remarks>
|
||||
public ChatOptions? ChatOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the factory method used to modify instances of <see cref="IChatClient"/> per-request.
|
||||
/// Gets or sets a factory function that can replace (typically via decorators) the chat client on a per-request basis.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A function that receives the agent's configured chat client and returns a potentially modified or entirely
|
||||
/// different chat client to use for this specific invocation. If <see langword="null"/>, the agent's default
|
||||
/// chat client will be used without modification.
|
||||
/// </value>
|
||||
public Func<IChatClient, IChatClient>? ChatClientFactory { get; set; }
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ using Microsoft.Shared.Diagnostics;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Thread for ChatClient based agents.
|
||||
/// Provides a thread implementation for use with <see cref="ChatClientAgent"/>.
|
||||
/// </summary>
|
||||
public class ChatClientAgentThread : AgentThread
|
||||
{
|
||||
@@ -27,12 +27,18 @@ public class ChatClientAgentThread : AgentThread
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChatClientAgentThread"/> class from serialized state.
|
||||
/// Initializes a new instance of the <see cref="ChatClientAgentThread"/> class from previously serialized state.
|
||||
/// </summary>
|
||||
/// <param name="serializedThreadState">A <see cref="JsonElement"/> representing the serialized state of the thread.</param>
|
||||
/// <param name="jsonSerializerOptions">Optional settings for customizing the JSON deserialization process.</param>
|
||||
/// <param name="chatMessageStoreFactory">An optional factory function to create a custom <see cref="ChatMessageStore"/>.</param>
|
||||
/// <param name="aiContextProviderFactory">An optional factory function to create a custom <see cref="AIContextProvider"/>.</param>
|
||||
/// <param name="chatMessageStoreFactory">
|
||||
/// An optional factory function to create a custom <see cref="ChatMessageStore"/> from its serialized state.
|
||||
/// If not provided, the default in-memory message store will be used.
|
||||
/// </param>
|
||||
/// <param name="aiContextProviderFactory">
|
||||
/// An optional factory function to create a custom <see cref="AIContextProvider"/> from its serialized state.
|
||||
/// If not provided, no context provider will be configured.
|
||||
/// </param>
|
||||
internal ChatClientAgentThread(
|
||||
JsonElement serializedThreadState,
|
||||
JsonSerializerOptions? jsonSerializerOptions = null,
|
||||
@@ -152,13 +158,9 @@ public class ChatClientAgentThread : AgentThread
|
||||
/// <inheritdoc/>
|
||||
public override JsonElement Serialize(JsonSerializerOptions? jsonSerializerOptions = null)
|
||||
{
|
||||
JsonElement? storeState = this._messageStore is null ?
|
||||
null :
|
||||
this._messageStore.Serialize(jsonSerializerOptions);
|
||||
JsonElement? storeState = this._messageStore?.Serialize(jsonSerializerOptions);
|
||||
|
||||
JsonElement? aiContextProviderState = this.AIContextProvider is null ?
|
||||
null :
|
||||
this.AIContextProvider.Serialize(jsonSerializerOptions);
|
||||
JsonElement? aiContextProviderState = this.AIContextProvider?.Serialize(jsonSerializerOptions);
|
||||
|
||||
var state = new ThreadState
|
||||
{
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>Provides extensions for configuring <see cref="OpenTelemetryAgent"/> instances.</summary>
|
||||
public static class OpenTelemetryAIAgentBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds OpenTelemetry support to the agent pipeline for agent runs, following the OpenTelemetry Semantic Conventions for Generative AI systems.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The draft specification this follows is available at <see href="https://opentelemetry.io/docs/specs/semconv/gen-ai/" />.
|
||||
/// The specification is still experimental and subject to change; as such, the telemetry output by this agent is also subject to change.
|
||||
/// </remarks>
|
||||
/// <param name="builder">The <see cref="AIAgentBuilder"/>.</param>
|
||||
/// <param name="sourceName">An optional source name that will be used on the telemetry data.</param>
|
||||
/// <param name="configure">An optional callback that can be used to configure the <see cref="OpenTelemetryAgent"/> instance.</param>
|
||||
/// <returns>The <paramref name="builder"/>.</returns>
|
||||
public static AIAgentBuilder UseOpenTelemetry(
|
||||
this AIAgentBuilder builder,
|
||||
string? sourceName = null,
|
||||
Action<OpenTelemetryAgent>? configure = null) =>
|
||||
Throw.IfNull(builder).Use((innerAgent, services) =>
|
||||
{
|
||||
var agent = new OpenTelemetryAgent(innerAgent, sourceName);
|
||||
configure?.Invoke(agent);
|
||||
|
||||
return agent;
|
||||
});
|
||||
}
|
||||
@@ -10,9 +10,11 @@ using Microsoft.Extensions.AI;
|
||||
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>Represents a delegating <see cref="AIAgent"/> that implements the OpenTelemetry Semantic Conventions for Generative AI systems.</summary>
|
||||
/// <summary>
|
||||
/// Provides a delegating <see cref="AIAgent"/> implementation that implements the OpenTelemetry Semantic Conventions for Generative AI systems.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class provides an implementation of the Semantic Conventions for Generative AI systems, defined at <see href="https://opentelemetry.io/docs/specs/semconv/gen-ai/" />.
|
||||
/// This class provides an implementation of the Semantic Conventions for Generative AI systems v1.37, defined at <see href="https://opentelemetry.io/docs/specs/semconv/gen-ai/" />.
|
||||
/// The specification is still experimental and subject to change; as such, the telemetry output by this client is also subject to change.
|
||||
/// </remarks>
|
||||
public sealed class OpenTelemetryAgent : DelegatingAIAgent, IDisposable
|
||||
@@ -32,9 +34,16 @@ public sealed class OpenTelemetryAgent : DelegatingAIAgent, IDisposable
|
||||
private readonly string? _providerName;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="OpenTelemetryAgent"/> class.</summary>
|
||||
/// <param name="innerAgent">The underlying <see cref="AIAgent"/>.</param>
|
||||
/// <param name="sourceName">An optional source name that will be used on the telemetry data.</param>
|
||||
/// <param name="innerAgent">The underlying <see cref="AIAgent"/> to be augmented with telemetry capabilities.</param>
|
||||
/// <param name="sourceName">
|
||||
/// An optional source name that will be used to identify telemetry data from this agent.
|
||||
/// If not provided, a default source name will be used for telemetry identification.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="innerAgent"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// The constructor automatically extracts provider metadata from the inner agent and configures
|
||||
/// telemetry collection according to OpenTelemetry semantic conventions for AI systems.
|
||||
/// </remarks>
|
||||
public OpenTelemetryAgent(AIAgent innerAgent, string? sourceName = null) : base(innerAgent)
|
||||
{
|
||||
this._providerName = innerAgent.GetService<AIAgentMetadata>()?.ProviderName;
|
||||
|
||||
@@ -12,7 +12,7 @@ using Moq;
|
||||
namespace Microsoft.Agents.AI.UnitTests;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for the <see cref="AgentExtensions.AsAIFunction"/> method.
|
||||
/// Unit tests for the <see cref="AIAgentExtensions.AsAIFunction"/> method.
|
||||
/// </summary>
|
||||
public class AgentExtensionsTests
|
||||
{
|
||||
@@ -21,7 +21,7 @@ public class AgentExtensionsTests
|
||||
{
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<ArgumentNullException>(() =>
|
||||
AgentExtensions.AsAIFunction(null!));
|
||||
AIAgentExtensions.AsAIFunction(null!));
|
||||
|
||||
Assert.Equal("agent", exception.ParamName);
|
||||
}
|
||||
|
||||
+2
-3
@@ -7,7 +7,7 @@ using Moq;
|
||||
namespace Microsoft.Agents.AI.UnitTests;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for the <see cref="OpenTelemetryAIAgentBuilderExtensions"/> class.
|
||||
/// Unit tests for the <see cref="AIAgentBuilderExtensions"/> class.
|
||||
/// </summary>
|
||||
public class OpenTelemetryAIAgentBuilderExtensionsTests
|
||||
{
|
||||
@@ -18,8 +18,7 @@ public class OpenTelemetryAIAgentBuilderExtensionsTests
|
||||
public void UseOpenTelemetry_WithNullBuilder_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>("builder", () =>
|
||||
OpenTelemetryAIAgentBuilderExtensions.UseOpenTelemetry(null!));
|
||||
Assert.Throws<ArgumentNullException>("builder", () => ((AIAgentBuilder)null!).UseOpenTelemetry());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user