This is tRPC group's Go implementation of the A2A protocol, enabling different AI agents to discover and collaborate with each other.
- Quick Start
- Examples
- Creating Your Own Agent
- Authentication
- Session Management
- Future Enhancements
- Contributing
- Acknowledgements
# 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
# 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"
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"
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
}
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)},
},
},
}
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)
}
The tRPC-A2A-Go framework supports multiple authentication methods for securing communication between agents and clients:
- 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
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),
)
// 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))
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.
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"),
)
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
- Persistent storage options for task history
- More utilities and helper functions
- Metrics and logging integrations
- Comprehensive test suite
- Advanced session management capabilities
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.
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.