diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx
index 22460827ef..127b065220 100644
--- a/dotnet/agent-framework-dotnet.slnx
+++ b/dotnet/agent-framework-dotnet.slnx
@@ -289,6 +289,7 @@
+
diff --git a/dotnet/samples/02-agents/A2A/A2AAgent_ProtocolSelection/A2AAgent_ProtocolSelection.csproj b/dotnet/samples/02-agents/A2A/A2AAgent_ProtocolSelection/A2AAgent_ProtocolSelection.csproj
new file mode 100644
index 0000000000..d21ac952b3
--- /dev/null
+++ b/dotnet/samples/02-agents/A2A/A2AAgent_ProtocolSelection/A2AAgent_ProtocolSelection.csproj
@@ -0,0 +1,19 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/A2A/A2AAgent_ProtocolSelection/Program.cs b/dotnet/samples/02-agents/A2A/A2AAgent_ProtocolSelection/Program.cs
new file mode 100644
index 0000000000..4d1612ee36
--- /dev/null
+++ b/dotnet/samples/02-agents/A2A/A2AAgent_ProtocolSelection/Program.cs
@@ -0,0 +1,36 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+// This sample demonstrates how to select the A2A protocol binding (HTTP+JSON vs JSON-RPC) when
+// creating an AIAgent from an A2A agent card using A2AClientOptions.PreferredBindings.
+
+using A2A;
+using Microsoft.Agents.AI;
+
+var a2aAgentHost = Environment.GetEnvironmentVariable("A2A_AGENT_HOST") ?? throw new InvalidOperationException("A2A_AGENT_HOST is not set.");
+
+// Initialize an A2ACardResolver to get an A2A agent card.
+A2ACardResolver agentCardResolver = new(new Uri(a2aAgentHost));
+
+// Get the agent card
+AgentCard agentCard = await agentCardResolver.GetAgentCardAsync();
+
+// Use A2AClientOptions to explicitly select the HTTP+JSON protocol binding.
+// This tells the A2A client factory to prefer the HTTP+JSON interface when the agent card
+// advertises multiple supported interfaces.
+A2AClientOptions options = new()
+{
+ PreferredBindings = [ProtocolBindingNames.HttpJson]
+};
+
+// To prefer JSON-RPC instead, use:
+// A2AClientOptions options = new()
+// {
+// PreferredBindings = [ProtocolBindingNames.JsonRpc]
+// };
+
+// Create an instance of the AIAgent for an existing A2A agent, using the specified protocol binding.
+AIAgent agent = agentCard.AsAIAgent(options: options);
+
+// Invoke the agent and output the text result.
+AgentResponse response = await agent.RunAsync("Tell me a joke about a pirate.");
+Console.WriteLine(response);
diff --git a/dotnet/samples/02-agents/A2A/A2AAgent_ProtocolSelection/README.md b/dotnet/samples/02-agents/A2A/A2AAgent_ProtocolSelection/README.md
new file mode 100644
index 0000000000..b50a76240c
--- /dev/null
+++ b/dotnet/samples/02-agents/A2A/A2AAgent_ProtocolSelection/README.md
@@ -0,0 +1,27 @@
+# A2A Agent Protocol Selection
+
+This sample demonstrates how to select the A2A protocol binding when creating an `AIAgent` from an A2A agent card.
+
+A2A agents can expose multiple interfaces with different protocol bindings (e.g., HTTP+JSON, JSON-RPC). By default, `AsAIAgent()` prefers HTTP+JSON with JSON-RPC as a fallback. This sample shows how to use `A2AClientOptions.PreferredBindings` to explicitly control which protocol binding is used.
+
+The sample:
+
+- Connects to an A2A agent server specified in the `A2A_AGENT_HOST` environment variable
+- Configures `A2AClientOptions` to prefer the HTTP+JSON protocol binding
+- Creates an `AIAgent` from the resolved agent card using the specified binding
+- Sends a message to the agent and displays the response
+
+## Prerequisites
+
+Before you begin, ensure you have the following prerequisites:
+
+- .NET 10.0 SDK or later
+- An A2A agent server running and accessible via HTTP
+
+**Note**: These samples need to be run against a valid A2A server. If no A2A server is available, they can be run against the echo-agent that can be spun up locally by following the guidelines at: https://github.com/a2aproject/a2a-dotnet/blob/main/samples/AgentServer/README.md
+
+Set the following environment variable:
+
+```powershell
+$env:A2A_AGENT_HOST="http://localhost:5000" # Replace with your A2A agent server host
+```
diff --git a/dotnet/samples/02-agents/A2A/README.md b/dotnet/samples/02-agents/A2A/README.md
index 2f161748df..28f2c0a910 100644
--- a/dotnet/samples/02-agents/A2A/README.md
+++ b/dotnet/samples/02-agents/A2A/README.md
@@ -3,7 +3,7 @@
These samples demonstrate how to work with Agent-to-Agent (A2A) specific features in the Agent Framework.
For other samples that demonstrate how to use AIAgent instances,
-see the [Getting Started With Agents](../../02-agents/Agents/README.md) samples.
+see the [Getting Started With Agents](../Agents/README.md) samples.
## Prerequisites
@@ -16,6 +16,7 @@ See the README.md for each sample for the prerequisites for that sample.
|[A2A Agent As Function Tools](./A2AAgent_AsFunctionTools/)|This sample demonstrates how to represent an A2A agent as a set of function tools, where each function tool corresponds to a skill of the A2A agent, and register these function tools with another AI agent so it can leverage the A2A agent's skills.|
|[A2A Agent Polling For Task Completion](./A2AAgent_PollingForTaskCompletion/)|This sample demonstrates how to poll for long-running task completion using continuation tokens with an A2A agent.|
|[A2A Agent Stream Reconnection](./A2AAgent_StreamReconnection/)|This sample demonstrates how to reconnect to an A2A agent's streaming response using continuation tokens, allowing recovery from stream interruptions.|
+|[A2A Agent Protocol Selection](./A2AAgent_ProtocolSelection/)|This sample demonstrates how to select the A2A protocol binding (HTTP+JSON vs JSON-RPC) when creating an AIAgent from an A2A agent card using A2AClientOptions.|
## Running the samples from the console
diff --git a/dotnet/samples/02-agents/README.md b/dotnet/samples/02-agents/README.md
index 5ff0db416d..69f649c9b4 100644
--- a/dotnet/samples/02-agents/README.md
+++ b/dotnet/samples/02-agents/README.md
@@ -19,3 +19,4 @@ The getting started samples demonstrate the fundamental concepts and functionali
| [Declarative Agents](./DeclarativeAgents) | Loading and executing AI agents from YAML configuration files |
| [AG-UI](./AGUI/README.md) | Getting started with AG-UI (Agent UI Protocol) servers and clients |
| [Dev UI](./DevUI/README.md) | Interactive web interface for testing and debugging AI agents during development |
+| [A2A Agents](./A2A/README.md) | Working with Agent-to-Agent (A2A) specific features |
diff --git a/dotnet/src/Microsoft.Agents.AI.A2A/A2AAgent.cs b/dotnet/src/Microsoft.Agents.AI.A2A/A2AAgent.cs
index 6e11f0a2cc..9fd2e8ff47 100644
--- a/dotnet/src/Microsoft.Agents.AI.A2A/A2AAgent.cs
+++ b/dotnet/src/Microsoft.Agents.AI.A2A/A2AAgent.cs
@@ -27,7 +27,7 @@ public sealed class A2AAgent : AIAgent
{
private static readonly AIAgentMetadata s_agentMetadata = new("a2a");
- private readonly A2AClient _a2aClient;
+ private readonly IA2AClient _a2aClient;
private readonly string? _id;
private readonly string? _name;
private readonly string? _description;
@@ -41,7 +41,7 @@ public sealed class A2AAgent : AIAgent
/// The the name of the agent.
/// The description of the agent.
/// Optional logger factory to use for logging.
- public A2AAgent(A2AClient a2aClient, string? id = null, string? name = null, string? description = null, ILoggerFactory? loggerFactory = null)
+ public A2AAgent(IA2AClient a2aClient, string? id = null, string? name = null, string? description = null, ILoggerFactory? loggerFactory = null)
{
_ = Throw.IfNull(a2aClient);
@@ -224,7 +224,7 @@ protected override async IAsyncEnumerable RunCoreStreamingA
///
public override object? GetService(Type serviceType, object? serviceKey = null)
=> base.GetService(serviceType, serviceKey)
- ?? (serviceType == typeof(A2AClient) ? this._a2aClient
+ ?? (serviceType == typeof(IA2AClient) ? this._a2aClient
: serviceType == typeof(AIAgentMetadata) ? s_agentMetadata
: null);
diff --git a/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AAgentCardExtensions.cs b/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AAgentCardExtensions.cs
index 897349f666..086505b2bc 100644
--- a/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AAgentCardExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AAgentCardExtensions.cs
@@ -1,7 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.
-using System;
-using System.Linq;
using System.Net.Http;
using Microsoft.Agents.AI;
using Microsoft.Extensions.Logging;
@@ -26,16 +24,15 @@ public static class A2AAgentCardExtensions
///
/// The to use for the agent creation.
/// The to use for HTTP requests.
+ ///
+ /// Optional controlling protocol binding preference.
+ /// When not provided, defaults to preferring HTTP+JSON first, with JSON-RPC as fallback.
+ ///
/// The logger factory for enabling logging within the agent.
/// An instance backed by the A2A agent.
- public static AIAgent AsAIAgent(this AgentCard card, HttpClient? httpClient = null, ILoggerFactory? loggerFactory = null)
+ public static AIAgent AsAIAgent(this AgentCard card, HttpClient? httpClient = null, A2AClientOptions? options = null, ILoggerFactory? loggerFactory = null)
{
- // TODO: Refactor to support interface selection from card.SupportedInterfaces.
- var url = card.SupportedInterfaces?.FirstOrDefault()?.Url
- ?? throw new InvalidOperationException("The AgentCard does not have any SupportedInterfaces with a URL.");
-
- // Create the A2A client using the agent URL from the card.
- var a2aClient = new A2AClient(new Uri(url), httpClient);
+ var a2aClient = A2AClientFactory.Create(card, httpClient, options);
return a2aClient.AsAIAgent(name: card.Name, description: card.Description, loggerFactory: loggerFactory);
}
diff --git a/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2ACardResolverExtensions.cs b/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2ACardResolverExtensions.cs
index 6a32822fea..49b6de1102 100644
--- a/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2ACardResolverExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2ACardResolverExtensions.cs
@@ -34,14 +34,18 @@ public static class A2ACardResolverExtensions
///
/// The to use for the agent creation.
/// The to use for HTTP requests.
+ ///
+ /// Optional controlling protocol binding preference.
+ /// When not provided, defaults to preferring HTTP+JSON first, with JSON-RPC as fallback.
+ ///
/// The logger factory for enabling logging within the agent.
/// The to monitor for cancellation requests. The default is .
/// An instance backed by the A2A agent.
- public static async Task GetAIAgentAsync(this A2ACardResolver resolver, HttpClient? httpClient = null, ILoggerFactory? loggerFactory = null, CancellationToken cancellationToken = default)
+ public static async Task GetAIAgentAsync(this A2ACardResolver resolver, HttpClient? httpClient = null, A2AClientOptions? options = null, ILoggerFactory? loggerFactory = null, CancellationToken cancellationToken = default)
{
// Obtain the agent card from the resolver.
var agentCard = await resolver.GetAgentCardAsync(cancellationToken).ConfigureAwait(false);
- return agentCard.AsAIAgent(httpClient, loggerFactory);
+ return agentCard.AsAIAgent(httpClient, options, loggerFactory);
}
}
diff --git a/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AClientExtensions.cs b/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AClientExtensions.cs
index cd93ca0bac..c7386309d3 100644
--- a/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AClientExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AClientExtensions.cs
@@ -7,7 +7,7 @@
namespace A2A;
///
-/// Provides extension methods for
+/// Provides extension methods for
/// to simplify the creation of A2A agents.
///
///
@@ -29,12 +29,12 @@ public static class A2AClientExtensions
/// Direct Configuration / Private Discovery
/// discovery mechanism.
///
- /// The to use for the agent.
+ /// The to use for the agent.
/// The unique identifier for the agent.
/// The the name of the agent.
/// The description of the agent.
/// Optional logger factory for enabling logging within the agent.
/// An instance backed by the A2A agent.
- public static AIAgent AsAIAgent(this A2AClient client, string? id = null, string? name = null, string? description = null, ILoggerFactory? loggerFactory = null) =>
+ public static AIAgent AsAIAgent(this IA2AClient client, string? id = null, string? name = null, string? description = null, ILoggerFactory? loggerFactory = null) =>
new A2AAgent(client, id, name, description, loggerFactory);
}
diff --git a/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/A2AAgentTests.cs b/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/A2AAgentTests.cs
index 4ae09e8f5a..320b5b030c 100644
--- a/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/A2AAgentTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/A2AAgentTests.cs
@@ -55,6 +55,21 @@ public void Constructor_WithNullA2AClient_ThrowsArgumentNullException() =>
// Act & Assert
Assert.Throws(() => new A2AAgent(null!));
+ [Fact]
+ public void Constructor_WithIA2AClient_InitializesCorrectly()
+ {
+ // Arrange
+ IA2AClient ia2aClient = this._a2aClient;
+
+ // Act
+ var agent = new A2AAgent(ia2aClient, "ia2a-id", "IA2A Agent", "An agent from IA2AClient");
+
+ // Assert
+ Assert.Equal("ia2a-id", agent.Id);
+ Assert.Equal("IA2A Agent", agent.Name);
+ Assert.Equal("An agent from IA2AClient", agent.Description);
+ }
+
[Fact]
public void Constructor_WithDefaultParameters_UsesBaseProperties()
{
@@ -1371,19 +1386,33 @@ public async Task RunStreamingAsync_WithInvalidSessionType_ThrowsInvalidOperatio
#region GetService Method Tests
///
- /// Verify that GetService returns A2AClient when requested.
+ /// Verify that GetService returns IA2AClient when requested.
///
[Fact]
- public void GetService_RequestingA2AClient_ReturnsA2AClient()
+ public void GetService_RequestingIA2AClient_ReturnsA2AClient()
{
// Arrange & Act
- var result = this._agent.GetService(typeof(A2AClient));
+ var result = this._agent.GetService(typeof(IA2AClient));
// Assert
Assert.NotNull(result);
Assert.Same(this._a2aClient, result);
}
+ ///
+ /// Verify that GetService returns null when requesting the concrete A2AClient type
+ /// since the agent now exposes IA2AClient instead.
+ ///
+ [Fact]
+ public void GetService_RequestingConcreteA2AClient_ReturnsNull()
+ {
+ // Arrange & Act
+ var result = this._agent.GetService(typeof(A2AClient));
+
+ // Assert
+ Assert.Null(result);
+ }
+
///
/// Verify that GetService returns AIAgentMetadata when requested.
///
@@ -1458,10 +1487,10 @@ public void GetService_RequestingAIAgentType_ReturnsBaseImplementation()
/// Verify that GetService calls base.GetService() first but continues to derived logic when base returns null.
///
[Fact]
- public void GetService_RequestingA2AClientWithServiceKey_CallsBaseFirstThenDerivedLogic()
+ public void GetService_RequestingIA2AClientWithServiceKey_CallsBaseFirstThenDerivedLogic()
{
- // Arrange & Act - Request A2AClient with a service key (base.GetService will return null due to serviceKey)
- var result = this._agent.GetService(typeof(A2AClient), "some-key");
+ // Arrange & Act - Request IA2AClient with a service key (base.GetService will return null due to serviceKey)
+ var result = this._agent.GetService(typeof(IA2AClient), "some-key");
// Assert
Assert.NotNull(result);
diff --git a/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AAgentCardExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AAgentCardExtensionsTests.cs
index b45c381bd2..603376b396 100644
--- a/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AAgentCardExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AAgentCardExtensionsTests.cs
@@ -57,7 +57,7 @@ public async Task RunIAgentAsync_SendsRequestToTheUrlSpecifiedInAgentCardAsync()
Parts = [Part.FromText("Response")],
});
- var agent = this._agentCard.AsAIAgent(httpClient);
+ var agent = this._agentCard.AsAIAgent(httpClient: httpClient);
// Act
await agent.RunAsync("Test input");
@@ -68,7 +68,7 @@ public async Task RunIAgentAsync_SendsRequestToTheUrlSpecifiedInAgentCardAsync()
}
[Fact]
- public async Task AsAIAgent_WithMultipleInterfaces_UsesFirstInterfaceAsync()
+ public async Task AsAIAgent_WithPreferredBindings_UsesMatchingInterfaceAsync()
{
// Arrange
var card = new AgentCard
@@ -77,9 +77,8 @@ public async Task AsAIAgent_WithMultipleInterfaces_UsesFirstInterfaceAsync()
Description = "An agent with multiple interfaces",
SupportedInterfaces =
[
- new AgentInterface { Url = "http://first/agent" },
- new AgentInterface { Url = "http://second/agent", ProtocolBinding = "grpc" },
- new AgentInterface { Url = "http://third/agent", ProtocolBinding = "http" },
+ new AgentInterface { Url = "http://first/agent", ProtocolBinding = ProtocolBindingNames.HttpJson },
+ new AgentInterface { Url = "http://second/agent", ProtocolBinding = ProtocolBindingNames.JsonRpc },
]
};
@@ -92,14 +91,79 @@ public async Task AsAIAgent_WithMultipleInterfaces_UsesFirstInterfaceAsync()
Parts = [Part.FromText("Response")],
});
- var agent = card.AsAIAgent(httpClient);
+ var options = new A2AClientOptions
+ {
+ PreferredBindings = [ProtocolBindingNames.JsonRpc]
+ };
+
+ var agent = card.AsAIAgent(httpClient, options: options);
// Act
await agent.RunAsync("Test input");
// Assert
Assert.Single(handler.CapturedUris);
- Assert.Equal(new Uri("http://first/agent"), handler.CapturedUris[0]);
+ Assert.Equal(new Uri("http://second/agent"), handler.CapturedUris[0]);
+ }
+
+ [Fact]
+ public void AsAIAgent_WithNullOptions_UsesDefaultBindingPreference()
+ {
+ // Arrange
+ var card = new AgentCard
+ {
+ Name = "Default Options Agent",
+ Description = "Tests default A2AClientOptions behavior",
+ SupportedInterfaces =
+ [
+ new AgentInterface { Url = "http://default/agent" },
+ ]
+ };
+
+ // Act - null options should use defaults (HTTP+JSON first, JSON-RPC as fallback)
+ var agent = card.AsAIAgent(options: null);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.IsType(agent);
+ Assert.Equal("Default Options Agent", agent.Name);
+ }
+
+ [Fact]
+ public void AsAIAgent_WithNoMatchingBinding_ThrowsException()
+ {
+ // Arrange
+ var card = new AgentCard
+ {
+ Name = "Unmatched Binding Agent",
+ Description = "Agent with unsupported binding only",
+ SupportedInterfaces =
+ [
+ new AgentInterface { Url = "http://grpc/agent", ProtocolBinding = "GRPC" },
+ ]
+ };
+
+ var options = new A2AClientOptions
+ {
+ PreferredBindings = [ProtocolBindingNames.JsonRpc]
+ };
+
+ // Act & Assert - factory should throw when no matching binding exists
+ Assert.ThrowsAny(() => card.AsAIAgent(options: options));
+ }
+
+ [Fact]
+ public void AsAIAgent_WithNoSupportedInterfaces_ThrowsException()
+ {
+ // Arrange
+ var card = new AgentCard
+ {
+ Name = "No Interfaces Agent",
+ Description = "Agent with no supported interfaces",
+ };
+
+ // Act & Assert
+ Assert.ThrowsAny(() => card.AsAIAgent());
}
internal sealed class HttpMessageHandlerStub : HttpMessageHandler
diff --git a/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2ACardResolverExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2ACardResolverExtensionsTests.cs
index 95cb2a67d2..8a664b7fc9 100644
--- a/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2ACardResolverExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2ACardResolverExtensionsTests.cs
@@ -68,7 +68,7 @@ public async Task RunIAgentAsync_WithUrlFromAgentCard_SendsRequestToTheUrlAsync(
Parts = [Part.FromText("Response")],
});
- var agent = await this._resolver.GetAIAgentAsync(this._httpClient);
+ var agent = await this._resolver.GetAIAgentAsync(httpClient: this._httpClient);
// Act
await agent.RunAsync("Test input");
@@ -78,6 +78,41 @@ public async Task RunIAgentAsync_WithUrlFromAgentCard_SendsRequestToTheUrlAsync(
Assert.Equal(new Uri("http://test-endpoint/agent"), this._handler.CapturedUris[1]);
}
+ [Fact]
+ public async Task GetAIAgentAsync_WithOptions_PassesOptionsToFactoryAsync()
+ {
+ // Arrange
+ this._handler.ResponsesToReturn.Enqueue(new AgentCard
+ {
+ Name = "Options Agent",
+ Description = "Agent with multiple interfaces",
+ SupportedInterfaces =
+ [
+ new AgentInterface { Url = "http://httpjson/agent", ProtocolBinding = ProtocolBindingNames.HttpJson },
+ new AgentInterface { Url = "http://jsonrpc/agent", ProtocolBinding = ProtocolBindingNames.JsonRpc },
+ ]
+ });
+ this._handler.ResponsesToReturn.Enqueue(new Message
+ {
+ Role = Role.Agent,
+ Parts = [Part.FromText("Response")],
+ });
+
+ var options = new A2AClientOptions
+ {
+ PreferredBindings = [ProtocolBindingNames.JsonRpc]
+ };
+
+ var agent = await this._resolver.GetAIAgentAsync(httpClient: this._httpClient, options: options);
+
+ // Act
+ await agent.RunAsync("Test input");
+
+ // Assert
+ Assert.Equal(2, this._handler.CapturedUris.Count);
+ Assert.Equal(new Uri("http://jsonrpc/agent"), this._handler.CapturedUris[1]);
+ }
+
public void Dispose()
{
this._handler.Dispose();
diff --git a/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AClientExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AClientExtensionsTests.cs
index 9ad4d982a9..80b5107bf1 100644
--- a/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AClientExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AClientExtensionsTests.cs
@@ -30,4 +30,40 @@ public void GetAIAgent_WithAllParameters_ReturnsA2AAgentWithSpecifiedProperties(
Assert.Equal(TestName, agent.Name);
Assert.Equal(TestDescription, agent.Description);
}
+
+ [Fact]
+ public void GetAIAgent_WithIA2AClient_ReturnsA2AAgentWithSpecifiedProperties()
+ {
+ // Arrange - use IA2AClient reference type to verify the extension method works with the interface
+ IA2AClient a2aClient = new A2AClient(new Uri("http://test-endpoint"));
+
+ const string TestId = "ia2a-agent-id";
+ const string TestName = "IA2A Agent";
+ const string TestDescription = "Agent created from IA2AClient";
+
+ // Act
+ var agent = a2aClient.AsAIAgent(TestId, TestName, TestDescription);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.IsType(agent);
+ Assert.Equal(TestId, agent.Id);
+ Assert.Equal(TestName, agent.Name);
+ Assert.Equal(TestDescription, agent.Description);
+ }
+
+ [Fact]
+ public void GetAIAgent_WithIA2AClient_ExposesClientViaGetService()
+ {
+ // Arrange
+ IA2AClient a2aClient = new A2AClient(new Uri("http://test-endpoint"));
+
+ // Act
+ var agent = a2aClient.AsAIAgent();
+
+ // Assert
+ var service = agent.GetService(typeof(IA2AClient));
+ Assert.NotNull(service);
+ Assert.Same(a2aClient, service);
+ }
}