A2A Agent Server
Overview
The A2A Agent Server is the core component that hosts individual agents as HTTP services. It provides REST API endpoints for agent interaction, manages agent lifecycle, and handles request routing.
Building an Agent Server
Step 1: Create Your Agent
Define your agent's behavior and capabilities:
csharp
using A2A;
using LlmTornado.Agents;
using LlmTornado.Agents.ChatRuntime;
using LlmTornado.Agents.ChatRuntime.RuntimeConfigurations;
using LlmTornado.Chat.Models;
namespace LlmTornado.A2A.AgentServer;
public class A2ATornadoAgentSample
{
TornadoAgent Agent;
TornadoApi Client;
public A2ATornadoAgentSample()
{
Client = new TornadoApi(LlmTornado.Code.LLmProviders.OpenAi, Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? "");
string instructions = @"
You are an expert assistant designed to help users with a variety of tasks.
You can perform tasks such as answering questions, providing recommendations, and assisting with problem-solving.
You should always strive to provide accurate and helpful information to the user.
";
Agent = new TornadoAgent(
client: Client,
model: ChatModel.OpenAi.Gpt5.V5,
name: "Assistant",
instructions: instructions,
streaming: true);
}
public BaseA2ATornadoRuntimeConfiguration Build()
{
IRuntimeConfiguration runtimeConfig = new SingletonRuntimeConfiguration(Agent); //Add your Runtime Configuration here
return new SampleRuntimeConfiguration(
runtimeConfig: runtimeConfig,
name: "LlmTornado.A2A.AgentServer", //Name of your agent server
version: "1.0.0" //Version of your agent server
);
}
}
/// <summary>
/// Define the Agent Capabilities here
/// </summary>
public class SampleRuntimeConfiguration : BaseA2ATornadoRuntimeConfiguration
{
/// <summary>
/// Initializes a new instance of the A2ATornadoRuntimeService
/// </summary>
public SampleRuntimeConfiguration(IRuntimeConfiguration runtimeConfig, string name, string version) : base(runtimeConfig, name, version) { }
/// <summary>
/// Defines a static Agent Card for the agent
/// </summary>
/// <returns></returns>
public override AgentCard DescribeAgentCard(string agentUrl)
{
AgentCapabilities capabilities = new AgentCapabilities()
{
Streaming = true,
PushNotifications = false,
};
AgentSkill chattingSkill = new AgentSkill()
{
Id = "chatting_skill",
Name = "Chatting feature",
Description = "Agent to chat with and search the web.",
Tags = ["chat", "llm-tornado"],
Examples =
[
"Hello, what's up?",
],
};
return new AgentCard()
{
Name = AgentName,
Description = "Agent to chat with and search the web",
Url = agentUrl, // Placeholder URL
Version = AgentVersion,
DefaultInputModes = ["text"],
DefaultOutputModes = ["text"],
Capabilities = capabilities,
Skills = [chattingSkill],
};
}
}Step 2: Add Agent to Program.cs
csharp
BaseA2ATornadoRuntimeConfiguration agentRuntime = new A2ATornadoAgentSample().Build(); //Replace this to customize or modify files directly.Step 3: Build the Project
bash
dotnet buildDocker Deployment
Step 4: Configure Environment Variables
Add API key to launchSettings.json:
json
{
"profiles": {
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"environmentVariables": {
"OPENAI_API_KEY": "your-api-key-here"
},
"publishAllPorts": true,
"useSSL": false
}
}
}Step 5: Build Docker Image
bash
docker build -t weather-agent .Step 6: Run Docker Container
bash
# Run with API key from environment
docker run -it -p 5000:80 \
-e OPENAI_API_KEY=your_api_key \
weather-agent
# Or run with multiple environment variables
docker run -it -p 5000:80 \
-e OPENAI_API_KEY=your_api_key \
-e ANTHROPIC_API_KEY=your_anthropic_key \
weather-agentAPI Endpoints
The agent server exposes the following endpoints:
Get Agent Card
http
GET /agent/cardReturns the agent's capabilities and metadata.
Send Message to Agent
http
POST /agent/message
Content-Type: application/json
{
"message": "What's the weather in Prague?",
"context": {}
}Health Check
http
GET /healthReturns agent server health status.
Testing Your Agent Server
Using cURL
bash
# Get agent card
curl http://localhost:5000/agent/card
# Send message
curl -X POST http://localhost:5000/agent/message \
-H "Content-Type: application/json" \
-d '{"message": "What is the weather in London?"}'Using HTTPClient
csharp
HttpClient client = new HttpClient();
// Get agent card
HttpResponseMessage cardResponse = await client.GetAsync("http://localhost:5000/agent/card");
string card = await cardResponse.Content.ReadAsStringAsync();
// Send message
StringContent content = new StringContent(
JsonConvert.SerializeObject(new { message = "What's the weather?" }),
Encoding.UTF8,
"application/json"
);
HttpResponseMessage response = await client.PostAsync(
"http://localhost:5000/agent/message",
content
);
string result = await response.Content.ReadAsStringAsync();Best Practices
Error Handling
- Implement global exception handling
- Return appropriate HTTP status codes
- Log errors for debugging
- Provide meaningful error messages
Performance
- Use async/await throughout
- Implement caching where appropriate
- Monitor resource usage
- Set appropriate timeouts
Security
- Validate all inputs
- Use HTTPS in production
- Implement authentication
- Rate limit requests
- Sanitize outputs
Monitoring
- Implement health checks
- Log all requests
- Track performance metrics
- Monitor error rates
- Set up alerts