Skip to content

Latest commit

 

History

466 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Agent Development Kit (ADK)

Build powerful, interoperable AI agents with the Agent-to-Agent (A2A) protocol

⚠️ Early Stage Warning: This project is in its early stages of development. Breaking changes are expected as the API evolves and improves. Please use pinned versions in production environments and be prepared to update your code when upgrading versions.

CI Status Release Version License Go Version


Table of Contents


Overview

The A2A ADK (Agent Development Kit) is a Go library that simplifies building Agent-to-Agent (A2A) protocol compatible agents. A2A enables seamless communication between AI agents, allowing them to collaborate, delegate tasks, and share capabilities across different systems and providers.

What is A2A?

Agent-to-Agent (A2A) is a standardized protocol that enables AI agents to:

  • Communicate with each other using a unified JSON-RPC interface
  • Delegate tasks to specialized agents with specific capabilities
  • Stream responses in real-time for better user experience
  • Authenticate securely using OIDC/OAuth2
  • Discover capabilities through standardized agent cards

🚀 Quick Start

Installation

go get github.com/inference-gateway/adk

Examples

For complete working examples, see the examples directory:

Getting Started

To run any example:

cd examples/minimal/server
go run main.go

Each example includes its own README with setup instructions and usage details.

✨ Key Features

Core Capabilities

  • 🤖 A2A Protocol Compliance: Full implementation of the Agent-to-Agent communication standard
  • 🔌 Multi-Provider Support: Works with Anthropic (Claude models), Cloudflare Workers AI, Cohere, DeepSeek, Elevenlabs, Google (Gemini), Groq, llama.cpp, MiniMax, Mistral, Moonshot, Nvidia, Ollama, Ollama Cloud, OpenAI (GPT models), Zai
, and other LLM providers
  • 🌊 Real-time Streaming: Stream responses as they're generated from language models
  • 🔧 Custom Tools: Easy integration of custom tools and capabilities
  • 🧩 MCP Client: Connect to MCP servers and expose their tools to the agent through a selector that keeps only tool metadata in context - see docs/mcp.md
  • 🪝 Callback Hooks: Lifecycle hooks for agent, model, and tool execution with flow control
  • 📎 File Artifacts: Support for downloadable file artifacts with filesystem and MinIO storage backends
  • 🔐 Secure Authentication: Built-in OIDC/OAuth2 authentication support
  • 📨 Push Notifications: Webhook notifications for real-time task state updates
  • ⏸️ Task Pausing: Built-in support for input-required state pausing and resumption
  • 🗄️ Multiple Storage Backends: Support for in-memory and Redis storage with horizontal scaling
  • 📊 Usage Metadata: Automatic tracking of LLM token consumption and execution metrics

Developer Experience

  • ⚙️ Environment Configuration: Simple setup through environment variables
  • 📊 Task Management: Built-in task queuing, polling, and lifecycle management
  • 🏗️ Extensible Architecture: Pluggable components for custom business logic
  • 📚 Type-Safe: Generated types from A2A schema for compile-time safety
  • 🧪 Well Tested: Comprehensive test coverage with table-driven tests

Enterprise Ready

  • 🌿 Lightweight: Optimized binary size for efficient deployment
  • 🛡️ Production Hardened: Configurable timeouts, TLS support, and error handling
  • ☸️ Cloud Native: Ready for cloud-native deployments and orchestration
  • 📊 Observability: OpenTelemetry integration for monitoring and tracing

🛠️ Development

Quick Setup

# Clone the repository
git clone https://github.com/inference-gateway/adk.git
cd adk

# Install dependencies
go mod download

# Install pre-commit hook
task precommit:install

Essential Tasks

Task Description
task a2a:download-schema Download the latest A2A schema
task a2a:generate-types Generate Go types from A2A schema
task lint Run linting and code quality checks
task test Run all tests
task precommit:install Install Git pre-commit hook (recommended)

Build-Time Agent Metadata

The ADK supports injecting agent metadata at build time using Go linker flags (LD flags). This makes agent information immutable and embedded in the binary, which is useful for production deployments.

Available LD Flags

The following build-time metadata variables can be set via LD flags:

  • BuildAgentName - The agent's display name
  • BuildAgentDescription - A description of the agent's capabilities
  • BuildAgentVersion - The agent's version number

Usage Examples

Simple A2A Server Example:

package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	zap "go.uber.org/zap"

	server "github.com/inference-gateway/adk/server"
	config "github.com/inference-gateway/adk/server/config"
	types "github.com/inference-gateway/adk/types"
)

func main() {
	fmt.Println("🤖 Starting Simple A2A Server...")

	// Initialize logger
	logger, err := zap.NewDevelopment()
	if err != nil {
		log.Fatalf("failed to create logger: %v", err)
	}
	defer logger.Sync()

	// Get port from environment or use default
	port := os.Getenv("SERVER_PORT")
	if port == "" {
		port = "8080"
	}

	// Configuration
	cfg := config.Config{
		AgentName:        "simple-agent",
		AgentDescription: "A simple A2A server with default handlers",
		AgentVersion:     "0.1.0",
		Debug:            true,
		QueueConfig: config.QueueConfig{
			CleanupInterval: 5 * time.Minute,
		},
		ServerConfig: config.ServerConfig{
			Port: port,
		},
	}

	// AgentCard.URL is a *string
	agentURL := fmt.Sprintf("http://localhost:%s", port)

	// Build and start server with default handlers. No agent is configured
	// here, and the default streaming handler requires one, so the card
	// advertises streaming: false - see examples/ai-powered/ to enable it.
	a2aServer, err := server.NewA2AServerBuilder(cfg, logger).
		WithDefaultTaskHandlers().
		WithAgentCard(types.AgentCard{
			Name:            cfg.AgentName,
			Description:     cfg.AgentDescription,
			Version:         cfg.AgentVersion,
			SupportedInterfaces: []types.AgentInterface{
				{URL: agentURL, ProtocolBinding: "JSONRPC", ProtocolVersion: "1.0"},
			},
			Capabilities: types.AgentCapabilities{
				Streaming:         &[]bool{false}[0],
				PushNotifications: &[]bool{false}[0],
			},
			DefaultInputModes:  []string{"text/plain"},
			DefaultOutputModes: []string{"text/plain"},
			Skills:             []types.AgentSkill{},
		}).
		Build()
	if err != nil {
		logger.Fatal("failed to create A2A server", zap.Error(err))
	}

	logger.Info("✅ server created")

	// Start server
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	go func() {
		if err := a2aServer.Start(ctx); err != nil {
			logger.Fatal("server failed to start", zap.Error(err))
		}
	}()

	logger.Info("🌐 server running on port " + port)

	// Wait for shutdown signal
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	logger.Info("🛑 shutting down...")

	// Graceful shutdown
	shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer shutdownCancel()

	if err := a2aServer.Stop(shutdownCtx); err != nil {
		logger.Error("shutdown error", zap.Error(err))
	} else {
		logger.Info("✅ goodbye!")
	}
}

See the Docker Support section for containerized builds.


For detailed development workflows, testing guidelines, and contribution processes, see the Contributing Guide.

📖 API Reference

Core Components

A2AServer

The main server interface that handles A2A protocol communication. See server examples for complete implementation details.

A2AServerBuilder

Build A2A servers with custom configurations using a fluent interface. The builder provides methods for:

  • WithAgent() - Configure AI agent integration
  • WithDefaultTaskHandlers() - Use built-in task processing
  • WithBackgroundTaskHandler() - Custom background task handling
  • WithStreamingTaskHandler() - Custom streaming task handling
  • WithAgentCardFromFile() - Load agent metadata from JSON
  • WithExtendedAgentCard() - Serve a richer card to authenticated callers via GetExtendedAgentCard

See examples for complete usage patterns.

Task Handler Interfaces

The ADK provides two distinct interfaces for handling tasks:

  • TaskHandler - For background/polling scenarios (SendMessage)
  • StreamableTaskHandler - For real-time streaming scenarios (SendStreamingMessage)

Streaming handlers require an agent to be configured. See task handler examples for implementation details.

AgentBuilder

Build OpenAI-compatible agents using a fluent interface. Supports:

  • Custom LLM clients
  • System prompts and conversation limits
  • Tool integration
  • Callback hooks (BeforeAgent, AfterAgent, BeforeModel, AfterModel, BeforeTool, AfterTool)
  • Configuration management

See AI-powered examples and callback examples for complete agent setup.

A2AClient

Client interface for communicating with A2A servers. Supports:

  • Task sending and streaming
  • Health monitoring
  • Agent card retrieval
  • Custom configuration

See examples/protocol-methods/ for usage patterns.

A2A JSON-RPC Methods

Beyond SendMessage, SendStreamingMessage, and GetTask, the client exposes every method in the A2A JSON-RPC surface. Each snippet below is runnable against any ADK-built server; see examples/protocol-methods/ for an end-to-end demo that ties them all together.

CancelTask

Cancel an in-flight task. Works for tasks in any non-terminal state (SUBMITTED, WORKING, INPUT_REQUIRED, AUTH_REQUIRED, UNSPECIFIED).

resp, err := a2a.CancelTask(ctx, types.CancelTaskRequest{ID: taskID})
if err != nil {
    log.Fatalf("cancel failed: %v", err)
}

taskBytes, _ := json.Marshal(resp.Result)
var task types.Task
_ = json.Unmarshal(taskBytes, &task)
log.Printf("cancelled task %s → state=%s", task.ID, task.Status.State)
ListTasks

List tasks the server knows about. PageSize controls the page size (server caps it at 100; default is 50) and PageToken selects the page: pass the NextPageToken from the previous response, or leave it empty for the first page. Iterate until no NextPageToken comes back to walk the full result set.

pageSize := 20
pageToken := ""
for {
    resp, err := a2a.ListTasks(ctx, types.ListTasksRequest{
        PageSize:  &pageSize,
        PageToken: &pageToken,
    })
    if err != nil {
        log.Fatalf("list failed: %v", err)
    }

    listBytes, _ := json.Marshal(resp.Result)
    var list types.ListTasksResponse
    _ = json.Unmarshal(listBytes, &list)

    for _, t := range list.Tasks {
        log.Printf("  task %s [%s]", t.ID, t.Status.State)
    }

    pageToken = list.NextPageToken
    if len(list.Tasks) == 0 || pageToken == "" {
        break
    }
}

You can also filter by ContextID or by State (e.g. only TASK_STATE_COMPLETED); both fields are optional pointers on TaskListParams.

CreateTaskPushNotificationConfig, GetTaskPushNotificationConfig, ListTaskPushNotificationConfigs, DeleteTaskPushNotificationConfig

Register, inspect, and remove webhook callbacks the server will POST to as a task changes state. The four methods share a common identifier (task.ID) and form a complete CRUD cycle.

configID := uuid.New().String()
authToken := "shared-secret"

// set: register a webhook for the task.
if _, err := a2a.SetTaskPushNotificationConfig(ctx, types.TaskPushNotificationConfig{
    TaskID: &taskID,
    ID:     &configID,
    URL:    "https://example.com/webhook",
    Token:  &authToken,
}); err != nil {
    log.Fatalf("set failed: %v", err)
}

// get: read the active config.
if _, err := a2a.GetTaskPushNotificationConfig(ctx, types.GetTaskPushNotificationConfigRequest{
    TaskID: taskID,
    ID:     configID,
}); err != nil {
    log.Fatalf("get failed: %v", err)
}

// list: enumerate every config attached to a task.
if _, err := a2a.ListTaskPushNotificationConfig(ctx, types.ListTaskPushNotificationConfigsRequest{
    TaskID: taskID,
}); err != nil {
    log.Fatalf("list failed: %v", err)
}

// delete: tear the config down.
if _, err := a2a.DeleteTaskPushNotificationConfig(ctx, types.DeleteTaskPushNotificationConfigRequest{
    TaskID: taskID,
    ID:     configID,
}); err != nil {
    log.Fatalf("delete failed: %v", err)
}

Server-side push notifications require the agent card's capabilities.pushNotifications to be true: the builder only installs the webhook sender when the card passed to WithAgentCard() / WithAgentCardFromFile() declares it. CAPABILITIES_PUSH_NOTIFICATIONS has no effect on its own.

SubscribeToTask

Re-attach to a streaming task after the original SSE connection has dropped. The server first re-emits the current task state, then forwards any further streaming events as they happen.

events, err := a2a.ResubscribeTask(ctx, types.SubscribeToTaskRequest{
    ID: taskID,
})
if err != nil {
    log.Fatalf("resubscribe failed: %v", err)
}
for evt := range events {
    payload, _ := json.Marshal(evt.Result)
    log.Printf("event: %s", string(payload))
}
GetExtendedAgentCard

The JSON-RPC counterpart to the public .well-known/agent-card.json endpoint. It returns a separate, richer card - the one registered with WithExtendedAgentCard() - through the JSON-RPC route, so it is subject to the server's authentication middleware and can stay invisible to anonymous callers.

Unlike the other snippets in this section, this one does not work against a default ADK server. The server answers -32004 (unsupported operation) when the public card does not set capabilities.extendedAgentCard: true, and -32007 when it does but no extended card is configured; the client surfaces both as errors, so the snippet below would exit via log.Fatalf. Register an extended card first:

server.NewA2AServerBuilder(cfg, logger).
    WithAgentCard(publicCard).
    WithExtendedAgentCard(extendedCard). // also flips capabilities.extendedAgentCard on the public card
    Build()

See docs/authentication.md for the full setup.

resp, err := a2a.GetAuthenticatedExtendedCard(ctx, types.GetExtendedAgentCardRequest{})
if err != nil {
    log.Fatalf("authenticated card fetch failed: %v", err)
}
cardBytes, _ := json.MarshalIndent(resp.Result, "", "  ")
log.Println(string(cardBytes))

Agent Health Monitoring

Monitor agent operational status with three health states:

  • healthy: Fully operational
  • degraded: Partially operational
  • unhealthy: Not operational

See client examples for implementation.

LLM Client

Create OpenAI-compatible LLM clients for agent integration. See AI examples for setup details.

Sending Images to a Vision Model

A client can attach an image to a user message as a file part (raw base64 bytes or a url), and the default agent forwards it to the model as an image_url content part, in order with the text parts:

img, _ := os.ReadFile("captcha.png")
b64 := base64.StdEncoding.EncodeToString(img)

resp, err := a2a.SendTask(ctx, types.SendMessageRequest{
    Message: types.Message{
        Role: types.RoleUser,
        Parts: []types.Part{
            types.CreateTextPart("What does this captcha say?"),
            types.CreateFilePart("captcha.png", "image/png", &b64, nil),
        },
    },
})

Notes:

  • fileWithBytes is inlined as a data: URL; fileWithUri is passed through unchanged, so the provider itself must be able to fetch that URL.
  • The operator picks the model: configure a vision-capable one via AGENT_CLIENT_MODEL. A model without vision support rejects the request and the task ends as failed with the provider's error.
  • Advertise what you accept on the agent card, for example DefaultInputModes: []string{"text/plain", "image/png"} - the bundled examples only advertise text/plain.
  • Only image/* files on user messages are forwarded. Other media types (PDF, audio) are still skipped, and agent-role file parts are never sent, because OpenAI-compatible assistant messages cannot carry images.

Configuration

Configure your A2A agent using environment variables. All configuration is optional and includes sensible defaults.

Core Server Configuration

Variable Default Description
SERVER_HOST - Bind address; empty listens on every interface, 127.0.0.1 keeps an embedded server loopback-only
SERVER_PORT 8080 HTTP server listen port
DEBUG false Enable debug logging
AGENT_URL - Stored on the config but never read by the library; the advertised URL comes from the agent card url
STREAMING_STATUS_UPDATE_INTERVAL 1s Unused - parsed but not read anywhere in server/

Agent & LLM Configuration

Variable Default Description
AGENT_CLIENT_PROVIDER - LLM provider (openai, anthropic, groq, etc.)
AGENT_CLIENT_MODEL - Model name (e.g., openai/gpt-4)
AGENT_CLIENT_BASE_URL - Custom LLM endpoint URL
AGENT_CLIENT_API_KEY - API key for LLM provider
AGENT_CLIENT_TIMEOUT 30s Request timeout
AGENT_CLIENT_MAX_RETRIES 3 Maximum retry attempts
AGENT_CLIENT_MAX_CHAT_COMPLETION_ITERATIONS 50 Max chat completion rounds
AGENT_CLIENT_MAX_TOKENS 4096 Maximum tokens per response
AGENT_CLIENT_TEMPERATURE 0.7 LLM temperature (0.0-2.0)
AGENT_CLIENT_SYSTEM_PROMPT (built-in, see below) System prompt for the agent
AGENT_CLIENT_ENABLE_USAGE_METADATA true Track token usage and execution metrics

AGENT_CLIENT_SYSTEM_PROMPT is not empty by default - when unset the agent uses the built-in prompt "You are a helpful AI assistant processing an A2A (Agent-to-Agent) task. Please provide helpful and accurate responses."

Agent Capabilities

Variable Default Description
CAPABILITIES_STREAMING true Enable streaming responses
CAPABILITIES_PUSH_NOTIFICATIONS true Enable webhook notifications

The server does not read CAPABILITIES_* itself. The capabilities it advertises and acts on come from the agent card passed to WithAgentCard() / WithAgentCardFromFile(), so these variables only matter when your application copies them into the card, as the examples do.

Authentication (Optional)

Variable Default Description
AUTH_ENABLED false Enable OIDC authentication
AUTH_ISSUER_URL http://keycloak:8080/realms/inference-gateway-realm OIDC issuer URL; discovery runs at startup against {issuer}/.well-known/openid-configuration. Because a default is set, leaving it unset with AUTH_ENABLED=true runs discovery against this Keycloak URL rather than failing - always set it explicitly
AUTH_CLIENT_ID inference-gateway-client OIDC client ID, used as the expected token audience when AUTH_AUDIENCE is empty
AUTH_AUDIENCE - Comma-separated accepted aud values, for example an API identifier
AUTH_TOKEN - Static bearer token that protects /a2a without an OIDC issuer (compared in constant time). Mutually exclusive with AUTH_ENABLED; declare it on the card with server.BearerTokenSecuritySchemes()

See docs/authentication.md for the full card-driven auth flow: discovery, out-of-band credentials, the authenticated extended card, and authorization via callbacks.

Task Management

Variable Default Description
TASK_RETENTION_MAX_COMPLETED_TASKS 100 Max completed tasks to keep (0 = unlimited)
TASK_RETENTION_MAX_FAILED_TASKS 50 Max failed tasks to keep (0 = unlimited)
TASK_RETENTION_CLEANUP_INTERVAL 5m Cleanup frequency (0 = manual only)

Storage Configuration (Optional)

Variable Default Description
QUEUE_PROVIDER memory Storage backend: memory or redis
QUEUE_URL - Redis connection URL (required when using Redis)
QUEUE_MAX_SIZE 100 Unused - parsed but not read anywhere in server/
QUEUE_CLEANUP_INTERVAL 120s Deprecated, unused (see TASK_RETENTION_*)

Storage Backends:

  • Memory Storage (Default): Fast in-memory storage for development and single-instance deployments
  • Redis Storage: Persistent storage with horizontal scaling support for production deployments

Redis Configuration Examples:

# Basic Redis setup
export QUEUE_PROVIDER=redis
export QUEUE_URL=redis://localhost:6379

# Redis with authentication
export QUEUE_URL=redis://:password@localhost:6379
export QUEUE_URL=redis://username:password@localhost:6379

# Redis with specific database
export QUEUE_URL=redis://localhost:6379/1

# Redis with TLS (Redis 6.0+)
export QUEUE_URL=rediss://username:password@redis.example.com:6380/0

MCP Client Configuration (Optional)

Connect the agent to MCP servers and expose their tools through a selector that keeps only tool metadata in the LLM context. Disabled by default and only useful when an LLM is configured. Enable with MCP_ENABLED=true and point MCP_SERVERS at one or more streamable-HTTP MCP servers; the full list of MCP_* variables (timeouts, retry, and polling-backoff tuning) is documented in docs/mcp.md.

Artifacts Configuration (Optional)

Enable file artifacts support for downloadable files generated by your agent:

Variable Default Description
ARTIFACTS_ENABLED false Enable artifacts support
ARTIFACTS_SERVER_HOST localhost Artifacts server host
ARTIFACTS_SERVER_PORT 8081 Artifacts server port
ARTIFACTS_STORAGE_PROVIDER filesystem Storage backend: filesystem or minio
ARTIFACTS_STORAGE_BASE_PATH ./artifacts Base path for filesystem storage
ARTIFACTS_STORAGE_BASE_URL (auto-generated) Override base URL for direct downloads
ARTIFACTS_STORAGE_ENDPOINT - MinIO/S3 endpoint URL
ARTIFACTS_STORAGE_ACCESS_KEY - MinIO/S3 access key
ARTIFACTS_STORAGE_SECRET_KEY - MinIO/S3 secret key
ARTIFACTS_STORAGE_BUCKET_NAME artifacts MinIO/S3 bucket name
ARTIFACTS_STORAGE_USE_SSL true Use SSL for MinIO/S3 connections
ARTIFACTS_RETENTION_MAX_ARTIFACTS 5 Max artifacts per task (0 = unlimited)
ARTIFACTS_RETENTION_MAX_AGE 168h Max artifact age, as a Go duration (0 = no age limit). d is not a valid unit - use 168h, not 7d
ARTIFACTS_RETENTION_CLEANUP_INTERVAL 24h Cleanup frequency (0 = manual only)

Storage Backends:

  • Filesystem Storage (Default): Store artifacts locally on disk, suitable for single-instance deployments
  • MinIO Storage: Cloud-native object storage with S3 compatibility, ideal for distributed deployments

Download Modes:

  • Proxy Mode (Default): Downloads go through the artifacts server (port 8081) with authentication and logging
  • Direct Mode: Configure ARTIFACTS_STORAGE_BASE_URL to enable direct downloads from storage backend

MinIO Configuration Example:

# Enable artifacts with MinIO storage
export ARTIFACTS_ENABLED=true
export ARTIFACTS_STORAGE_PROVIDER=minio
export ARTIFACTS_STORAGE_ENDPOINT=localhost:9000
export ARTIFACTS_STORAGE_ACCESS_KEY=minioadmin
export ARTIFACTS_STORAGE_SECRET_KEY=minioadmin
export ARTIFACTS_STORAGE_USE_SSL=false

# Optional: Enable direct downloads (bypasses artifacts server)
export ARTIFACTS_STORAGE_BASE_URL=http://localhost:9000

Benefits of Redis Storage:

  • ✅ Persistent Tasks - Tasks survive server restarts
  • ✅ Distributed Processing - Multiple server instances can share the same queue
  • ✅ High Performance - Redis provides fast task queuing and retrieval
  • ✅ Task History - Completed and failed tasks are retained based on configuration
  • ✅ Horizontal Scaling - Scale to N number of A2A servers processing the same queue

TLS Configuration (Optional)

Variable Default Description
SERVER_TLS_ENABLED false Enable TLS/HTTPS
SERVER_TLS_CERT_PATH - Path to TLS certificate
SERVER_TLS_KEY_PATH - Path to TLS private key

Telemetry (Optional)

When enabled, the server exports metrics (Prometheus pull or OTLP push) and can export traces via OTLP over HTTP or gRPC. It also participates in W3C Trace Context propagation: incoming traceparent and baggage headers are extracted, a request-scoped a2a.request span is created, and the session.id / gen_ai.tool.call.id baggage items are surfaced as span attributes. Exporters are selected with the standard OTEL_* variables; the original TELEMETRY_* variables remain supported as deprecated aliases. See docs/telemetry.md for the full matrix.

TELEMETRY_ENABLED=true is the master switch; the OTEL_* variables then choose which exporters run per signal.

Variable Default Description
TELEMETRY_ENABLED false Master switch for the telemetry subsystem
OTEL_METRICS_EXPORTER prometheus Metrics exporter: prometheus, otlp, or none
OTEL_TRACES_EXPORTER otlp Traces exporter: otlp or none
OTEL_EXPORTER_OTLP_ENDPOINT http://localhost:4318 OTLP endpoint base URL for traces and metrics
OTEL_EXPORTER_OTLP_PROTOCOL http/protobuf OTLP transport: http/protobuf or grpc
OTEL_EXPORTER_PROMETHEUS_HOST - Prometheus pull host (empty = all interfaces)
OTEL_EXPORTER_PROMETHEUS_PORT 9090 Prometheus pull port

Attribute keys (default to OTel semantic conventions; used for both the baggage member and the span attribute):

Variable Default Description
TELEMETRY_ATTR_SESSION_ID_KEY session.id Session id baggage/attribute key
TELEMETRY_ATTR_TOOL_CALL_ID_KEY gen_ai.tool.call.id Tool call id baggage/attribute key

Deprecated aliases (superseded by the OTEL_* variables above, still honored):

Variable Default Superseded by
TELEMETRY_METRICS_PORT 9090 OTEL_EXPORTER_PROMETHEUS_PORT
TELEMETRY_METRICS_HOST - OTEL_EXPORTER_PROMETHEUS_HOST
TELEMETRY_TRACE_ENDPOINT http://localhost:4318 OTEL_EXPORTER_OTLP_ENDPOINT
TELEMETRY_TRACE_HEADERS - OTEL_EXPORTER_OTLP_HEADERS
TELEMETRY_LOG_* - Reserved - OTLP log export not yet wired

The tracing service name is taken from the agent card name (the build-time agent identity), not a separate variable.

Library consumers that already run their own OpenTelemetry setup can inject it with WithTelemetry() instead of letting the ADK build one from the environment. The injected instance activates the middleware, request spans, and /metrics endpoint regardless of TELEMETRY_ENABLED:

srv, err := server.NewA2AServerBuilder(cfg, logger).
    WithTelemetry(myOtel).
    WithAgentCard(card).
    WithDefaultTaskHandlers().
    Build()

Example Configuration

See configuration examples for complete setup patterns, including environment variables, custom config structs, and programmatic overrides.

🔧 Advanced Usage

For detailed implementation examples and patterns, see the examples directory:

🌐 A2A Ecosystem

This ADK is part of the broader Inference Gateway ecosystem:

Related Projects

A2A Agents

📋 Requirements

  • Go: 1.26 or later
  • Dependencies: See go.mod for full dependency list

🐳 Docker Support

Build and run your A2A agent application in a container. Here's an example Dockerfile for an application using the ADK:

FROM golang:1.26-alpine AS builder

# Build arguments for agent metadata
ARG AGENT_NAME="My A2A Agent"
ARG AGENT_DESCRIPTION="A custom A2A agent built with the ADK"
ARG AGENT_VERSION="0.1.0"

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN go mod tidy && \
    go build -ldflags "-X 'github.com/inference-gateway/adk/server.BuildAgentName=${AGENT_NAME}' -X 'github.com/inference-gateway/adk/server.BuildAgentDescription=${AGENT_DESCRIPTION}' -X 'github.com/inference-gateway/adk/server.BuildAgentVersion=${AGENT_VERSION}'" -o bin/agent .

FROM alpine:latest
RUN apk --no-cache add ca-certificates && \
    addgroup -g 1001 -S a2a && \
    adduser -u 1001 -S agent -G a2a
WORKDIR /home/agent
COPY --from=builder /app/bin/agent .
RUN chown agent:a2a ./agent
USER agent
CMD ["./agent"]

Build with custom metadata:

docker build \
  --build-arg AGENT_NAME="Weather Assistant" \
  --build-arg AGENT_DESCRIPTION="AI-powered weather forecasting agent" \
  --build-arg AGENT_VERSION="0.1.1" \
  -t my-a2a-agent .

📄 License

This project is licensed under the Apache 2.0 License. See the LICENSE file for details.

🤝 Contributing

Contributions to the A2A ADK are welcome! Whether you're fixing bugs, adding features, improving documentation, or helping with testing, your contributions make the project better for everyone.

Please see the Contributing Guide for:

  • 🚀 Getting Started - Development environment setup and prerequisites
  • 📋 Development Workflow - Step-by-step development process and tools
  • 🎯 Coding Guidelines - Code style, testing patterns, and best practices
  • 🛠️ Making Changes - Branch naming, commit format, and submission process
  • 🧪 Testing Guidelines - Test structure, mocking, and coverage requirements
  • 🔄 Pull Request Process - Review process and submission checklist

Quick Start for Contributors:

# Fork the repo and clone it
git clone https://github.com/your-username/adk.git
cd adk

# Install pre-commit hook
task precommit:install

For questions or help getting started, please open a discussion or check out the contributing guide.

📞 Support

Issues & Questions

🔗 Resources

Documentation


GitHub • Documentation

About

An Agent Development Kit (ADK) allowing for seamless creation of A2A-compatible agents written in Go.

Topics

Resources

Contributing

Security policy

Stars

25 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages