diff --git a/dotnet/src/Microsoft.Agents.Abstractions/Agent.cs b/dotnet/src/Microsoft.Agents.Abstractions/Agent.cs
index ba452532c0..90c0c155db 100644
--- a/dotnet/src/Microsoft.Agents.Abstractions/Agent.cs
+++ b/dotnet/src/Microsoft.Agents.Abstractions/Agent.cs
@@ -21,7 +21,7 @@ public abstract class Agent
///
/// 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.
///
- public virtual string Id => Guid.NewGuid().ToString();
+ public virtual string Id { get; } = Guid.NewGuid().ToString();
///
/// Gets the name of the agent (optional).
@@ -60,7 +60,7 @@ public abstract class Agent
/// Optional parameters for agent invocation.
/// The to monitor for cancellation requests. The default is .
/// A containing the list of items.
- public virtual Task RunAsync(
+ public Task RunAsync(
AgentThread? thread = null,
AgentRunOptions? options = null,
CancellationToken cancellationToken = default)
@@ -79,7 +79,7 @@ public abstract class Agent
///
/// The provided message string will be treated as a user message.
///
- public virtual Task RunAsync(
+ public Task RunAsync(
string message,
AgentThread? thread = null,
AgentRunOptions? options = null,
@@ -98,7 +98,7 @@ public abstract class Agent
/// Optional parameters for agent invocation.
/// The to monitor for cancellation requests. The default is .
/// A containing the list of items.
- public virtual Task RunAsync(
+ public Task RunAsync(
ChatMessage message,
AgentThread? thread = null,
AgentRunOptions? options = null,
@@ -130,7 +130,7 @@ public abstract class Agent
/// Optional parameters for agent invocation.
/// The to monitor for cancellation requests. The default is .
/// An async list of response items that each contain a .
- public virtual IAsyncEnumerable RunStreamingAsync(
+ public IAsyncEnumerable RunStreamingAsync(
AgentThread? thread = null,
AgentRunOptions? options = null,
CancellationToken cancellationToken = default)
@@ -149,7 +149,7 @@ public abstract class Agent
///
/// The provided message string will be treated as a user message.
///
- public virtual IAsyncEnumerable RunStreamingAsync(
+ public IAsyncEnumerable RunStreamingAsync(
string message,
AgentThread? thread = null,
AgentRunOptions? options = null,
@@ -168,7 +168,7 @@ public abstract class Agent
/// Optional parameters for agent invocation.
/// The to monitor for cancellation requests. The default is .
/// An async list of response items that each contain a .
- public virtual IAsyncEnumerable RunStreamingAsync(
+ public IAsyncEnumerable RunStreamingAsync(
ChatMessage message,
AgentThread? thread = null,
AgentRunOptions? options = null,
@@ -241,6 +241,9 @@ public abstract class Agent
/// An async task that completes once the notification is complete.
protected async Task NotifyThreadOfNewMessagesAsync(AgentThread thread, IReadOnlyCollection messages, CancellationToken cancellationToken)
{
+ _ = Throw.IfNull(thread);
+ _ = Throw.IfNull(messages);
+
if (messages.Count > 0)
{
await thread.OnNewMessagesAsync(messages, cancellationToken).ConfigureAwait(false);
diff --git a/dotnet/tests/Microsoft.Agents.Abstractions.UnitTests/AgentTests.cs b/dotnet/tests/Microsoft.Agents.Abstractions.UnitTests/AgentTests.cs
index 94dd047b2d..e2a9580591 100644
--- a/dotnet/tests/Microsoft.Agents.Abstractions.UnitTests/AgentTests.cs
+++ b/dotnet/tests/Microsoft.Agents.Abstractions.UnitTests/AgentTests.cs
@@ -211,6 +211,16 @@ public class AgentTests
Times.Once);
}
+ [Fact]
+ public void ValidateAgentIDIsIdempotent()
+ {
+ var agent = new MockAgent();
+
+ string id = agent.Id;
+ Assert.NotNull(id);
+ Assert.Equal(id, agent.Id);
+ }
+
[Fact]
public void ValidateOrCreateThreadTypeVerifiesAndCreatesThread()
{