Wednesday, February 25, 2026

Explore A2A protocol with .NET and GitHub Models

Let's explore the Agent-to-Agent (A2A) protocol using .NET. The A2A protocol standardizes communication between agents. It allows agents built with different frameworks and technologies to seamlesssly communicate with one-another.

What's A2A?

A2A is a standardized protocol that supports:

  • Agent discovery through agent cards
  • Message-based communication between agents
  • Long-running agentic processes via tasks
  • Cross-platform interoperability between different agent frameworks

The A2A protocol was developed by Google and later donated to the Linux Foundation.For more information, visit A2A protocol specification.

Source Code: https://github.com/medhatelmasry/A2Aapi

Get Started

In the following example, we will learn how to expose an agent with A2A. The example uses an AI model hosted on GitHub. In addition, we will use Swagger to simplify testing.

In a working directory on your computer, create an ASP.NET Minimal API project named A2Aapi with the following terminal window command:

dotnet new webapi -o A2Aapi
cd A2Aapi
dotnet new gitignore

Install the following NuGet packages:

# Hosting.A2A.AspNetCore for A2A protocol integration
dotnet add package Microsoft.Agents.AI.Hosting.A2A.AspNetCore -v 1.0.0-preview.260219.1

# Libraries to connect to GitHub AI models
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.AI.OpenAI

# Swagger to test app
dotnet add package Microsoft.AspNetCore.OpenApi
dotnet add package Swashbuckle.AspNetCore


Configure connection to GitHub AI Models

You will need to get a Personal Access Token from GitHub. If this is the first time, follow this tutorial.

Add the following JSON to appsettings.Development.json file:

"GitHub": {
    "Token": "put-your-github-personal-access-token-here",
    "ApiEndpoint": "https://models.github.ai/inference",
    "Model": "openai/gpt-4o-mini"
}

NOTE: Replace put-your-github-personal-access-token-here with your GitHub Personal Access Token.

Edit the .gitignore file in the A2Aapi folder and add to it appsettings.Development.json so that your secrets do not find their way into source control by mistake.

Replace contents of Program.cs with the following code:

using OpenAI;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Extensions.AI;
using Azure;
using OpenAI.Chat;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi();
builder.Services.AddSwaggerGen();

string githubToken = builder.Configuration["GitHub:Token"]
    ?? throw new InvalidOperationException("GitHub:Token is not set.");
string apiEndpoint = builder.Configuration["GitHub:ApiEndpoint"]
    ?? throw new InvalidOperationException("GitHub:ApiEndpoint is not set.");
string model = builder.Configuration["GitHub:Model"]
    ?? throw new InvalidOperationException("GitHub:Model is not set.");

// Register the chat client
IChatClient chatClient = new ChatClient(
    model,
    new AzureKeyCredential(githubToken),
    new OpenAIClientOptions
    {
        Endpoint = new Uri(apiEndpoint)
    }
)
.AsIChatClient();

builder.Services.AddSingleton(chatClient);

// Register agents
var pirateAgent = builder.AddAIAgent("pirate", instructions: "You are a pirate. Speak like a pirate.");

var app = builder.Build();

app.MapOpenApi();
app.UseSwagger();
app.UseSwaggerUI();

// Expose the agent via A2A protocol. You can also customize the agentCard
app.MapA2A(pirateAgent, path: "/a2a/pirate", agentCard: new()
{
    Name = "Pirate Agent",
    Description = "An agent that speaks like a pirate.",
    Version = "1.0"
});

app.Run();


Test Agent

Run the web app with:

dotnet run

We have two options to test our agent: we can either use Swallger by pointing our browser to the /swagger endpoint, or we can use the A2Aapi.http REST Client that is built into the ASP.NET Minimal API template.

Option 1 - using Swagger

Point your browser to the URL displayed the the terminal window with /swagger. In my case it would be http://localhost:5112/swagger. You will see an interface similar to this:

Cloose the POST /a2a/pirate/v1/message:stream endpoint.

Click on the "Try it out" 

Enter the following JSON request then click on the Execute button:
{
  "message": {
    "kind": "message",
    "role": "user",
    "parts": [
      {
        "kind": "text",
        "text": "Hey pirate! Tell me where have you been",
        "metadata": {}
      }
    ],
    "messageId": null,
    "contextId": "foo"
  }
}

The server response looks like this:

This is the prompt we sent to the agent:

Hey pirate! Tell me where have you been

This is the response from the agent:

Ahoy, matey! I've been sailin' the seven seas, searchin' fer treasure and chasin' down the fiercest storms!

From the shores of Tortuga to the depths of Davy Jones' locker, me heart be filled with tales of adventure. And where be ye anchorin" yer ship, eh?

The response includes the contextId (conversation identifier), messageId (message identifier), and the actual content from the pirate agent.

Option 2 - using .http REST Client

If you are using VS Code, install the following VS Code extension:


Edit the A2Aapi.http in your project and add this request:
###
# Send A2A request to the pirate agent
POST {{A2Aapi_HostAddress}}/a2a/pirate/v1/message:stream
Accept: application/json
Content-Type: application/json

{
  "message": {
    "kind": "message",
    "role": "user",
    "parts": [
      {
        "kind": "text",
        "text": "Hey pirate! Tell me where have you been",
        "metadata": {}
      }
    ],
    "messageId": null,
    "contextId": "foo"
  }
}

Click on the "Send Request" link as shown below:

The response will show in a separate panel like this:

AgentCard Configuration

The AgentCard provides metadata about your agent for discovery and integration:

app.MapA2A(agent, "/a2a/my-agent", agentCard: new() {
   Name = "My Agent",
   Description = "A helpful agent that assists with tasks.",
   Version = "1.0",
});

The agent card can be accessed by sending this request:

# Send A2A request to the pirate agent
GET {{baseAddress}}/a2a/pirate/v1/card


Properties of the Agent Card

NameDisplay name of the agent
DescriptionBrief description of the agent
VersionVersion string for the agent
UrlEndpoint URL (automatically assigned if not specified)
CapabilitiesOptional metadata about streaming, push notifications, and other features


Exposing More Agents

You can expose multiple agents in a single application, as long as their endpoints don't collide. Here's an example:

Add the following code to Program.cs right under the "// Register agents" comment line:

var mathAgent = builder.AddAIAgent("math", instructions: "You are a math expert.");
var scienceAgent = builder.AddAIAgent("science", instructions: "You are a science expert.");

Similarly, add these endpoint mappings to Program.cs right above the last "app.Run();" statement:

app.MapA2A(mathAgent, "/a2a/math");
app.MapA2A(scienceAgent, "/a2a/science");

You can test the math agent and science agents with these respective requests:

Test math agent

###
# Send A2A request to the math agent
POST {{A2Aapi_HostAddress}}/a2a/math/v1/message:stream
Accept: application/json
Content-Type: application/json

{
  "message": {
    "kind": "message",
    "role": "user",
    "parts": [
      {
        "kind": "text",
        "text": "add 2 and 7",
        "metadata": {}
      }
    ],
    "messageId": null,
    "contextId": null
  }
}


Test science agent

###
# Send A2A request to the science agent
POST {{A2Aapi_HostAddress}}/a2a/science/v1/message:stream
Accept: application/json
Content-Type: application/json

{
  "message": {
    "kind": "message",
    "role": "user",
    "parts": [
      {
        "kind": "text",
        "text": "how far is saturn from earth?",
        "metadata": {}
      }
    ],
    "messageId": null,
    "contextId": null
  }
}


Conclusion

Therea re many emerging protocols that are giving us an insight into the future landscapte of the Agentic AI world o the future. This is one amone others. I trust that is article gives you in insight into the significance of the A2A protocol.

References

A2A Integration

Agent2Agent (A2A) Protocol

No comments:

Post a Comment