diff --git a/dotnet/AutoGen.v3.ncrunchsolution b/dotnet/AutoGen.v3.ncrunchsolution
new file mode 100644
index 00000000000..13107d39442
--- /dev/null
+++ b/dotnet/AutoGen.v3.ncrunchsolution
@@ -0,0 +1,8 @@
+
+
+ True
+ True
+ True
+ True
+
+
\ No newline at end of file
diff --git a/dotnet/src/Microsoft.AutoGen/Abstractions/IAgentRuntime.cs b/dotnet/src/Microsoft.AutoGen/Abstractions/IAgentRuntime.cs
index aa5b5a13a6d..6b3d4f98cdb 100644
--- a/dotnet/src/Microsoft.AutoGen/Abstractions/IAgentRuntime.cs
+++ b/dotnet/src/Microsoft.AutoGen/Abstractions/IAgentRuntime.cs
@@ -15,8 +15,8 @@ public interface IAgentRuntime
ValueTask SendRequestAsync(IAgentBase agent, RpcRequest request, CancellationToken cancellationToken = default);
ValueTask SendMessageAsync(Message message, CancellationToken cancellationToken = default);
ValueTask PublishEventAsync(CloudEvent @event, CancellationToken cancellationToken = default);
- void Update(Activity? activity, RpcRequest request);
- void Update(Activity? activity, CloudEvent cloudEvent);
- (string?, string?) GetTraceIDandState(IDictionary metadata);
+ void Update(RpcRequest request, Activity? activity);
+ void Update(CloudEvent cloudEvent, Activity? activity);
+ (string?, string?) GetTraceIdAndState(IDictionary metadata);
IDictionary ExtractMetadata(IDictionary metadata);
}
diff --git a/dotnet/src/Microsoft.AutoGen/Abstractions/IAgentState.cs b/dotnet/src/Microsoft.AutoGen/Abstractions/IAgentState.cs
index 0a6784b54fd..1b816b4ef3a 100644
--- a/dotnet/src/Microsoft.AutoGen/Abstractions/IAgentState.cs
+++ b/dotnet/src/Microsoft.AutoGen/Abstractions/IAgentState.cs
@@ -3,8 +3,24 @@
namespace Microsoft.AutoGen.Abstractions;
+///
+/// Interface for managing the state of an agent.
+///
public interface IAgentState
{
- ValueTask ReadStateAsync();
- ValueTask WriteStateAsync(AgentState state, string eTag);
+ ///
+ /// Reads the current state of the agent asynchronously.
+ ///
+ /// A token to cancel the operation.
+ /// A task that represents the asynchronous read operation. The task result contains the current state of the agent.
+ ValueTask ReadStateAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Writes the specified state of the agent asynchronously.
+ ///
+ /// The state to write.
+ /// The ETag for concurrency control.
+ /// A token to cancel the operation.
+ /// A task that represents the asynchronous write operation. The task result contains the ETag of the written state.
+ ValueTask WriteStateAsync(AgentState state, string eTag, CancellationToken cancellationToken = default);
}
diff --git a/dotnet/src/Microsoft.AutoGen/Agents/AgentBase.cs b/dotnet/src/Microsoft.AutoGen/Agents/AgentBase.cs
index 13b2e851969..345e6d34c82 100644
--- a/dotnet/src/Microsoft.AutoGen/Agents/AgentBase.cs
+++ b/dotnet/src/Microsoft.AutoGen/Agents/AgentBase.cs
@@ -93,7 +93,7 @@ protected internal async Task HandleRpcMessage(Message msg, CancellationToken ca
{
var activity = this.ExtractActivity(msg.CloudEvent.Type, msg.CloudEvent.Metadata);
await this.InvokeWithActivityAsync(
- static ((AgentBase Agent, CloudEvent Item) state) => state.Agent.CallHandler(state.Item),
+ static ((AgentBase Agent, CloudEvent Item) state, CancellationToken _) => state.Agent.CallHandler(state.Item),
(this, msg.CloudEvent),
activity,
msg.CloudEvent.Type, cancellationToken).ConfigureAwait(false);
@@ -103,7 +103,7 @@ await this.InvokeWithActivityAsync(
{
var activity = this.ExtractActivity(msg.Request.Method, msg.Request.Metadata);
await this.InvokeWithActivityAsync(
- static ((AgentBase Agent, RpcRequest Request) state) => state.Agent.OnRequestCoreAsync(state.Request),
+ static ((AgentBase Agent, RpcRequest Request) state, CancellationToken ct) => state.Agent.OnRequestCoreAsync(state.Request, ct),
(this, msg.Request),
activity,
msg.Request.Method, cancellationToken).ConfigureAwait(false);
@@ -142,8 +142,8 @@ public async Task StoreAsync(AgentState state, CancellationToken cancellationTok
}
public async Task ReadAsync(AgentId agentId, CancellationToken cancellationToken = default) where T : IMessage, new()
{
- var agentstate = await _context.ReadAsync(agentId, cancellationToken).ConfigureAwait(false);
- return agentstate.FromAgentState();
+ var agentState = await _context.ReadAsync(agentId, cancellationToken).ConfigureAwait(false);
+ return agentState.FromAgentState();
}
private void OnResponseCore(RpcResponse response)
{
@@ -195,9 +195,9 @@ protected async Task RequestAsync(AgentId target, string method, Di
activity?.SetTag("peer.service", target.ToString());
var completion = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
- _context.Update(activity, request);
+ _context.Update(request, activity);
await this.InvokeWithActivityAsync(
- static async ((AgentBase Agent, RpcRequest Request, TaskCompletionSource) state) =>
+ static async ((AgentBase Agent, RpcRequest Request, TaskCompletionSource) state, CancellationToken ct) =>
{
var (self, request, completion) = state;
@@ -206,7 +206,7 @@ static async ((AgentBase Agent, RpcRequest Request, TaskCompletionSource
+ static async ((AgentBase Agent, CloudEvent Event) state, CancellationToken ct) =>
{
- await state.Agent._context.PublishEventAsync(state.Event).ConfigureAwait(false);
+ await state.Agent._context.PublishEventAsync(state.Event, ct).ConfigureAwait(false);
},
(this, item),
activity,
diff --git a/dotnet/src/Microsoft.AutoGen/Agents/AgentBaseExtensions.cs b/dotnet/src/Microsoft.AutoGen/Agents/AgentBaseExtensions.cs
index ce1318a0d33..5d738e5fc38 100644
--- a/dotnet/src/Microsoft.AutoGen/Agents/AgentBaseExtensions.cs
+++ b/dotnet/src/Microsoft.AutoGen/Agents/AgentBaseExtensions.cs
@@ -5,15 +5,25 @@
namespace Microsoft.AutoGen.Agents;
+///
+/// Provides extension methods for the class.
+///
public static class AgentBaseExtensions
{
+ ///
+ /// Extracts an from the given agent and metadata.
+ ///
+ /// The agent from which to extract the activity.
+ /// The name of the activity.
+ /// The metadata containing trace information.
+ /// The extracted or null if extraction fails.
public static Activity? ExtractActivity(this AgentBase agent, string activityName, IDictionary metadata)
{
Activity? activity;
- (var traceParent, var traceState) = agent.Context.GetTraceIDandState(metadata);
+ var (traceParent, traceState) = agent.Context.GetTraceIdAndState(metadata);
if (!string.IsNullOrEmpty(traceParent))
{
- if (ActivityContext.TryParse(traceParent, traceState, isRemote: true, out ActivityContext parentContext))
+ if (ActivityContext.TryParse(traceParent, traceState, isRemote: true, out var parentContext))
{
// traceParent is a W3CId
activity = AgentBase.s_source.CreateActivity(activityName, ActivityKind.Server, parentContext);
@@ -33,12 +43,9 @@ public static class AgentBaseExtensions
var baggage = agent.Context.ExtractMetadata(metadata);
- if (baggage is not null)
+ foreach (var baggageItem in baggage)
{
- foreach (var baggageItem in baggage)
- {
- activity.AddBaggage(baggageItem.Key, baggageItem.Value);
- }
+ activity.AddBaggage(baggageItem.Key, baggageItem.Value);
}
}
}
@@ -49,7 +56,19 @@ public static class AgentBaseExtensions
return activity;
}
- public static async Task InvokeWithActivityAsync(this AgentBase agent, Func func, TState state, Activity? activity, string methodName, CancellationToken cancellationToken = default)
+
+ ///
+ /// Invokes a function asynchronously within the context of an .
+ ///
+ /// The type of the state parameter.
+ /// The agent invoking the function.
+ /// The function to invoke.
+ /// The state parameter to pass to the function.
+ /// The activity within which to invoke the function.
+ /// The name of the method being invoked.
+ /// A token to monitor for cancellation requests.
+ /// A task representing the asynchronous operation.
+ public static async Task InvokeWithActivityAsync(this AgentBase agent, Func func, TState state, Activity? activity, string methodName, CancellationToken cancellationToken = default)
{
if (activity is not null && activity.StartTimeUtc == default)
{
@@ -63,7 +82,7 @@ public static async Task InvokeWithActivityAsync(this AgentBase agent, F
try
{
- await func(state).ConfigureAwait(false);
+ await func(state, cancellationToken).ConfigureAwait(false);
if (activity is not null && activity.IsAllDataRequested)
{
activity.SetStatus(ActivityStatusCode.Ok);
diff --git a/dotnet/src/Microsoft.AutoGen/Agents/AgentRuntime.cs b/dotnet/src/Microsoft.AutoGen/Agents/AgentRuntime.cs
index fad372ce2f9..c36d456af32 100644
--- a/dotnet/src/Microsoft.AutoGen/Agents/AgentRuntime.cs
+++ b/dotnet/src/Microsoft.AutoGen/Agents/AgentRuntime.cs
@@ -15,7 +15,7 @@ internal sealed class AgentRuntime(AgentId agentId, IAgentWorker worker, ILogger
public ILogger Logger { get; } = logger;
public IAgentBase? AgentInstance { get; set; }
private DistributedContextPropagator DistributedContextPropagator { get; } = distributedContextPropagator;
- public (string?, string?) GetTraceIDandState(IDictionary metadata)
+ public (string?, string?) GetTraceIdAndState(IDictionary metadata)
{
DistributedContextPropagator.ExtractTraceIdAndState(metadata,
static (object? carrier, string fieldName, out string? fieldValue, out IEnumerable? fieldValues) =>
@@ -28,11 +28,11 @@ internal sealed class AgentRuntime(AgentId agentId, IAgentWorker worker, ILogger
out var traceState);
return (traceParent, traceState);
}
- public void Update(Activity? activity, RpcRequest request)
+ public void Update(RpcRequest request, Activity? activity = null)
{
DistributedContextPropagator.Inject(activity, request.Metadata, static (carrier, key, value) => ((IDictionary)carrier!)[key] = value);
}
- public void Update(Activity? activity, CloudEvent cloudEvent)
+ public void Update(CloudEvent cloudEvent, Activity? activity = null)
{
DistributedContextPropagator.Inject(activity, cloudEvent.Metadata, static (carrier, key, value) => ((IDictionary)carrier!)[key] = value);
}
diff --git a/dotnet/src/Microsoft.AutoGen/Agents/Agents/AIAgent/InferenceAgent.cs b/dotnet/src/Microsoft.AutoGen/Agents/Agents/AIAgent/InferenceAgent.cs
index a0383a3c219..bf68467e3fa 100644
--- a/dotnet/src/Microsoft.AutoGen/Agents/Agents/AIAgent/InferenceAgent.cs
+++ b/dotnet/src/Microsoft.AutoGen/Agents/Agents/AIAgent/InferenceAgent.cs
@@ -5,16 +5,14 @@
using Microsoft.AutoGen.Abstractions;
using Microsoft.Extensions.AI;
namespace Microsoft.AutoGen.Agents;
-public abstract class InferenceAgent : AgentBase where T : IMessage, new()
+public abstract class InferenceAgent(
+ IAgentRuntime context,
+ EventTypes typeRegistry,
+ IChatClient client)
+ : AgentBase(context, typeRegistry)
+ where T : IMessage, new()
{
- protected IChatClient ChatClient { get; }
- public InferenceAgent(
- IAgentRuntime context,
- EventTypes typeRegistry, IChatClient client
- ) : base(context, typeRegistry)
- {
- ChatClient = client;
- }
+ protected IChatClient ChatClient { get; } = client;
private Task CompleteAsync(
IList chatMessages,
diff --git a/dotnet/src/Microsoft.AutoGen/Agents/Services/Orleans/AgentStateGrain.cs b/dotnet/src/Microsoft.AutoGen/Agents/Services/Orleans/AgentStateGrain.cs
index 50d8c3ad454..9905f6aebac 100644
--- a/dotnet/src/Microsoft.AutoGen/Agents/Services/Orleans/AgentStateGrain.cs
+++ b/dotnet/src/Microsoft.AutoGen/Agents/Services/Orleans/AgentStateGrain.cs
@@ -7,7 +7,8 @@ namespace Microsoft.AutoGen.Agents;
internal sealed class AgentStateGrain([PersistentState("state", "AgentStateStore")] IPersistentState state) : Grain, IAgentState
{
- public async ValueTask WriteStateAsync(AgentState newState, string eTag)
+ ///
+ public async ValueTask WriteStateAsync(AgentState newState, string eTag, CancellationToken cancellationToken = default)
{
// etags for optimistic concurrency control
// if the Etag is null, its a new state
@@ -27,7 +28,8 @@ public async ValueTask WriteStateAsync(AgentState newState, string eTag)
return state.Etag;
}
- public ValueTask ReadStateAsync()
+ ///
+ public ValueTask ReadStateAsync(CancellationToken cancellationToken = default)
{
return ValueTask.FromResult(state.State);
}