{"id":30737703,"url":"https://github.com/inference-gateway/rust-adk","last_synced_at":"2025-09-03T21:46:40.841Z","repository":{"id":307277576,"uuid":"1028642132","full_name":"inference-gateway/rust-adk","owner":"inference-gateway","description":"An Agent Development Kit (ADK) allowing for seamless creation of A2A-compatible agents written in Rust","archived":false,"fork":false,"pushed_at":"2025-09-02T04:25:23.000Z","size":180,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-02T05:39:19.956Z","etag":null,"topics":["a2a","a2a-protocol","adk","inference-gateway","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/inference-gateway.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-29T20:53:05.000Z","updated_at":"2025-09-02T04:23:28.000Z","dependencies_parsed_at":"2025-07-30T12:47:13.736Z","dependency_job_id":"889a7686-ecc5-4000-9502-d507b3ce9586","html_url":"https://github.com/inference-gateway/rust-adk","commit_stats":null,"previous_names":["inference-gateway/rust-adk"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/inference-gateway/rust-adk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inference-gateway%2Frust-adk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inference-gateway%2Frust-adk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inference-gateway%2Frust-adk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inference-gateway%2Frust-adk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/inference-gateway","download_url":"https://codeload.github.com/inference-gateway/rust-adk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inference-gateway%2Frust-adk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273517077,"owners_count":25119765,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-03T02:00:09.631Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["a2a","a2a-protocol","adk","inference-gateway","rust"],"created_at":"2025-09-03T21:46:39.668Z","updated_at":"2025-09-03T21:46:40.824Z","avatar_url":"https://github.com/inference-gateway.png","language":"Rust","funding_links":[],"categories":["⚙️ Implementations \u0026 Libraries","🛠️ Tools \u0026 Libraries"],"sub_categories":["🏗️ Frameworks \u0026 SDKs"],"readme":"\u003ch1 align=\"center\"\u003eAgent Development Kit (ADK) - Rust\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eBuild powerful, interoperable AI agents with the Agent-to-Agent (A2A) protocol\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003e ⚠️ **Early Stage Warning**: This project is in its early stages of development. Breaking changes are expected as we iterate and improve the API. Please use pinned versions in production environments and be prepared to update your code when upgrading versions.\n\n\u003cp align=\"center\"\u003e\n  \u003c!-- CI Status Badge --\u003e\n  \u003ca href=\"https://github.com/inference-gateway/rust-adk/actions/workflows/ci.yml?query=branch%3Amain\"\u003e\n    \u003cimg src=\"https://github.com/inference-gateway/rust-adk/actions/workflows/ci.yml/badge.svg?branch=main\" alt=\"CI Status\"/\u003e\n  \u003c/a\u003e\n  \u003c!-- Version Badge --\u003e\n  \u003ca href=\"https://github.com/inference-gateway/rust-adk/releases\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/v/release/inference-gateway/rust-adk?color=blue\u0026style=flat-square\" alt=\"Version\"/\u003e\n  \u003c/a\u003e\n  \u003c!-- License Badge --\u003e\n  \u003ca href=\"https://github.com/inference-gateway/rust-adk/blob/main/LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/license/inference-gateway/rust-adk?color=blue\u0026style=flat-square\" alt=\"License\"/\u003e\n  \u003c/a\u003e\n  \u003c!-- Rust Version --\u003e\n  \u003cimg src=\"https://img.shields.io/badge/rust-1.88+-blue.svg?style=flat-square\" alt=\"Rust Version\"/\u003e\n\u003c/p\u003e\n\n---\n\n## Table of Contents\n\n- [Table of Contents](#table-of-contents)\n- [Overview](#overview)\n  - [What is A2A?](#what-is-a2a)\n- [🚀 Quick Start](#-quick-start)\n  - [Installation](#installation)\n  - [Basic Usage (Minimal Server)](#basic-usage-minimal-server)\n  - [AI-Powered Server](#ai-powered-server)\n  - [Health Check Example](#health-check-example)\n  - [Examples](#examples)\n- [✨ Key Features](#-key-features)\n  - [Core Capabilities](#core-capabilities)\n  - [Developer Experience](#developer-experience)\n  - [Production Ready](#production-ready)\n- [🛠️ Development](#️-development)\n  - [Prerequisites](#prerequisites)\n  - [Development Workflow](#development-workflow)\n  - [Available Tasks](#available-tasks)\n  - [Build-Time Agent Metadata](#build-time-agent-metadata)\n    - [Available Build-Time Variables](#available-build-time-variables)\n    - [Usage Examples](#usage-examples)\n- [📖 API Reference](#-api-reference)\n  - [Core Components](#core-components)\n    - [A2AServer](#a2aserver)\n    - [A2AServerBuilder](#a2aserverbuilder)\n    - [AgentBuilder](#agentbuilder)\n    - [A2AClient](#a2aclient)\n    - [Agent Health Monitoring](#agent-health-monitoring)\n    - [LLM Client](#llm-client)\n  - [Configuration](#configuration)\n- [🔧 Advanced Usage](#-advanced-usage)\n  - [Building Custom Agents with AgentBuilder](#building-custom-agents-with-agentbuilder)\n    - [Basic Agent Creation](#basic-agent-creation)\n    - [Agent with Custom Configuration](#agent-with-custom-configuration)\n    - [Agent with Custom LLM Client](#agent-with-custom-llm-client)\n    - [Fully Configured Agent](#fully-configured-agent)\n  - [Custom Tools](#custom-tools)\n  - [Custom Task Processing](#custom-task-processing)\n  - [Push Notifications](#push-notifications)\n    - [Webhook Payload](#webhook-payload)\n  - [Agent Metadata](#agent-metadata)\n    - [Build-Time Metadata (Recommended)](#build-time-metadata-recommended)\n    - [Runtime Metadata Configuration](#runtime-metadata-configuration)\n  - [Environment Configuration](#environment-configuration)\n- [🌐 A2A Ecosystem](#-a2a-ecosystem)\n  - [Related Projects](#related-projects)\n  - [A2A Agents](#a2a-agents)\n- [📋 Requirements](#-requirements)\n- [🐳 Docker Support](#-docker-support)\n- [🧪 Testing](#-testing)\n- [📄 License](#-license)\n- [🤝 Contributing](#-contributing)\n  - [Getting Started](#getting-started)\n  - [Development Guidelines](#development-guidelines)\n  - [Before Submitting](#before-submitting)\n  - [Pull Request Process](#pull-request-process)\n- [📞 Support](#-support)\n  - [Issues \\\u0026 Questions](#issues--questions)\n- [🔗 Resources](#-resources)\n  - [Documentation](#documentation)\n\n---\n\n## Overview\n\nThe **A2A ADK (Agent Development Kit)** is a Rust library that simplifies building [Agent-to-Agent (A2A) protocol](https://github.com/inference-gateway/schemas/tree/main/a2a) compatible agents. A2A enables seamless communication between AI agents, allowing them to collaborate, delegate tasks, and share capabilities across different systems and providers.\n\n### What is A2A?\n\nAgent-to-Agent (A2A) is a standardized protocol that enables AI agents to:\n\n- **Communicate** with each other using a unified JSON-RPC interface\n- **Delegate tasks** to specialized agents with specific capabilities\n- **Stream responses** in real-time for better user experience\n- **Authenticate** securely using OIDC/OAuth2\n- **Discover capabilities** through standardized agent cards\n\n## 🚀 Quick Start\n\n### Installation\n\nAdd the ADK to your `Cargo.toml`:\n\n```toml\n[dependencies]\ninference-gateway-adk = \"0.1.0\"\n```\n\n### Basic Usage (Minimal Server)\n\n```rust\nuse inference_gateway_adk::server::{A2AServer, A2AServerBuilder};\nuse tokio;\nuse tracing::{info, error};\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    // Initialize tracing\n    tracing_subscriber::init();\n\n    // Create the simplest A2A server\n    let server = A2AServerBuilder::new()\n        .build()\n        .await?;\n\n    // Start server\n    let addr = \"0.0.0.0:8080\".parse()?;\n    info!(\"Server running on port 8080\");\n\n    if let Err(e) = server.serve(addr).await {\n        error!(\"Server failed to start: {}\", e);\n    }\n\n    Ok(())\n}\n```\n\n### AI-Powered Server\n\n```rust\nuse inference_gateway_adk::{\n    server::{A2AServer, A2AServerBuilder, AgentBuilder},\n    config::Config,\n    tools::ToolBox,\n};\nuse serde_json::json;\nuse tokio;\nuse tracing::{info, error};\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    // Initialize tracing\n    tracing_subscriber::init();\n\n    // Load configuration from environment\n    let config = Config::from_env()?;\n\n    // Create toolbox with custom tools\n    let mut toolbox = ToolBox::new();\n\n    // Add a weather tool\n    toolbox.add_tool(\n        \"get_weather\",\n        \"Get weather information\",\n        json!({\n            \"type\": \"object\",\n            \"properties\": {\n                \"location\": {\n                    \"type\": \"string\",\n                    \"description\": \"City name\"\n                }\n            },\n            \"required\": [\"location\"]\n        }),\n        |args| async move {\n            let location = args[\"location\"].as_str().unwrap_or(\"Unknown\");\n            Ok(format!(r#\"{{\"location\": \"{}\", \"temperature\": \"22°C\"}}\"#, location))\n        },\n    );\n\n    // Create LLM client (requires AGENT_CLIENT_API_KEY environment variable)\n    let server = if let Some(api_key) = \u0026config.agent_config.api_key {\n        // AI-powered agent\n        let agent = AgentBuilder::new()\n            .with_config(\u0026config.agent_config)\n            .with_toolbox(toolbox)\n            .build()\n            .await?;\n\n        A2AServerBuilder::new()\n            .with_config(config)\n            .with_agent(agent)\n            .with_agent_card_from_file(\".well-known/agent.json\")\n            .build()\n            .await?\n    } else {\n        // Mock mode without actual LLM\n        let agent = AgentBuilder::new()\n            .with_toolbox(toolbox)\n            .build()\n            .await?;\n\n        A2AServerBuilder::new()\n            .with_config(config)\n            .with_agent(agent)\n            .with_agent_card_from_file(\".well-known/agent.json\")\n            .build()\n            .await?\n    };\n\n    // Start server\n    let addr = \"0.0.0.0:8080\".parse()?;\n    info!(\"AI-powered A2A server running on port 8080\");\n\n    if let Err(e) = server.serve(addr).await {\n        error!(\"Server failed to start: {}\", e);\n    }\n\n    Ok(())\n}\n```\n\n### Health Check Example\n\nMonitor the health status of A2A agents for service discovery and load balancing:\n\n```rust\nuse inference_gateway_adk::client::A2AClient;\nuse tokio::time::{sleep, Duration};\nuse tracing::{info, error};\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    // Initialize tracing\n    tracing_subscriber::init();\n\n    // Create client\n    let client = A2AClient::new(\"http://localhost:8080\")?;\n\n    // Single health check\n    match client.get_health().await {\n        Ok(health) =\u003e info!(\"Agent health: {}\", health.status),\n        Err(e) =\u003e {\n            error!(\"Health check failed: {}\", e);\n            return Ok(());\n        }\n    }\n\n    // Periodic health monitoring\n    loop {\n        sleep(Duration::from_secs(30)).await;\n\n        match client.get_health().await {\n            Ok(health) =\u003e match health.status.as_str() {\n                \"healthy\" =\u003e info!(\"[{}] Agent is healthy\", chrono::Utc::now().format(\"%H:%M:%S\")),\n                \"degraded\" =\u003e info!(\"[{}] Agent is degraded - some functionality may be limited\", chrono::Utc::now().format(\"%H:%M:%S\")),\n                \"unhealthy\" =\u003e info!(\"[{}] Agent is unhealthy - may not be able to process requests\", chrono::Utc::now().format(\"%H:%M:%S\")),\n                _ =\u003e info!(\"[{}] Unknown health status: {}\", chrono::Utc::now().format(\"%H:%M:%S\"), health.status),\n            },\n            Err(e) =\u003e error!(\"Health check failed: {}\", e),\n        }\n    }\n}\n```\n\n### Examples\n\nFor complete working examples, see the [examples](./examples/) directory:\n\n- **[Minimal Server](./examples/minimal-server/)** - Basic A2A server without AI capabilities\n- **[AI-Powered Server](./examples/ai-powered-server/)** - Full A2A server with LLM integration\n- **[JSON AgentCard Server](./examples/json-agentcard-server/)** - A2A server with agent metadata loaded from JSON file\n- **[Client Example](./examples/client/)** - A2A client implementation\n- **[Health Check Example](#health-check-example)** - Monitor agent health status\n\n## ✨ Key Features\n\n### Core Capabilities\n\n- 🤖 **A2A Protocol Compliance**: Full implementation of the Agent-to-Agent communication standard\n- 🔌 **Multi-Provider Support**: Works with OpenAI, Ollama, Groq, Cohere, and other LLM providers\n- 🌊 **Real-time Streaming**: Stream responses as they're generated from language models\n- 🔧 **Custom Tools**: Easy integration of custom tools and capabilities\n- 🔐 **Secure Authentication**: Built-in OIDC/OAuth2 authentication support\n- 📨 **Push Notifications**: Webhook notifications for real-time task state updates\n\n### Developer Experience\n\n- ⚙️ **Environment Configuration**: Simple setup through environment variables\n- 📊 **Task Management**: Built-in task queuing, polling, and lifecycle management\n- 🏗️ **Extensible Architecture**: Pluggable components for custom business logic\n- 📚 **Type-Safe**: Generated types from A2A schema for compile-time safety\n- 🧪 **Well Tested**: Comprehensive test coverage with table-driven tests\n\n### Production Ready\n\n- 🌿 **Lightweight**: Optimized binary size with Rust's zero-cost abstractions\n- 🛡️ **Production Hardened**: Configurable timeouts, TLS support, and error handling\n- 🐳 **Containerized**: OCI compliant and works with Docker and Docker Compose\n- ☸️ **Kubernetes Native**: Ready for cloud-native deployments\n- 📊 **Observability**: OpenTelemetry integration for monitoring and tracing\n\n## 🛠️ Development\n\n### Prerequisites\n\n- Rust 1.88 or later\n- [Task](https://taskfile.dev/) for build automation (optional, can use `cargo` directly)\n\n### Development Workflow\n\n1. **Download latest A2A schema**:\n\n   ```bash\n   task a2a:download-schema\n   ```\n\n2. **Generate types from schema**:\n\n   ```bash\n   task a2a:generate-types\n   ```\n\n3. **Run linting**:\n\n   ```bash\n   task lint\n   ```\n\n4. **Run tests**:\n   ```bash\n   task test\n   ```\n\n### Available Tasks\n\n| Task                       | Description                                 |\n| -------------------------- | ------------------------------------------- |\n| `task a2a:download-schema` | Download the latest A2A schema              |\n| `task a2a:generate-types`  | Generate Rust types from A2A schema         |\n| `task lint`                | Run static analysis and linting with clippy |\n| `task test`                | Run all tests                               |\n| `task build`               | Build the project                           |\n| `task clean`               | Clean up build artifacts                    |\n\n### Build-Time Agent Metadata\n\nThe ADK supports injecting agent metadata at build time using Rust's build script and environment variables. This makes agent information immutable and embedded in the binary, which is useful for production deployments.\n\n#### Available Build-Time Variables\n\nThe following build-time metadata variables can be set:\n\n- **`AGENT_NAME`** - The agent's display name\n- **`AGENT_DESCRIPTION`** - A description of the agent's capabilities\n- **`AGENT_VERSION`** - The agent's version number\n\n#### Usage Examples\n\n**Direct Cargo Build:**\n\n```bash\n# Build your application with custom metadata\nAGENT_NAME=\"MyAgent\" \\\nAGENT_DESCRIPTION=\"My custom agent description\" \\\nAGENT_VERSION=\"1.2.3\" \\\ncargo build --release\n```\n\n**Docker Build:**\n\n```dockerfile\n# Build with custom metadata in Docker\nFROM rust:1.88 AS builder\n\nARG AGENT_NAME=\"Production Agent\"\nARG AGENT_DESCRIPTION=\"Production deployment agent with enhanced capabilities\"\nARG AGENT_VERSION=\"1.0.0\"\n\nWORKDIR /app\nCOPY Cargo.toml Cargo.lock ./\nRUN cargo fetch\n\nCOPY . .\nRUN AGENT_NAME=\"${AGENT_NAME}\" \\\n    AGENT_DESCRIPTION=\"${AGENT_DESCRIPTION}\" \\\n    AGENT_VERSION=\"${AGENT_VERSION}\" \\\n    cargo build --release\n\nFROM debian:bookworm-slim\nRUN apt-get update \u0026\u0026 apt-get install -y ca-certificates \u0026\u0026 rm -rf /var/lib/apt/lists/*\nWORKDIR /app\nCOPY --from=builder /app/target/release/rust-adk .\nCMD [\"./rust-adk\"]\n```\n\n## 📖 API Reference\n\n### Core Components\n\n#### A2AServer\n\nThe main server trait that handles A2A protocol communication.\n\n```rust\nuse inference_gateway_adk::server::{A2AServer, A2AServerBuilder};\n\n// Create a default A2A server\nlet server = A2AServerBuilder::new()\n    .build()\n    .await?;\n\n// Create a server with agent integration\nlet server = A2AServerBuilder::new()\n    .with_agent(agent)\n    .with_agent_card_from_file(\".well-known/agent.json\")\n    .build()\n    .await?;\n\n// Create a server with custom configuration\nlet server = A2AServerBuilder::new()\n    .with_config(config)\n    .with_task_handler(custom_task_handler)\n    .with_task_processor(custom_processor)\n    .build()\n    .await?;\n```\n\n#### A2AServerBuilder\n\nBuild A2A servers with custom configurations using a fluent interface:\n\n```rust\nuse inference_gateway_adk::server::{A2AServerBuilder, AgentBuilder};\n\n// Basic server with agent\nlet server = A2AServerBuilder::new()\n    .with_agent(agent)\n    .with_agent_card_from_file(\".well-known/agent.json\")\n    .build()\n    .await?;\n\n// Server with custom task handler\nlet server = A2AServerBuilder::new()\n    .with_task_handler(custom_task_handler)\n    .with_task_processor(custom_processor)\n    .with_agent_card_from_file(\".well-known/agent.json\")\n    .build()\n    .await?;\n\n// Server with custom configuration\nlet server = A2AServerBuilder::new()\n    .with_config(config)\n    .with_agent(agent)\n    .with_agent_card_from_file(\".well-known/agent.json\")\n    .build()\n    .await?;\n```\n\n#### AgentBuilder\n\nBuild OpenAI-compatible agents that live inside the A2A server using a fluent interface:\n\n```rust\nuse inference_gateway_adk::server::AgentBuilder;\n\n// Basic agent with custom LLM\nlet agent = AgentBuilder::new()\n    .with_config(\u0026config)\n    .with_toolbox(tools)\n    .build()\n    .await?;\n\n// Agent with system prompt\nlet agent = AgentBuilder::new()\n    .with_system_prompt(\"You are a helpful assistant\")\n    .with_max_chat_completion(10)\n    .build()\n    .await?;\n\n// Use with A2A server builder\nlet server = A2AServerBuilder::new()\n    .with_agent(agent)\n    .with_agent_card_from_file(\".well-known/agent.json\")\n    .build()\n    .await?;\n```\n\n#### A2AClient\n\nThe client struct for communicating with A2A servers:\n\n```rust\nuse inference_gateway_adk::client::A2AClient;\n\n// Basic client creation\nlet client = A2AClient::new(\"http://localhost:8080\")?;\n\n// Client with custom configuration\nlet config = ClientConfig {\n    base_url: \"http://localhost:8080\".to_string(),\n    timeout: Duration::from_secs(45),\n    max_retries: 5,\n};\nlet client = A2AClient::with_config(config)?;\n\n// Using the client\nlet agent_card = client.get_agent_card().await?;\nlet health = client.get_health().await?;\nlet response = client.send_task(params).await?;\nclient.send_task_streaming(params, event_handler).await?;\n```\n\n#### Agent Health Monitoring\n\nMonitor the health status of A2A agents to ensure they are operational:\n\n```rust\nuse inference_gateway_adk::client::A2AClient;\n\n// Check agent health\nlet health = client.get_health().await?;\n\n// Process health status\nmatch health.status.as_str() {\n    \"healthy\" =\u003e println!(\"Agent is healthy\"),\n    \"degraded\" =\u003e println!(\"Agent is degraded - some functionality may be limited\"),\n    \"unhealthy\" =\u003e println!(\"Agent is unhealthy - may not be able to process requests\"),\n    _ =\u003e println!(\"Unknown health status: {}\", health.status),\n}\n```\n\n**Health Status Values:**\n\n- `healthy`: Agent is fully operational\n- `degraded`: Agent is partially operational (some functionality may be limited)\n- `unhealthy`: Agent is not operational or experiencing significant issues\n\n**Use Cases:**\n\n- Monitor agent availability in distributed systems\n- Implement health checks for load balancers\n- Detect and respond to agent failures\n- Service discovery and routing decisions\n\n#### LLM Client\n\nCreate OpenAI-compatible LLM clients for agents:\n\n```rust\nuse inference_gateway_adk::llm::OpenAICompatibleClient;\n\n// Create LLM client with configuration\nlet llm_client = OpenAICompatibleClient::new(agent_config).await?;\n\n// Use with agent builder\nlet agent = AgentBuilder::new()\n    .with_llm_client(llm_client)\n    .build()\n    .await?;\n```\n\n### Configuration\n\nThe configuration is managed through environment variables and the config module:\n\n```rust\nuse inference_gateway_adk::config::{Config, AgentConfig};\n\n#[derive(Debug, Clone)]\npub struct Config {\n    pub agent_url: String,                           // AGENT_URL (default: http://helloworld-agent:8080)\n    pub debug: bool,                                 // DEBUG (default: false)\n    pub port: u16,                                   // PORT (default: 8080)\n    pub streaming_status_update_interval: Duration,  // STREAMING_STATUS_UPDATE_INTERVAL (default: 1s)\n    pub agent_config: AgentConfig,                   // AGENT_CLIENT_*\n    pub capabilities_config: CapabilitiesConfig,     // CAPABILITIES_*\n    pub tls_config: Option\u003cTlsConfig\u003e,               // TLS_*\n    pub auth_config: Option\u003cAuthConfig\u003e,             // AUTH_*\n    pub queue_config: QueueConfig,                   // QUEUE_*\n    pub server_config: ServerConfig,                 // SERVER_*\n    pub telemetry_config: TelemetryConfig,           // TELEMETRY_*\n}\n\n#[derive(Debug, Clone)]\npub struct AgentConfig {\n    pub provider: String,                    // AGENT_CLIENT_PROVIDER\n    pub model: String,                       // AGENT_CLIENT_MODEL\n    pub base_url: Option\u003cString\u003e,            // AGENT_CLIENT_BASE_URL\n    pub api_key: Option\u003cString\u003e,             // AGENT_CLIENT_API_KEY\n    pub timeout: Duration,                   // AGENT_CLIENT_TIMEOUT (default: 30s)\n    pub max_retries: u32,                    // AGENT_CLIENT_MAX_RETRIES (default: 3)\n    pub max_chat_completion_iterations: u32, // AGENT_CLIENT_MAX_CHAT_COMPLETION_ITERATIONS (default: 10)\n    pub max_tokens: u32,                     // AGENT_CLIENT_MAX_TOKENS (default: 4096)\n    pub temperature: f32,                    // AGENT_CLIENT_TEMPERATURE (default: 0.7)\n    pub system_prompt: Option\u003cString\u003e,       // AGENT_CLIENT_SYSTEM_PROMPT\n}\n```\n\n## 🔧 Advanced Usage\n\n### Building Custom Agents with AgentBuilder\n\nThe `AgentBuilder` provides a fluent interface for creating highly customized agents with specific configurations, LLM clients, and toolboxes.\n\n#### Basic Agent Creation\n\n```rust\nuse inference_gateway_adk::server::AgentBuilder;\nuse tracing;\n\n// Create a simple agent with defaults\nlet agent = AgentBuilder::new()\n    .build()\n    .await?;\n\n// Or use the builder pattern for more control\nlet agent = AgentBuilder::new()\n    .with_system_prompt(\"You are a helpful AI assistant specialized in customer support.\")\n    .with_max_chat_completion(15)\n    .with_max_conversation_history(30)\n    .build()\n    .await?;\n```\n\n#### Agent with Custom Configuration\n\n```rust\nuse inference_gateway_adk::config::AgentConfig;\nuse std::time::Duration;\n\nlet config = AgentConfig {\n    provider: \"openai\".to_string(),\n    model: \"gpt-4\".to_string(),\n    api_key: Some(\"your-api-key\".to_string()),\n    max_tokens: 4096,\n    temperature: 0.7,\n    max_chat_completion_iterations: 10,\n    max_conversation_history: 20,\n    system_prompt: Some(\"You are a travel planning assistant.\".to_string()),\n    ..Default::default()\n};\n\nlet agent = AgentBuilder::new()\n    .with_config(\u0026config)\n    .build()\n    .await?;\n```\n\n#### Agent with Custom LLM Client\n\n```rust\nuse inference_gateway_adk::llm::OpenAICompatibleClient;\n\n// Create a custom LLM client\nlet llm_client = OpenAICompatibleClient::new(\u0026config).await?;\n\n// Build agent with the custom client\nlet agent = AgentBuilder::new()\n    .with_llm_client(llm_client)\n    .with_system_prompt(\"You are a coding assistant.\")\n    .build()\n    .await?;\n```\n\n#### Fully Configured Agent\n\n```rust\nuse inference_gateway_adk::server::AgentBuilder;\nuse inference_gateway_sdk::{Tool, ToolType, FunctionObject};\nuse serde_json::json;\n\n// Create tools for the agent's toolbox\nlet tools = vec![\n    Tool {\n        r#type: ToolType::Function,\n        function: FunctionObject {\n            name: \"get_weather\".to_string(),\n            description: \"Get current weather for a location\".to_string(),\n            parameters: json!({\n                \"type\": \"object\",\n                \"properties\": {\n                    \"location\": {\n                        \"type\": \"string\",\n                        \"description\": \"The city and state, e.g. San Francisco, CA\"\n                    },\n                    \"unit\": {\n                        \"type\": \"string\",\n                        \"enum\": [\"celsius\", \"fahrenheit\"],\n                        \"description\": \"Temperature unit\"\n                    }\n                },\n                \"required\": [\"location\"]\n            }),\n        },\n    },\n    Tool {\n        r#type: ToolType::Function,\n        function: FunctionObject {\n            name: \"calculate\".to_string(),\n            description: \"Perform basic mathematical calculations\".to_string(),\n            parameters: json!({\n                \"type\": \"object\",\n                \"properties\": {\n                    \"expression\": {\n                        \"type\": \"string\",\n                        \"description\": \"Mathematical expression to evaluate\"\n                    }\n                },\n                \"required\": [\"expression\"]\n            }),\n        },\n    },\n];\n\n// Build a fully configured agent with toolbox\nlet agent = AgentBuilder::new()\n    .with_config(\u0026config)\n    .with_system_prompt(\"You are a helpful assistant with weather and calculation capabilities.\")\n    .with_max_chat_completion(15)\n    .with_max_conversation_history(30)\n    .with_toolbox(tools)\n    .build()\n    .await?;\n);\n\n// Build a fully configured agent\nlet agent = AgentBuilder::new()\n    .with_config(\u0026config)\n    .with_llm_client(llm_client)\n    .with_toolbox(toolbox)\n    .with_system_prompt(\"You are a comprehensive AI assistant with weather capabilities.\")\n    .with_max_chat_completion(20)\n    .with_max_conversation_history(50)\n    .build()\n    .await?;\n\n// Use the agent in your server\nlet server = A2AServerBuilder::new()\n    .with_agent(agent)\n    .with_agent_card_from_file(\".well-known/agent.json\")\n    .build()\n    .await?;\n```\n\n### Custom Tools\n\nCreate custom tools to extend your agent's capabilities using the Inference Gateway SDK's tool system:\n\n```rust\nuse inference_gateway_adk::server::AgentBuilder;\nuse inference_gateway_sdk::{Tool, ToolType, FunctionObject};\nuse serde_json::json;\n\n// Define tools for your agent's toolbox\nlet tools = vec![\n    Tool {\n        r#type: ToolType::Function,\n        function: FunctionObject {\n            name: \"get_weather\".to_string(),\n            description: \"Get current weather for a location\".to_string(),\n            parameters: json!({\n                \"type\": \"object\",\n                \"properties\": {\n                    \"location\": {\n                        \"type\": \"string\",\n                        \"description\": \"The city and state, e.g. San Francisco, CA\"\n                    },\n                    \"unit\": {\n                        \"type\": \"string\",\n                        \"enum\": [\"celsius\", \"fahrenheit\"],\n                        \"description\": \"Temperature unit (default: celsius)\"\n                    }\n                },\n                \"required\": [\"location\"]\n            }),\n        },\n    },\n    Tool {\n        r#type: ToolType::Function,\n        function: FunctionObject {\n            name: \"search_web\".to_string(),\n            description: \"Search the web for information\".to_string(),\n            parameters: json!({\n                \"type\": \"object\",\n                \"properties\": {\n                    \"query\": {\n                        \"type\": \"string\",\n                        \"description\": \"Search query\"\n                    },\n                    \"limit\": {\n                        \"type\": \"integer\",\n                        \"description\": \"Maximum number of results (default: 5)\",\n                        \"default\": 5\n                    }\n                },\n                \"required\": [\"query\"]\n            }),\n        },\n    },\n];\n\n// Create an agent with the toolbox\nlet agent = AgentBuilder::new()\n    .with_config(\u0026config)\n    .with_system_prompt(\n        \"You are a helpful assistant with access to weather information and web search. \\\n        Use the provided tools when users ask for weather or need web search results.\"\n    )\n    .with_toolbox(tools)\n    .build()\n    .await?;\n```\n\nThe toolbox integrates with the Inference Gateway SDK's function calling system. When the LLM decides to use a tool, the tool call information is automatically sent through the gateway to the configured LLM provider, which will return tool call requests that can be processed by your application logic.\n\n### Custom Task Processing\n\nImplement custom business logic for task completion:\n\n```rust\nuse inference_gateway_adk::server::{TaskProcessor, TaskResult};\nuse inference_gateway_adk::types::Message;\n\nstruct CustomTaskProcessor;\n\nimpl TaskProcessor for CustomTaskProcessor {\n    async fn process_tool_result(\u0026self, tool_call_result: \u0026str) -\u003e Option\u003cMessage\u003e {\n        // Parse the tool result\n        let result: serde_json::Value = serde_json::from_str(tool_call_result).ok()?;\n\n        // Apply your business logic\n        if should_complete_task(\u0026result) {\n            Some(Message {\n                role: \"assistant\".to_string(),\n                parts: vec![Part {\n                    kind: \"text\".to_string(),\n                    content: \"Task completed successfully!\".to_string(),\n                }],\n            })\n        } else {\n            // Return None to continue processing\n            None\n        }\n    }\n}\n\n// Set the processor when building your server\nlet server = A2AServerBuilder::new()\n    .with_task_processor(CustomTaskProcessor)\n    .with_agent_card_from_file(\".well-known/agent.json\")\n    .build()\n    .await?;\n```\n\n### Push Notifications\n\nConfigure webhook notifications to receive real-time updates when task states change:\n\n```rust\nuse inference_gateway_adk::notifications::{HttpPushNotificationSender, TaskPushNotificationConfig};\nuse inference_gateway_adk::server::TaskManager;\n\n// Create an HTTP push notification sender\nlet notification_sender = HttpPushNotificationSender::new();\n\n// Create a task manager with push notification support\nlet task_manager = TaskManager::with_notifications(\n    100, // max conversation history\n    notification_sender,\n);\n\n// Configure push notification webhooks for a task\nlet config = TaskPushNotificationConfig {\n    task_id: \"task-123\".to_string(),\n    push_notification_config: PushNotificationConfig {\n        url: \"https://your-app.com/webhooks/task-updates\".to_string(),\n        token: Some(token),\n        authentication: Some(PushNotificationAuthenticationInfo {\n            schemes: vec![\"bearer\".to_string()],\n            credentials: bearer_token,\n        }),\n    },\n};\n\n// Set the configuration\ntask_manager.set_task_push_notification_config(config).await?;\n```\n\n#### Webhook Payload\n\nWhen a task state changes, your webhook will receive a POST request with this payload:\n\n```json\n{\n  \"type\": \"task_update\",\n  \"taskId\": \"task-123\",\n  \"state\": \"completed\",\n  \"timestamp\": \"2025-06-16T10:30:00Z\",\n  \"task\": {\n    \"id\": \"task-123\",\n    \"kind\": \"task\",\n    \"status\": {\n      \"state\": \"completed\",\n      \"message\": {\n        \"role\": \"assistant\",\n        \"parts\": [{ \"kind\": \"text\", \"text\": \"Task completed successfully\" }]\n      },\n      \"timestamp\": \"2025-06-16T10:30:00Z\"\n    },\n    \"contextId\": \"context-456\",\n    \"history\": []\n  }\n}\n```\n\n### Agent Metadata\n\nAgent metadata can be configured in two ways: at build-time via environment variables (recommended for production) or at runtime via configuration.\n\n#### Build-Time Metadata (Recommended)\n\nAgent metadata is embedded directly into the binary during compilation using environment variables. This approach ensures immutable agent information and is ideal for production deployments:\n\n```bash\n# Build your application with custom metadata\nAGENT_NAME=\"Weather Assistant\" \\\nAGENT_DESCRIPTION=\"Specialized weather analysis agent\" \\\nAGENT_VERSION=\"2.0.0\" \\\ncargo build --release\n```\n\n#### Runtime Metadata Configuration\n\nFor development or when dynamic configuration is needed, you can override the build-time metadata through the server's configuration:\n\n```rust\nuse inference_gateway_adk::config::Config;\n\nlet mut config = Config::from_env()?;\n\n// Override build-time metadata for development\nconfig.agent_name = Some(\"Development Weather Assistant\".to_string());\nconfig.agent_description = Some(\"Development version with debug features\".to_string());\nconfig.agent_version = Some(\"dev-1.0.0\".to_string());\n\nlet server = A2AServerBuilder::new()\n    .with_config(config)\n    .with_agent_card_from_file(\".well-known/agent.json\")\n    .build()\n    .await?;\n```\n\n**Note:** Build-time metadata takes precedence as defaults, but can be overridden at runtime using the configuration.\n\n### Environment Configuration\n\nKey environment variables for configuring your agent:\n\n```bash\n# Server configuration\nPORT=\"8080\"\n\n# Agent metadata configuration (via build-time environment variables)\nAGENT_NAME=\"My Agent\"                       # Build-time only\nAGENT_DESCRIPTION=\"My agent description\"    # Build-time only\nAGENT_VERSION=\"1.0.0\"                      # Build-time only\nAGENT_CARD_FILE_PATH=\"./.well-known/agent.json\"    # Path to JSON AgentCard file (optional)\n\n# LLM client configuration\nAGENT_CLIENT_PROVIDER=\"openai\"              # openai, anthropic, deepseek, ollama\nAGENT_CLIENT_MODEL=\"gpt-4\"                  # Model name\nAGENT_CLIENT_API_KEY=\"your-api-key\"         # Required for AI features\nAGENT_CLIENT_BASE_URL=\"https://api.openai.com/v1\"  # Custom endpoint\nAGENT_CLIENT_MAX_TOKENS=\"4096\"              # Max tokens for completion\nAGENT_CLIENT_TEMPERATURE=\"0.7\"              # Temperature for completion\nAGENT_CLIENT_SYSTEM_PROMPT=\"You are a helpful assistant\"\n\n# Capabilities\nCAPABILITIES_STREAMING=\"true\"\nCAPABILITIES_PUSH_NOTIFICATIONS=\"true\"\nCAPABILITIES_STATE_TRANSITION_HISTORY=\"false\"\n\n# Authentication (optional)\nAUTH_ENABLE=\"false\"\nAUTH_ISSUER_URL=\"http://keycloak:8080/realms/inference-gateway-realm\"\nAUTH_CLIENT_ID=\"inference-gateway-client\"\nAUTH_CLIENT_SECRET=\"your-secret\"\n\n# TLS (optional)\nSERVER_TLS_ENABLE=\"false\"\nSERVER_TLS_CERT_PATH=\"/path/to/cert.pem\"\nSERVER_TLS_KEY_PATH=\"/path/to/key.pem\"\n```\n\n## 🌐 A2A Ecosystem\n\nThis ADK is part of the broader Inference Gateway ecosystem:\n\n### Related Projects\n\n- **[Inference Gateway](https://github.com/inference-gateway/inference-gateway)** - Unified API gateway for AI providers\n- **[Go ADK](https://github.com/inference-gateway/adk)** - Go library for building A2A agents\n- **[Go SDK](https://github.com/inference-gateway/go-sdk)** - Go client library for Inference Gateway\n- **[TypeScript SDK](https://github.com/inference-gateway/typescript-sdk)** - TypeScript/JavaScript client library\n- **[Python SDK](https://github.com/inference-gateway/python-sdk)** - Python client library\n\n### A2A Agents\n\n- **[Awesome A2A](https://github.com/inference-gateway/awesome-a2a)** - Curated list of A2A-compatible agents\n- **[Google Calendar Agent](https://github.com/inference-gateway/google-calendar-agent)** - Google Calendar integration agent\n\n## 📋 Requirements\n\n- **Rust**: 1.70 or later\n- **Dependencies**: See [Cargo.toml](./Cargo.toml) for full dependency list\n\n## 🐳 Docker Support\n\nBuild and run your A2A agent application in a container. Here's an example Dockerfile for an application using the ADK:\n\n```dockerfile\nFROM rust:1.70 AS builder\n\n# Build arguments for agent metadata\nARG AGENT_NAME=\"My A2A Agent\"\nARG AGENT_DESCRIPTION=\"A custom A2A agent built with the Rust ADK\"\nARG AGENT_VERSION=\"1.0.0\"\n\nWORKDIR /app\nCOPY Cargo.toml Cargo.lock ./\nRUN cargo fetch\n\nCOPY . .\n\n# Build with custom agent metadata\nRUN AGENT_NAME=\"${AGENT_NAME}\" \\\n    AGENT_DESCRIPTION=\"${AGENT_DESCRIPTION}\" \\\n    AGENT_VERSION=\"${AGENT_VERSION}\" \\\n    cargo build --release\n\nFROM debian:bookworm-slim\nRUN apt-get update \u0026\u0026 apt-get install -y ca-certificates \u0026\u0026 rm -rf /var/lib/apt/lists/*\nWORKDIR /app\nCOPY --from=builder /app/target/release/rust-adk .\nCMD [\"./rust-adk\"]\n```\n\n**Build with custom metadata:**\n\n```bash\ndocker build \\\n  --build-arg AGENT_NAME=\"Weather Assistant\" \\\n  --build-arg AGENT_DESCRIPTION=\"AI-powered weather forecasting agent\" \\\n  --build-arg AGENT_VERSION=\"2.0.0\" \\\n  -t my-a2a-agent .\n```\n\n## 🧪 Testing\n\nThe ADK follows table-driven testing patterns and provides comprehensive test coverage:\n\n```rust\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use tokio_test;\n\n    #[derive(Debug)]\n    struct TestCase {\n        name: \u0026'static str,\n        endpoint: \u0026'static str,\n        method: \u0026'static str,\n        expected_status: u16,\n    }\n\n    #[tokio::test]\n    async fn test_a2a_server_endpoints() {\n        let test_cases = vec![\n            TestCase {\n                name: \"health check\",\n                endpoint: \"/health\",\n                method: \"GET\",\n                expected_status: 200,\n            },\n            TestCase {\n                name: \"agent info\",\n                endpoint: \"/.well-known/agent.json\",\n                method: \"GET\",\n                expected_status: 200,\n            },\n            TestCase {\n                name: \"a2a endpoint\",\n                endpoint: \"/a2a\",\n                method: \"POST\",\n                expected_status: 200,\n            },\n        ];\n\n        for test_case in test_cases {\n            // Each test case has isolated mocks\n            let server = setup_test_server().await;\n\n            // Test implementation with table-driven approach\n            let response = make_request(\u0026server, test_case.method, test_case.endpoint).await;\n            assert_eq!(test_case.expected_status, response.status().as_u16());\n        }\n    }\n}\n```\n\nRun tests with:\n\n```bash\ntask test\n```\n\nOr directly with cargo:\n\n```bash\ncargo test\n```\n\n## 📄 License\n\nThis project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for details.\n\n## 🤝 Contributing\n\nWe welcome contributions! Here's how you can help:\n\n### Getting Started\n\n1. **Fork the repository**\n2. **Clone your fork**:\n\n   ```bash\n   git clone https://github.com/your-username/rust-adk.git\n   cd rust-adk\n   ```\n\n3. **Create a feature branch**:\n   ```bash\n   git checkout -b feature/amazing-feature\n   ```\n\n### Development Guidelines\n\n- Follow the established code style and conventions (use `rustfmt`)\n- Write table-driven tests for new functionality\n- Use early returns to simplify logic and avoid deep nesting\n- Prefer match statements over if-else chains\n- Ensure type safety with proper error handling\n- Use lowercase log messages for consistency\n\n### Before Submitting\n\n1. **Download latest schema**: `task a2a:download-schema`\n2. **Generate types**: `task a2a:generate-types`\n3. **Run linting**: `task lint`\n4. **All tests pass**: `task test`\n\n### Pull Request Process\n\n1. Update documentation for any new features\n2. Add tests for new functionality\n3. Ensure all CI checks pass\n4. Request review from maintainers\n\nFor more details, see [CONTRIBUTING.md](./CONTRIBUTING.md).\n\n## 📞 Support\n\n### Issues \u0026 Questions\n\n- **Bug Reports**: [GitHub Issues](https://github.com/inference-gateway/rust-adk/issues)\n- **Documentation**: [Official Docs](https://docs.inference-gateway.com)\n\n## 🔗 Resources\n\n### Documentation\n\n- [A2A Protocol Specification](https://github.com/inference-gateway/schemas/tree/main/a2a)\n- [API Documentation](https://docs.inference-gateway.com/a2a)\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eBuilt with ❤️ by the Inference Gateway team\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/inference-gateway\"\u003eGitHub\u003c/a\u003e •\n  \u003ca href=\"https://docs.inference-gateway.com\"\u003eDocumentation\u003c/a\u003e\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finference-gateway%2Frust-adk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finference-gateway%2Frust-adk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finference-gateway%2Frust-adk/lists"}