semantic kernel exposing services using A2A (server and client)
Semantic kernel hasn't natively provide full support for A2A or atleast not proper yet So i am using these 2 libraries here to do all the hard work. There is no agent llm added in this post - you need to add in those code.
dotnet add package A2A
dotnet add package A2A.AspNetCore
The server side code
using A2A;
using A2A.AspNetCore;
using AgentServer;
var builder = WebApplication.CreateBuilder(args);
var baseUrl = "http://localhost:5000";
builder.Services.AddA2AAgent<EchoAgent>(EchoAgent.GetAgentCard($"{baseUrl}/echo"));
var agentType ="echo";
var app = builder.Build();
app.UseHttpsRedirection();
app.MapGet("/health", () => Results.Ok(new { Status = "Healthy", Timestamp = DateTimeOffset.UtcNow }));
// Map A2A endpoints using DI-registered services
var path = agentType.ToLowerInvariant() switch
{
"echo" => "/echo",
"echotasks" => "/echotasks",
"researcher" => "/researcher",
"speccompliance" => "/speccompliance",
_ => "/agent",
};
app.MapA2A(path);
// For spec compliance, also map at root for well-known agent card discovery
if (agentType.Equals("speccompliance", StringComparison.OrdinalIgnoreCase))
{
var card = app.Services.GetRequiredService<AgentCard>();
app.MapWellKnownAgentCard(card);
}
app.Run();
And you can view the your agent card here: http://localhost:5000/echo/.well-known/agent-card.json
The client side code - please create another project and then place this code in there. Be careful about the "/echo/" missing the slash can turn into a disaster :)
using A2A;
using System.Text.Json;
// 2. Create agent card resolver
A2ACardResolver agentCardResolver = new(new Uri("http://localhost:5000/echo/"));
// 3. Get agent card
AgentCard agentCard = await agentCardResolver.GetAgentCardAsync();
JsonSerializerOptions s_indentedOptions = new(A2AJsonUtilities.DefaultOptions)
{
WriteIndented = true
};
// 4. Display agent details
Console.WriteLine("\nAgent card details:");
Console.WriteLine(JsonSerializer.Serialize(agentCard, s_indentedOptions));
A2AClient agentClient = new(new Uri(agentCard.SupportedInterfaces[0].Url));
// 3. Create a message to send to the agent
Message userMessage = new()
{
Role = Role.User,
MessageId = Guid.NewGuid().ToString(),
Parts = [Part.FromText("Hello from the message-based communication sample! Please echo this message.")]
};
// 4. Send the message using non-streaming API
await EchoMessage.SendMessageAsync(agentClient, userMessage);
public class EchoMessage
{
public static async Task SendMessageAsync(A2AClient agentClient, Message userMessage)
{
Console.WriteLine("\nNon-Streaming Message Communication");
Console.WriteLine($" Sending message via non-streaming API: {userMessage.Parts[0].Text}");
// Send the message and get the response
SendMessageResponse response = await agentClient.SendMessageAsync(new SendMessageRequest { Message = userMessage });
// Display the response
Console.WriteLine($" Received complete response from agent: {response.Message!.Parts[0].Text}");
}
}
If all works successfully, then you will get this output
Comments