Skip to content

trpc-group/trpc-a2a-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tRPC-A2A-Go

Go Reference Go Report Card LICENSE Releases Tests Coverage

This is tRPC group's Go implementation of the A2A protocol, enabling different AI agents to discover and collaborate with each other.

Table of Contents

Quick Start

Running the Basic Server Example

# Start the example server on default port 8080
cd examples/basic/server
go run main.go

# Specify different host and port
go run main.go --host 0.0.0.0 --port 9000

# Disable streaming capability
go run main.go --no-stream

# Disable CORS headers
go run main.go --no-cors

Using the Basic CLI Client

# Connect to a local agent
cd examples/basic/client
go run main.go

# Connect to a specific agent
go run main.go --agent http://localhost:9000/

# Specify request timeout
go run main.go --timeout 30s

# Disable streaming mode
go run main.go --no-stream

# Use a specific session ID
go run main.go --session "your-session-id"

Examples

The repository includes several examples demonstrating different aspects of the A2A protocol:

1. Simple Example (examples/simple)

A minimal example demonstrating the core A2A functionality:

  • Simple server that reverses text input
  • Simple client that sends non-streaming requests
  • Basic task lifecycle (submission, processing, completion)
  • Text processing with artifacts
# Start the simple server
cd examples/simple/server
go run main.go

# Run the simple client
cd examples/simple/client
go run main.go

# Send a custom message
go run main.go --message "Text to be reversed"

2. Streaming Examples (examples/streaming)

Examples focused on streaming capabilities:

  • Server implementation with streaming response support
  • Client implementation for handling streaming data
# Start the streaming server
cd examples/streaming/server
go run main.go

# Run the streaming client
cd examples/streaming/client
go run main.go

3. Basic Example (examples/basic)

A comprehensive example showcasing:

  • A versatile text processing server with multiple operations
  • A feature-rich CLI client with support for all core A2A protocol APIs
  • Streaming and non-streaming modes
  • Multi-turn conversations with session management
  • Task management (create, cancel, get)
  • Agent capability discovery

4. Authentication Examples (examples/auth)

Complete examples demonstrating authentication:

  • Server implementation with various authentication methods
  • Client examples showing how to connect with different auth methods
  • JWT, API key, and OAuth2 implementations
  • Command-line options for all authentication parameters
# Start the authentication server with OAuth2 support enabled
cd examples/auth/server
go run main.go --enable-oauth true

# Run client with JWT authentication
cd examples/auth/client
go run main.go --auth jwt --jwt-secret "your-secret-key"

# Run client with API key authentication
go run main.go --auth apikey --api-key "test-api-key"

# Run client with OAuth2 authentication
go run main.go --auth oauth2 \
  --oauth2-client-id "my-client-id" \
  --oauth2-client-secret "my-client-secret"

# Run client with JWT from a file
go run main.go --auth jwt --jwt-secret-file "path/to/jwt-secret.key"

# Specify custom message and session ID
go run main.go --auth jwt --message "Custom message" --session-id "session123"

Creating Your Own Agent

1. Implement the TaskProcessor Interface

This interface defines how your agent processes incoming tasks:

import (
    "context"

    "trpc.group/trpc-go/trpc-a2a-go/protocol"
    "trpc.group/trpc-go/trpc-a2a-go/taskmanager"
)

// Implement the TaskProcessor interface
type myTaskProcessor struct {
    // Optional: add your custom fields
}

func (p *myTaskProcessor) Process(
    ctx context.Context,
    taskID string,
    message protocol.Message,
    handle taskmanager.TaskHandle,
) error {
    // 1. Extract input data from message
    // 2. Process data, generate results
    // 3. Use handle to update task status and add artifacts

    // Processing complete, return nil for success
    return nil
}

2. Create an Agent Card

The agent card describes your agent's capabilities:

import (
    "trpc.group/trpc-go/trpc-a2a-go/server"
    "trpc.group/trpc-go/trpc-a2a-go/protocol"
)

// Helper function to create string pointers
func stringPtr(s string) *string {
    return &s
}

agentCard := server.AgentCard{
    Name: "My Agent",
    Description: stringPtr("Agent description"),
    URL: "http://localhost:8080/",
    Version: "1.0.0",
    Provider: &server.AgentProvider{
        Name: "Provider name",
    },
    Capabilities: server.AgentCapabilities{
        Streaming: true,
        StateTransitionHistory: true,
    },
    DefaultInputModes: []string{string(protocol.PartTypeText)},
    DefaultOutputModes: []string{string(protocol.PartTypeText)},
    Skills: []server.AgentSkill{
        {
            ID: "my_skill",
            Name: "Skill name",
            Description: stringPtr("Skill description"),
            Tags: []string{"tag1", "tag2"},
            Examples: []string{"Example input"},
            InputModes: []string{string(protocol.PartTypeText)},
            OutputModes: []string{string(protocol.PartTypeText)},
        },
    },
}

3. Create and Start the Server

Initialize the server with your task processor and agent card:

import (
    "log"

    "trpc.group/trpc-go/trpc-a2a-go/server"
    "trpc.group/trpc-go/trpc-a2a-go/taskmanager"
)

// Create the task processor
processor := &myTaskProcessor{}

// Create task manager, inject processor
taskManager, err := taskmanager.NewMemoryTaskManager(processor)
if err != nil {
    log.Fatalf("Failed to create task manager: %v", err)
}

// Create the server
srv, err := server.NewA2AServer(agentCard, taskManager)
if err != nil {
    log.Fatalf("Failed to create server: %v", err)
}

// Start the server
log.Printf("Agent server started on :8080")
if err := srv.Start(":8080"); err != nil {
    log.Fatalf("Server start failed: %v", err)
}

Authentication

The tRPC-A2A-Go framework supports multiple authentication methods for securing communication between agents and clients:

Supported Authentication Methods

  • JWT (JSON Web Tokens): Secure token-based authentication with support for audience and issuer validation
  • API Keys: Simple key-based authentication using custom headers
  • OAuth 2.0: Support for various OAuth2 flows, including:
    • Client Credentials flow
    • Password Credentials flow
    • Custom token sources
    • Token validation

Server-Side Authentication

Adding Authentication to Your Server

import (
    "time"
    
    "trpc.group/trpc-go/trpc-a2a-go/auth"
    "trpc.group/trpc-go/trpc-a2a-go/server"
)

// Create a JWT authentication provider
jwtSecret := []byte("your-secret-key")
jwtProvider := auth.NewJWTAuthProvider(
    jwtSecret,
    "your-audience",
    "your-issuer",
    24*time.Hour, // token lifetime
)

// Or create an API key authentication provider
apiKeys := map[string]string{
    "api-key-1": "user1",
    "api-key-2": "user2",
}
apiKeyProvider := auth.NewAPIKeyAuthProvider(apiKeys, "X-API-Key")

// OAuth2 token validation provider
oauth2Provider := auth.NewOAuth2AuthProviderWithConfig(
    nil,   // No config needed for simple validation
    "",    // No userinfo endpoint for this example
    "sub", // Default subject field for identifying users
)

// Chain multiple authentication methods
chainProvider := auth.NewChainAuthProvider(
    jwtProvider, 
    apiKeyProvider,
    oauth2Provider,
)

// Create the server with authentication
srv, err := server.NewA2AServer(
    agentCard,
    taskManager,
    server.WithAuthProvider(chainProvider),
)

Using Authentication Middleware

// Create an authentication provider
jwtProvider := auth.NewJWTAuthProvider(secretKey, audience, issuer, tokenLifetime)

// Create middleware
authMiddleware := auth.NewMiddleware(jwtProvider)

// Wrap your handler
http.Handle("/protected", authMiddleware.Wrap(yourHandler))

Client-Side Authentication

Create authenticated clients using the appropriate options:

import (
    "trpc.group/trpc-go/trpc-a2a-go/client"
)

// JWT Authentication
client, err := client.NewA2AClient(
    "https://agent.example.com/",
    client.WithJWTAuth(secretKey, audience, issuer, tokenLifetime),
)

// API Key Authentication
client, err := client.NewA2AClient(
    "https://agent.example.com/",
    client.WithAPIKeyAuth("your-api-key", "X-API-Key"),
)

// OAuth2 Client Credentials
client, err := client.NewA2AClient(
    "https://agent.example.com/",
    client.WithOAuth2ClientCredentials(
        "client-id",
        "client-secret",
        "https://auth.example.com/token",
        []string{"scope1", "scope2"},
    ),
)

See the examples/auth/client directory for complete examples of using different authentication methods.

Push Notification Authentication

The framework includes support for secure push notifications:

// Create an authenticator for push notifications
notifAuth := auth.NewPushNotificationAuthenticator()

// Generate a key pair
if err := notifAuth.GenerateKeyPair(); err != nil {
    // Handle error
}

// Expose JWKS endpoint
http.HandleFunc("/.well-known/jwks.json", notifAuth.HandleJWKS)

// Enable JWKS endpoint when creating the server
srv, err := server.NewA2AServer(
    agentCard,
    taskManager,
    server.WithJWKSEndpoint(true, "/.well-known/jwks.json"),
)

Session Management

The A2A protocol supports session management to group related tasks:

// Client-side: Creating a task with session ID
sessionID := "your-session-id" // Or generate one with uuid.New().String()
taskParams := protocol.SendTaskParams{
    ID:        "task-123",
    SessionID: &sessionID,
    Message:   message,
}

// Server-side: Tasks with the same sessionID are recognized
// as belonging to the same conversation or workflow

This allows for:

  • Grouping related tasks under a single session
  • Multi-turn conversations across different task IDs
  • Better organization and retrieval of task history

Future Enhancements

  • Persistent storage options for task history
  • More utilities and helper functions
  • Metrics and logging integrations
  • Comprehensive test suite
  • Advanced session management capabilities

Contributing

Contributions and improvement suggestions are welcome! Please ensure your code follows Go coding standards and includes appropriate tests. See the CONTRIBUTING.md file for more details.

Acknowledgements

This project's protocol design is based on Google's open-source A2A protocol (original repository), following the Apache 2.0 license. This is an unofficial implementation.

About

Go implementation for A2A (Agent2Agent) protocol

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages