Skip to content

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 build

Docker 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-agent

API Endpoints

The agent server exposes the following endpoints:

Get Agent Card

http
GET /agent/card

Returns 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 /health

Returns 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