diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Program.cs b/dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Program.cs
index ab71949751..ff0c8df71f 100644
--- a/dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Program.cs
+++ b/dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Program.cs
@@ -94,8 +94,8 @@ app.UseExceptionHandler();
app.MapActors();
// attach a2a with simple message communication
-app.AttachA2A(agentName: "pirate", path: "/a2a/pirate");
-app.AttachA2A(agentName: "knights-and-knaves", path: "/a2a/knights-and-knaves", agentCard: new()
+app.MapA2A(agentName: "pirate", path: "/a2a/pirate");
+app.MapA2A(agentName: "knights-and-knaves", path: "/a2a/knights-and-knaves", agentCard: new()
{
Name = "Knights and Knaves",
Description = "An agent that helps you solve the knights and knaves puzzle.",
diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.A2A.AspNetCore/WebApplicationExtensions.cs b/dotnet/src/Microsoft.Agents.AI.Hosting.A2A.AspNetCore/WebApplicationExtensions.cs
index e1642b5a9f..3b9d21ac5d 100644
--- a/dotnet/src/Microsoft.Agents.AI.Hosting.A2A.AspNetCore/WebApplicationExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Hosting.A2A.AspNetCore/WebApplicationExtensions.cs
@@ -20,14 +20,14 @@ public static class WebApplicationExtensions
/// The web application used to configure the pipeline and routes.
/// The name of the agent to use for A2A protocol integration.
/// The route group to use for A2A endpoints.
- public static void AttachA2A(this WebApplication app, string agentName, string path)
+ public static void MapA2A(this WebApplication app, string agentName, string path)
{
var agent = app.Services.GetRequiredKeyedService(agentName);
var loggerFactory = app.Services.GetRequiredService();
var actorClient = app.Services.GetRequiredService();
- var taskManager = agent.AttachA2A(actorClient, loggerFactory: loggerFactory);
- app.AttachA2A(taskManager, path);
+ var taskManager = agent.MapA2A(actorClient, loggerFactory: loggerFactory);
+ app.MapA2A(taskManager, path);
}
///
@@ -37,7 +37,7 @@ public static class WebApplicationExtensions
/// The name of the agent to use for A2A protocol integration.
/// The route group to use for A2A endpoints.
/// Agent card info to return on query.
- public static void AttachA2A(
+ public static void MapA2A(
this WebApplication app,
string agentName,
string path,
@@ -47,8 +47,8 @@ public static class WebApplicationExtensions
var loggerFactory = app.Services.GetRequiredService();
var actorClient = app.Services.GetRequiredService();
- var taskManager = agent.AttachA2A(actorClient, agentCard: agentCard, loggerFactory: loggerFactory);
- app.AttachA2A(taskManager, path);
+ var taskManager = agent.MapA2A(actorClient, agentCard: agentCard, loggerFactory: loggerFactory);
+ app.MapA2A(taskManager, path);
}
///
@@ -58,7 +58,7 @@ public static class WebApplicationExtensions
/// The web application used to configure the pipeline and routes.
/// Pre-configured A2A TaskManager to use for A2A endpoints handling.
/// The route group to use for A2A endpoints.
- public static void AttachA2A(this WebApplication app, TaskManager taskManager, string path)
+ public static void MapA2A(this WebApplication app, TaskManager taskManager, string path)
{
// note: current SDK version registers multiple `.well-known/agent.json` handlers here.
// it makes app return HTTP 500, but will be fixed once new A2A SDK is released.
diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/AIAgentExtensions.cs b/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/AIAgentExtensions.cs
index 2f46df2be1..2de1200a49 100644
--- a/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/AIAgentExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/AIAgentExtensions.cs
@@ -22,13 +22,14 @@ public static class AIAgentExtensions
/// Instance of to configure for A2A messaging. New instance will be created if not passed.
/// The logger factory to use for creating instances.
/// The configured .
- public static TaskManager AttachA2A(
+ public static TaskManager MapA2A(
this AIAgent agent,
IActorClient actorClient,
TaskManager? taskManager = null,
ILoggerFactory? loggerFactory = null)
{
ArgumentNullException.ThrowIfNull(agent, nameof(agent));
+ ArgumentNullException.ThrowIfNull(agent.Name, nameof(agent.Name));
ArgumentNullException.ThrowIfNull(actorClient, nameof(actorClient));
taskManager ??= new();
@@ -49,14 +50,14 @@ public static class AIAgentExtensions
/// Instance of to configure for A2A messaging. New instance will be created if not passed.
/// The logger factory to use for creating instances.
/// The configured .
- public static TaskManager AttachA2A(
+ public static TaskManager MapA2A(
this AIAgent agent,
IActorClient actorClient,
AgentCard agentCard,
TaskManager? taskManager = null,
ILoggerFactory? loggerFactory = null)
{
- taskManager = agent.AttachA2A(actorClient, taskManager, loggerFactory);
+ taskManager = agent.MapA2A(actorClient, taskManager, loggerFactory);
taskManager.OnAgentCardQuery += (context, query) =>
{
diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/Converters/ActorEntitiesConverter.cs b/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/Converters/ActorEntitiesConverter.cs
index 8e7cead201..e20f43cf22 100644
--- a/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/Converters/ActorEntitiesConverter.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/Converters/ActorEntitiesConverter.cs
@@ -10,18 +10,13 @@ namespace Microsoft.Agents.AI.Hosting.A2A.Converters;
internal static class ActorEntitiesConverter
{
- public static Message ToMessage(this ActorResponse response)
+ public static Message ToMessage(this AgentRunResponse response, string contextId)
{
- var agentRunResponse =
- response.Data.Deserialize(AgentHostingJsonUtilities.DefaultOptions.GetTypeInfo(typeof(AgentRunResponse))) as AgentRunResponse ??
- throw new ArgumentException("The ActorResponse data could not be deserialized to an AgentRunResponse.", nameof(response));
-
- var contextId = response.ActorId.Key;
- var parts = agentRunResponse.Messages.ToParts();
+ var parts = response.Messages.ToParts();
return new Message
{
- MessageId = response.MessageId ?? Guid.NewGuid().ToString("N"),
+ MessageId = response.ResponseId ?? Guid.NewGuid().ToString("N"),
ContextId = contextId,
Role = MessageRole.Agent,
Parts = parts
diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/Internal/A2AAgentWrapper.cs b/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/Internal/A2AAgentWrapper.cs
index a0b361ca62..f9a9f7387a 100644
--- a/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/Internal/A2AAgentWrapper.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/Internal/A2AAgentWrapper.cs
@@ -1,13 +1,13 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
-using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using A2A;
using Microsoft.Agents.AI.Hosting.A2A.Converters;
using Microsoft.Agents.AI.Runtime;
using Microsoft.Extensions.Logging;
+using Microsoft.Shared.Diagnostics;
namespace Microsoft.Agents.AI.Hosting.A2A.Internal;
@@ -16,51 +16,26 @@ namespace Microsoft.Agents.AI.Hosting.A2A.Internal;
///
internal sealed class A2AAgentWrapper
{
- private readonly AIAgent _innerAgent;
- private readonly IActorClient _actorClient;
+ private readonly AgentProxy _agentProxy;
public A2AAgentWrapper(
IActorClient actorClient,
AIAgent innerAgent,
ILoggerFactory? loggerFactory = null)
{
- this._actorClient = actorClient;
- this._innerAgent = innerAgent ?? throw new ArgumentNullException(nameof(innerAgent));
+ Throw.IfNullOrEmpty(innerAgent.Name);
+
+ this._agentProxy = new AgentProxy(innerAgent.Name, actorClient);
}
public async Task ProcessMessageAsync(MessageSendParams messageSendParams, CancellationToken cancellationToken)
{
var contextId = messageSendParams.Message.ContextId ?? Guid.NewGuid().ToString("N");
- var messageId = messageSendParams.Message.MessageId;
-
- var actorId = new ActorId(type: this.GetActorType(), key: contextId!);
-
- // Verify request does not exist already
- var existingResponseHandle = await this._actorClient.GetResponseAsync(actorId, messageId, cancellationToken).ConfigureAwait(false);
- var existingResponse = await existingResponseHandle.GetResponseAsync(cancellationToken).ConfigureAwait(false);
- if (existingResponse.Status is RequestStatus.Completed or RequestStatus.Failed)
- {
- return existingResponse.ToMessage();
- }
-
- // here we know we did not yet send the request, so lets do it
var chatMessages = messageSendParams.ToChatMessages();
- var runRequest = new AgentRunRequest
- {
- Messages = chatMessages
- };
- var @params = JsonSerializer.SerializeToElement(runRequest, AgentHostingJsonUtilities.DefaultOptions.GetTypeInfo(typeof(AgentRunRequest)));
- var requestHandle = await this._actorClient.SendRequestAsync(new ActorRequest(actorId, messageId, method: "Run" /* ?refer to const here? */, @params: @params), cancellationToken).ConfigureAwait(false);
- var response = await requestHandle.GetResponseAsync(cancellationToken).ConfigureAwait(false);
+ var thread = this._agentProxy.GetNewThread(contextId);
+ var response = await this._agentProxy.RunAsync(messages: chatMessages, thread: thread, options: null, cancellationToken: cancellationToken).ConfigureAwait(false);
- return response.ToMessage();
- }
-
- private ActorType GetActorType()
- {
- // agent is registered in DI via name
- ArgumentException.ThrowIfNullOrEmpty(this._innerAgent.Name);
- return new ActorType(this._innerAgent.Name);
+ return response.ToMessage(contextId);
}
}
diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/Microsoft.Agents.AI.Hosting.A2A.csproj b/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/Microsoft.Agents.AI.Hosting.A2A.csproj
index 138cb8d9f5..3d343577f2 100644
--- a/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/Microsoft.Agents.AI.Hosting.A2A.csproj
+++ b/dotnet/src/Microsoft.Agents.AI.Hosting.A2A/Microsoft.Agents.AI.Hosting.A2A.csproj
@@ -8,6 +8,10 @@
alpha
+
+ true
+
+