{"id":41023845,"url":"https://github.com/traylinx/traylinx-auth-client-py","last_synced_at":"2026-01-22T09:37:36.192Z","repository":{"id":329251440,"uuid":"1090300745","full_name":"traylinx/traylinx-auth-client-py","owner":"traylinx","description":"Enterprise-grade Python authentication client for Traylinx Sentinel API with full A2A Protocol support","archived":false,"fork":false,"pushed_at":"2025-12-20T14:36:42.000Z","size":108,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-21T16:18:14.285Z","etag":null,"topics":["a2a","agent-communication","agent2agent","authentication","fastapi","jwt","microservices","oauth2","python","sdk","sentinel","traylinx"],"latest_commit_sha":null,"homepage":null,"language":"Python","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/traylinx.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-05T13:39:18.000Z","updated_at":"2025-12-20T14:36:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/traylinx/traylinx-auth-client-py","commit_stats":null,"previous_names":["traylinx/traylinx-auth-client-py"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/traylinx/traylinx-auth-client-py","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traylinx%2Ftraylinx-auth-client-py","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traylinx%2Ftraylinx-auth-client-py/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traylinx%2Ftraylinx-auth-client-py/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traylinx%2Ftraylinx-auth-client-py/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/traylinx","download_url":"https://codeload.github.com/traylinx/traylinx-auth-client-py/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traylinx%2Ftraylinx-auth-client-py/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28660770,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"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","agent-communication","agent2agent","authentication","fastapi","jwt","microservices","oauth2","python","sdk","sentinel","traylinx"],"created_at":"2026-01-22T09:37:36.051Z","updated_at":"2026-01-22T09:37:36.183Z","avatar_url":"https://github.com/traylinx.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Traylinx Auth Client (Python)\n\n[![PyPI version](https://badge.fury.io/py/traylinx-auth-client.svg)](https://badge.fury.io/py/traylinx-auth-client)\n[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA robust, enterprise-grade Python library for Traylinx Sentinel Agent-to-Agent (A2A) authentication. This client provides secure token management, automatic retry logic, comprehensive error handling, and seamless integration with FastAPI applications.\n\n## 🚀 Features\n\n- **🔐 Dual Token Authentication**: Handles both `access_token` and `agent_secret_token` with automatic refresh\n- **🛡️ Enterprise Security**: Input validation, secure credential handling, and comprehensive error management\n- **⚡ High Performance**: Connection pooling, automatic retries with exponential backoff, and efficient token caching\n- **🔄 Thread-Safe**: Built-in thread safety for concurrent applications and production environments\n- **🎯 FastAPI Integration**: Simple decorators for protecting endpoints with A2A authentication\n- **📡 JSON-RPC Support**: Full support for A2A RPC method calls with automatic credential detection\n- **🔧 Zero Configuration**: Works with environment variables out of the box\n- **📊 Production Ready**: Configurable logging, monitoring, and comprehensive error handling\n\n## 📦 Installation\n\n### Using pip\n\n```bash\npip install traylinx-auth-client\n```\n\n### Using Poetry\n\n```bash\npoetry add traylinx-auth-client\n```\n\n### Requirements\n\n- Python 3.8 or higher\n- `requests` \u003e= 2.25.0\n- `pydantic` \u003e= 2.0.0\n\n## ⚡ Quick Start (5 lines)\n\n```python\nfrom traylinx_auth_client import make_a2a_request\n\n# Set environment variables: TRAYLINX_CLIENT_ID, TRAYLINX_CLIENT_SECRET, \n# TRAYLINX_API_BASE_URL, TRAYLINX_AGENT_USER_ID\n\n# Make authenticated request to another agent\nresponse = make_a2a_request(\"GET\", \"https://other-agent.com/api/data\")\nprint(response)  # JSON response from the agent\n```\n\n## 🔧 Configuration\n\n### Environment Variables\n\nSet these environment variables for your agent:\n\n```bash\nexport TRAYLINX_CLIENT_ID=\"your-client-id\"\nexport TRAYLINX_CLIENT_SECRET=\"your-client-secret\"  \nexport TRAYLINX_API_BASE_URL=\"https://auth.traylinx.com\"\nexport TRAYLINX_AGENT_USER_ID=\"12345678-1234-1234-1234-123456789abc\"\n```\n\n### Programmatic Configuration\n\n```python\nfrom traylinx_auth_client import TraylinxAuthClient\n\nclient = TraylinxAuthClient(\n    client_id=\"your-client-id\",\n    client_secret=\"your-client-secret\",\n    api_base_url=\"https://auth.traylinx.com\",\n    agent_user_id=\"12345678-1234-1234-1234-123456789abc\",\n    timeout=30,           # Request timeout in seconds\n    max_retries=3,        # Maximum retry attempts\n    retry_delay=1.0,      # Base delay between retries\n    cache_tokens=True,    # Enable token caching\n    log_level=\"INFO\"      # Logging level\n)\n```\n\n## 📖 Usage Examples\n\n### Making Authenticated Requests\n\n#### Simple Function Approach\n\n```python\nfrom traylinx_auth_client import make_a2a_request\n\n# GET request\ndata = make_a2a_request(\"GET\", \"https://other-agent.com/api/users\")\n\n# POST request with JSON data\nresult = make_a2a_request(\n    \"POST\", \n    \"https://other-agent.com/api/process\",\n    json={\"items\": [\"item1\", \"item2\"]},\n    timeout=60\n)\n\n# PUT request with custom headers\nresponse = make_a2a_request(\n    \"PUT\",\n    \"https://other-agent.com/api/update/123\",\n    json={\"status\": \"completed\"},\n    headers={\"X-Custom-Header\": \"value\"}\n)\n```\n\n#### Manual Header Management\n\n```python\nfrom traylinx_auth_client import get_agent_request_headers\nimport requests\n\n# Get headers for calling other agents\nheaders = get_agent_request_headers()\n\n# Make authenticated request\nresponse = requests.get(\n    \"https://other-agent.com/api/data\",\n    headers=headers\n)\n\n# Headers include:\n# {\n#     \"X-Agent-Secret-Token\": \"your-agent-secret-token\",\n#     \"X-Agent-User-Id\": \"your-agent-user-id\"\n# }\n```\n\n### Protecting FastAPI Endpoints\n\n#### Simple Decorator Approach\n\n```python\nfrom fastapi import FastAPI, Request\nfrom traylinx_auth_client import require_a2a_auth\n\napp = FastAPI()\n\n@app.get(\"/protected\")\n@require_a2a_auth\nasync def protected_endpoint(request: Request):\n    return {\"message\": \"This endpoint requires A2A authentication\"}\n\n@app.post(\"/process\")\n@require_a2a_auth\nasync def process_data(request: Request, data: dict):\n    # This endpoint is automatically protected\n    return {\"processed\": data}\n```\n\n#### Manual Validation\n\n```python\nfrom fastapi import FastAPI, Request, HTTPException\nfrom traylinx_auth_client import validate_a2a_request\n\napp = FastAPI()\n\n@app.post(\"/manual-validation\")\nasync def manual_validation(request: Request):\n    if not validate_a2a_request(request.headers):\n        raise HTTPException(status_code=401, detail=\"Invalid A2A token\")\n    \n    return {\"message\": \"Token is valid\"}\n```\n\n#### Dual Authentication Support (A2A + Bearer)\n\n```python\nfrom traylinx_auth_client import require_dual_auth, detect_auth_mode\n\n@app.get(\"/flexible-auth\")\n@require_dual_auth  # Supports both Bearer tokens and custom headers\nasync def flexible_endpoint(request: Request):\n    auth_mode = detect_auth_mode(request.headers)\n    return {\"auth_mode\": auth_mode, \"message\": \"Authenticated successfully\"}\n```\n\n## 🔧 Advanced Usage\n\n### Using the Client Directly\n\n```python\nfrom traylinx_auth_client import TraylinxAuthClient\n\n# Create client with custom configuration\nclient = TraylinxAuthClient(\n    timeout=60,\n    max_retries=5,\n    retry_delay=2.0\n)\n\n# Get individual tokens\naccess_token = client.get_access_token()\nagent_secret_token = client.get_agent_secret_token()\n\n# Get different header types\nauth_headers = client.get_request_headers()      # For auth service calls\nagent_headers = client.get_agent_request_headers()  # For agent calls\na2a_headers = client.get_a2a_headers()          # A2A-compatible format\n\n# Validate incoming tokens\nis_valid = client.validate_token(\n    agent_secret_token=\"incoming-token\",\n    agent_user_id=\"sender-agent-id\"\n)\n\n# Context manager for automatic cleanup\nwith TraylinxAuthClient() as client:\n    response = client.rpc_health_check()\n```\n\n### JSON-RPC Method Calls\n\n```python\nfrom traylinx_auth_client import TraylinxAuthClient\n\nclient = TraylinxAuthClient()\n\n# Built-in RPC methods\nresult = client.rpc_introspect_token(\n    agent_secret_token=\"token-to-validate\",\n    agent_user_id=\"agent-id\"\n)\n\ncapabilities = client.rpc_get_capabilities()\nhealth = client.rpc_health_check()\n\n# Custom RPC calls\nresponse = client.rpc_call(\n    method=\"custom_method\",\n    params={\"param1\": \"value1\"},\n    rpc_url=\"https://custom-agent.com/a2a/rpc\"\n)\n\n# RPC call with explicit credential control\nresponse = client.rpc_call(\n    method=\"auth_service_method\",\n    params={},\n    include_agent_credentials=False  # Uses only access_token\n)\n```\n\n### Error Handling\n\n```python\nfrom traylinx_auth_client import (\n    TraylinxAuthClient, \n    AuthenticationError, \n    NetworkError, \n    ValidationError,\n    TokenExpiredError\n)\n\ntry:\n    client = TraylinxAuthClient(\n        client_id=\"invalid-id\",\n        client_secret=\"invalid-secret\"\n    )\n    response = client.rpc_health_check()\n    \nexcept ValidationError as e:\n    print(f\"Configuration error: {e}\")\n    print(f\"Error code: {e.error_code}\")\n    \nexcept AuthenticationError as e:\n    print(f\"Authentication failed: {e}\")\n    print(f\"Status code: {e.status_code}\")\n    \nexcept NetworkError as e:\n    print(f\"Network error: {e}\")\n    if e.error_code == \"TIMEOUT\":\n        print(\"Request timed out - check network connectivity\")\n    elif e.error_code == \"RATE_LIMIT\":\n        print(\"Rate limited - retry after delay\")\n        \nexcept TokenExpiredError as e:\n    print(f\"Token expired: {e}\")\n    # Token will be automatically refreshed on next request\n```\n\n### Concurrent Usage\n\n```python\nimport threading\nfrom traylinx_auth_client import TraylinxAuthClient\n\n# Thread-safe client usage\nclient = TraylinxAuthClient()\n\ndef worker_function(worker_id):\n    try:\n        # Each thread can safely use the same client\n        headers = client.get_agent_request_headers()\n        response = make_a2a_request(\"GET\", f\"https://api.com/data/{worker_id}\")\n        print(f\"Worker {worker_id}: {response}\")\n    except Exception as e:\n        print(f\"Worker {worker_id} error: {e}\")\n\n# Create multiple threads\nthreads = []\nfor i in range(10):\n    thread = threading.Thread(target=worker_function, args=(i,))\n    threads.append(thread)\n    thread.start()\n\n# Wait for all threads to complete\nfor thread in threads:\n    thread.join()\n```\n\n## 📚 Complete API Reference\n\n### Core Functions\n\n#### `make_a2a_request(method: str, url: str, **kwargs) -\u003e dict`\n\nMake an authenticated A2A request to another agent.\n\n**Parameters:**\n- `method` (str): HTTP method (GET, POST, PUT, DELETE, etc.)\n- `url` (str): Target agent's URL\n- `**kwargs`: Additional arguments for `requests.request()`\n\n**Returns:**\n- `dict`: JSON response from the target agent\n\n**Raises:**\n- `NetworkError`: For network-related issues\n- `AuthenticationError`: For authentication failures\n- `ValidationError`: For invalid parameters\n\n**Example:**\n```python\nresponse = make_a2a_request(\"POST\", \"https://agent.com/api\", json={\"key\": \"value\"})\n```\n\n#### `get_request_headers() -\u003e dict`\n\nReturns headers for calling the auth service (includes access_token).\n\n**Returns:**\n```python\n{\n    \"Authorization\": \"Bearer \u003caccess_token\u003e\",\n    \"X-Agent-Secret-Token\": \"\u003cagent_secret_token\u003e\",\n    \"X-Agent-User-Id\": \"\u003cagent_user_id\u003e\"\n}\n```\n\n#### `get_agent_request_headers() -\u003e dict`\n\nReturns headers for calling other agents (ONLY agent_secret_token).\n\n**Returns:**\n```python\n{\n    \"X-Agent-Secret-Token\": \"\u003cagent_secret_token\u003e\",\n    \"X-Agent-User-Id\": \"\u003cagent_user_id\u003e\"\n}\n```\n\n#### `get_a2a_request_headers() -\u003e dict`\n\nReturns A2A-compatible headers using Bearer token format.\n\n**Returns:**\n```python\n{\n    \"Authorization\": \"Bearer \u003cagent_secret_token\u003e\",\n    \"X-Agent-User-Id\": \"\u003cagent_user_id\u003e\"\n}\n```\n\n#### `require_a2a_auth(func)`\n\nDecorator that protects FastAPI endpoints with A2A authentication.\n\n**Example:**\n```python\n@app.get(\"/protected\")\n@require_a2a_auth\nasync def protected_endpoint(request: Request):\n    return {\"message\": \"Protected\"}\n```\n\n#### `require_dual_auth(func)`\n\nEnhanced decorator supporting both Bearer tokens and custom headers.\n\n#### `validate_a2a_request(headers: dict) -\u003e bool`\n\nValidates incoming A2A request headers (custom format).\n\n**Parameters:**\n- `headers` (dict): Request headers\n\n**Returns:**\n- `bool`: True if valid, False otherwise\n\n#### `validate_dual_auth_request(headers: dict) -\u003e bool`\n\nValidates incoming requests supporting both Bearer tokens and custom headers.\n\n#### `detect_auth_mode(headers: dict) -\u003e str`\n\nDetect authentication mode from request headers.\n\n**Returns:**\n- `str`: 'bearer', 'custom', or 'none'\n\n### TraylinxAuthClient Class\n\n#### Constructor\n\n```python\nTraylinxAuthClient(\n    client_id: str = None,           # OAuth client ID\n    client_secret: str = None,       # OAuth client secret  \n    api_base_url: str = None,        # Traylinx API base URL\n    agent_user_id: str = None,       # Agent user UUID\n    timeout: int = 30,               # Request timeout (seconds)\n    max_retries: int = 3,            # Maximum retry attempts\n    retry_delay: float = 1.0,        # Base retry delay (seconds)\n    cache_tokens: bool = True,       # Enable token caching\n    log_level: str = \"INFO\"          # Logging level\n)\n```\n\n**Parameters:**\n- All parameters default to corresponding environment variables\n- `timeout`: Request timeout in seconds (default: 30)\n- `max_retries`: Maximum retry attempts for failed requests (default: 3)\n- `retry_delay`: Base delay between retries in seconds (default: 1.0)\n- `cache_tokens`: Whether to cache tokens in memory (default: True)\n- `log_level`: Logging level - DEBUG, INFO, WARN, ERROR (default: \"INFO\")\n\n**Raises:**\n- `ValidationError`: If configuration parameters are invalid\n\n#### Token Management Methods\n\n##### `get_access_token() -\u003e str`\n\nGet current access token for calling auth service.\n\n**Returns:**\n- `str`: Valid access token\n\n**Raises:**\n- `TokenExpiredError`: If token is unavailable\n- `AuthenticationError`: If token fetch fails\n\n##### `get_agent_secret_token() -\u003e str`\n\nGet current agent secret token for agent-to-agent communication.\n\n**Returns:**\n- `str`: Valid agent secret token\n\n**Raises:**\n- `TokenExpiredError`: If token is unavailable\n- `AuthenticationError`: If token fetch fails\n\n#### Header Generation Methods\n\n##### `get_request_headers() -\u003e dict`\n\nGet headers for calling the auth service (includes access_token).\n\n##### `get_agent_request_headers() -\u003e dict`\n\nGet headers for calling other agents (ONLY agent_secret_token).\n\n##### `get_a2a_headers() -\u003e dict`\n\nGet A2A-compatible authentication headers using Bearer token format.\n\n#### Validation Methods\n\n##### `validate_token(agent_secret_token: str, agent_user_id: str) -\u003e bool`\n\nValidate an agent secret token against the auth service.\n\n**Parameters:**\n- `agent_secret_token` (str): Token to validate\n- `agent_user_id` (str): Agent user ID associated with token\n\n**Returns:**\n- `bool`: True if token is valid and active\n\n**Raises:**\n- `AuthenticationError`: If validation request fails\n- `NetworkError`: For network-related issues\n\n##### `validate_a2a_request(headers: dict) -\u003e bool`\n\nValidate A2A request supporting both Bearer tokens and custom headers.\n\n##### `detect_auth_mode(headers: dict) -\u003e str`\n\nDetect authentication mode from request headers.\n\n#### JSON-RPC Methods\n\n##### `rpc_call(method: str, params: dict, rpc_url: str = None, include_agent_credentials: bool = None) -\u003e dict`\n\nMake a JSON-RPC call with automatic credential detection.\n\n**Parameters:**\n- `method` (str): RPC method name\n- `params` (dict): RPC method parameters\n- `rpc_url` (str, optional): Custom RPC endpoint URL\n- `include_agent_credentials` (bool, optional): Whether to include agent credentials\n\n**Returns:**\n- `dict`: JSON-RPC response\n\n**Raises:**\n- `ValidationError`: For invalid RPC requests or parameters\n- `AuthenticationError`: For authentication failures\n- `NetworkError`: For network issues\n- `TraylinxAuthError`: For RPC-specific errors\n\n##### `rpc_introspect_token(agent_secret_token: str, agent_user_id: str) -\u003e dict`\n\nIntrospect a token via JSON-RPC.\n\n##### `rpc_get_capabilities() -\u003e dict`\n\nGet agent capabilities via JSON-RPC.\n\n##### `rpc_health_check() -\u003e dict`\n\nPerform health check via JSON-RPC.\n\n#### Context Manager Methods\n\n##### `close()`\n\nClose the HTTP session and clean up resources.\n\n##### `__enter__()` and `__exit__()`\n\nSupport for context manager usage:\n\n```python\nwith TraylinxAuthClient() as client:\n    response = client.rpc_health_check()\n# Automatically cleaned up\n```\n\n### Exception Classes\n\n#### `TraylinxAuthError`\n\nBase exception class for all TraylinxAuthClient errors.\n\n**Attributes:**\n- `error_code` (str): Specific error code\n- `status_code` (int): HTTP status code (if applicable)\n\n#### `ValidationError(TraylinxAuthError)`\n\nRaised for input validation failures.\n\n#### `AuthenticationError(TraylinxAuthError)`\n\nRaised for authentication-related failures.\n\n#### `TokenExpiredError(TraylinxAuthError)`\n\nRaised when tokens are expired or unavailable.\n\n#### `NetworkError(TraylinxAuthError)`\n\nRaised for network-related issues (timeouts, connection errors, etc.).\n\n### Configuration Classes\n\n#### `AuthConfig`\n\nPydantic model for configuration validation.\n\n**Fields:**\n- `client_id` (str): OAuth client ID\n- `client_secret` (str): OAuth client secret\n- `api_base_url` (HttpUrl): Traylinx API base URL\n- `agent_user_id` (str): Agent user UUID\n- `timeout` (int): Request timeout in seconds\n- `max_retries` (int): Maximum retry attempts\n- `retry_delay` (float): Base retry delay\n- `cache_tokens` (bool): Enable token caching\n- `log_level` (str): Logging level\n\n## 🔐 Authentication Flow\n\n### Dual Token System\n\nTraylinx uses a dual-token authentication system for enhanced security:\n\n1. **`access_token`**: Used for calling Traylinx auth service endpoints\n2. **`agent_secret_token`**: Used for agent-to-agent communication\n\n### Authentication Process\n\n```mermaid\nsequenceDiagram\n    participant Client as TraylinxAuthClient\n    participant Auth as Traylinx Sentinel API\n    participant Agent as Target Agent\n    \n    Note over Client,Auth: Initial Authentication\n    Client-\u003e\u003eAuth: POST /oauth/token (client_credentials)\n    Auth--\u003e\u003eClient: {access_token, agent_secret_token, expires_in}\n    \n    Note over Client,Auth: Calling Auth Service\n    Client-\u003e\u003eAuth: GET /a2a/rpc (Authorization: Bearer access_token)\n    Auth--\u003e\u003eClient: Response\n    \n    Note over Client,Agent: Calling Other Agents\n    Client-\u003e\u003eAgent: POST /endpoint (X-Agent-Secret-Token: agent_secret_token)\n    Agent-\u003e\u003eAuth: Validate token\n    Auth--\u003e\u003eAgent: Token valid\n    Agent--\u003e\u003eClient: Response\n```\n\n### Token Usage Matrix\n\n| Scenario | access_token | agent_secret_token | Headers |\n|----------|--------------|-------------------|---------|\n| **Auth service calls** | ✅ Required | ❌ Not used | `Authorization: Bearer \u003caccess_token\u003e` |\n| **Agent-to-agent calls** | ❌ Not used | ✅ Required | `X-Agent-Secret-Token: \u003cagent_secret_token\u003e` |\n| **A2A compatible calls** | ❌ Not used | ✅ Required | `Authorization: Bearer \u003cagent_secret_token\u003e` |\n| **Token validation** | ✅ Required | ❌ Not used | `Authorization: Bearer \u003caccess_token\u003e` |\n\n### Automatic Token Management\n\n1. **Token Acquisition**: Automatically fetches tokens using OAuth2 `client_credentials` grant\n2. **Token Caching**: Tokens cached in memory with thread-safe access\n3. **Automatic Refresh**: Expired tokens refreshed automatically before requests\n4. **Error Recovery**: Handles token expiration and authentication failures gracefully\n\n**Example token response:**\n```json\n{\n    \"access_token\": \"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...\",\n    \"agent_secret_token\": \"TqlJuJi5aJa7lz8rg9zWjbRDChND8m9PMr4bsn...\",\n    \"token_type\": \"Bearer\",\n    \"expires_in\": 7200,\n    \"scope\": \"a2a\"\n}\n```\n\n## 🛡️ Error Handling \u0026 Resilience\n\n### Comprehensive Error Management\n\nThe client provides robust error handling with specific exception types:\n\n```python\nfrom traylinx_auth_client import (\n    TraylinxAuthError,      # Base exception\n    ValidationError,        # Configuration/input validation\n    AuthenticationError,    # Authentication failures  \n    TokenExpiredError,      # Token expiration\n    NetworkError           # Network/connectivity issues\n)\n```\n\n### Automatic Retry Logic\n\n- **Exponential Backoff**: Automatic retries with increasing delays\n- **Configurable Retries**: Set `max_retries` and `retry_delay` parameters\n- **Smart Retry Logic**: Only retries on transient failures (429, 5xx errors)\n- **Connection Pooling**: Efficient connection reuse for better performance\n\n### Error Scenarios Handled\n\n| Error Type | HTTP Status | Retry | Description |\n|------------|-------------|-------|-------------|\n| `ValidationError` | 400 | ❌ | Invalid configuration or parameters |\n| `AuthenticationError` | 401 | ❌ | Invalid credentials or expired tokens |\n| `NetworkError` (Rate Limit) | 429 | ✅ | Rate limiting - automatic retry with backoff |\n| `NetworkError` (Timeout) | 408 | ✅ | Request timeout - configurable retry |\n| `NetworkError` (Server Error) | 5xx | ✅ | Server errors - automatic retry |\n| `NetworkError` (Connection) | 0 | ✅ | Connection failures - automatic retry |\n\n### Production Monitoring\n\n```python\nimport logging\nfrom traylinx_auth_client import TraylinxAuthClient, NetworkError\n\n# Configure logging\nlogging.basicConfig(level=logging.INFO)\n\nclient = TraylinxAuthClient(log_level=\"INFO\")\n\ntry:\n    response = client.rpc_health_check()\nexcept NetworkError as e:\n    if e.error_code == \"RATE_LIMIT\":\n        logging.warning(f\"Rate limited: {e}\")\n        # Implement backoff strategy\n    elif e.error_code == \"TIMEOUT\":\n        logging.error(f\"Request timeout: {e}\")\n        # Check network connectivity\n    else:\n        logging.error(f\"Network error: {e}\")\n```\n\n## 🔒 Security Best Practices\n\n### Credential Management\n\n✅ **DO:**\n- Store credentials in environment variables or secure vaults\n- Use different credentials for different environments (dev/staging/prod)\n- Regularly rotate client credentials\n- Monitor authentication failures and unusual patterns\n- Use HTTPS for all communications\n\n❌ **DON'T:**\n- Hard-code credentials in source code\n- Log sensitive data (tokens, secrets, passwords)\n- Share credentials between different applications\n- Use production credentials in development/testing\n\n### Secure Configuration\n\n```python\n# ✅ Good: Use environment variables\nclient = TraylinxAuthClient()  # Reads from env vars\n\n# ✅ Good: Use secure credential management\nimport os\nfrom your_vault import get_secret\n\nclient = TraylinxAuthClient(\n    client_id=os.getenv(\"TRAYLINX_CLIENT_ID\"),\n    client_secret=get_secret(\"traylinx_client_secret\"),\n    api_base_url=os.getenv(\"TRAYLINX_API_BASE_URL\"),\n    agent_user_id=os.getenv(\"TRAYLINX_AGENT_USER_ID\")\n)\n\n# ❌ Bad: Hard-coded credentials\nclient = TraylinxAuthClient(\n    client_id=\"hardcoded-id\",  # Never do this!\n    client_secret=\"hardcoded-secret\"  # Never do this!\n)\n```\n\n### Network Security\n\n- **TLS/HTTPS**: All communications use HTTPS with certificate validation\n- **Request Signing**: Tokens provide request authenticity\n- **Timeout Protection**: Configurable timeouts prevent hanging requests\n- **Rate Limiting**: Built-in protection against rate limiting\n\n### Logging Security\n\n```python\nimport logging\n\n# ✅ Safe logging - no sensitive data\nlogging.info(\"Authentication successful for agent %s\", agent_user_id)\nlogging.error(\"Authentication failed with status %d\", response.status_code)\n\n# ❌ Unsafe logging - exposes sensitive data\nlogging.info(\"Token: %s\", access_token)  # Never log tokens!\nlogging.debug(\"Secret: %s\", client_secret)  # Never log secrets!\n```\n\n## 🔧 Troubleshooting\n\n### Common Issues\n\n#### Authentication Failures\n\n**Problem**: `AuthenticationError: Invalid credentials`\n\n**Solutions:**\n1. Verify environment variables are set correctly\n2. Check client_id and client_secret are valid\n3. Ensure API base URL is correct\n4. Verify agent_user_id is a valid UUID\n\n```bash\n# Check environment variables\necho $TRAYLINX_CLIENT_ID\necho $TRAYLINX_CLIENT_SECRET  \necho $TRAYLINX_API_BASE_URL\necho $TRAYLINX_AGENT_USER_ID\n```\n\n#### Network Issues\n\n**Problem**: `NetworkError: Connection failed`\n\n**Solutions:**\n1. Check network connectivity to API endpoint\n2. Verify firewall/proxy settings\n3. Increase timeout value\n4. Check DNS resolution\n\n```python\n# Test connectivity\nimport requests\nresponse = requests.get(\"https://your-api-base-url/health\")\nprint(response.status_code)\n```\n\n#### Configuration Errors\n\n**Problem**: `ValidationError: Configuration validation failed`\n\n**Solutions:**\n1. Ensure agent_user_id is a valid UUID format\n2. Verify API base URL is a valid HTTPS URL\n3. Check all required parameters are provided\n\n```python\n# Validate UUID format\nimport uuid\ntry:\n    uuid.UUID(\"your-agent-user-id\")\n    print(\"Valid UUID\")\nexcept ValueError:\n    print(\"Invalid UUID format\")\n```\n\n#### Token Issues\n\n**Problem**: `TokenExpiredError: Token is not available`\n\n**Solutions:**\n1. Check if initial authentication succeeded\n2. Verify network connectivity during token refresh\n3. Check if credentials are still valid\n\n### Debug Mode\n\n```python\nimport logging\n\n# Enable debug logging\nlogging.basicConfig(level=logging.DEBUG)\n\nclient = TraylinxAuthClient(log_level=\"DEBUG\")\n# This will show detailed request/response information\n```\n\n### Performance Optimization\n\n```python\n# Optimize for high-throughput scenarios\nclient = TraylinxAuthClient(\n    timeout=60,          # Longer timeout for slow networks\n    max_retries=5,       # More retries for reliability\n    retry_delay=0.5,     # Faster initial retry\n    cache_tokens=True    # Enable token caching\n)\n\n# Use context manager for automatic cleanup\nwith TraylinxAuthClient() as client:\n    # Client automatically cleaned up after use\n    response = client.rpc_health_check()\n```\n\n## ❓ FAQ\n\n### Q: What's the difference between access_token and agent_secret_token?\n\n**A:** The `access_token` is used for calling Traylinx auth service endpoints, while `agent_secret_token` is used for agent-to-agent communication. They serve different purposes in the dual-token authentication system.\n\n### Q: How do I handle token expiration?\n\n**A:** Token expiration is handled automatically. The client will refresh tokens before they expire and retry failed requests with fresh tokens.\n\n### Q: Can I use the same client instance across multiple threads?\n\n**A:** Yes! The client is thread-safe and can be safely used across multiple threads. Token management is protected with locks.\n\n### Q: How do I customize retry behavior?\n\n**A:** Use the `max_retries` and `retry_delay` parameters:\n\n```python\nclient = TraylinxAuthClient(\n    max_retries=5,      # Retry up to 5 times\n    retry_delay=2.0     # Start with 2-second delay\n)\n```\n\n### Q: What happens if the auth service is down?\n\n**A:** The client will retry requests with exponential backoff. If all retries fail, it will raise a `NetworkError` with details about the failure.\n\n### Q: How do I validate incoming requests in my agent?\n\n**A:** Use the `@require_a2a_auth` decorator or `validate_a2a_request()` function:\n\n```python\n@app.post(\"/endpoint\")\n@require_a2a_auth\nasync def my_endpoint(request: Request):\n    return {\"status\": \"authenticated\"}\n```\n\n## 🚀 Development\n\n### Setting Up Development Environment\n\n```bash\n# Clone the repository\ngit clone https://github.com/traylinx/traylinx-auth-client-py.git\ncd traylinx-auth-client-py\n\n# Install Poetry (if not already installed)\ncurl -sSL https://install.python-poetry.org | python3 -\n\n# Install dependencies\npoetry install\n\n# Activate virtual environment\npoetry shell\n```\n\n### Running Tests\n\n```bash\n# Run all tests\npoetry run pytest\n\n# Run tests with coverage report\npoetry run pytest --cov=traylinx_auth_client --cov-report=html\n\n# Run specific test file\npoetry run pytest tests/test_client.py\n\n# Run tests with verbose output\npoetry run pytest -v\n\n# Run tests and generate coverage report\npoetry run pytest --cov=traylinx_auth_client --cov-report=term-missing\n```\n\n### Code Quality\n\n```bash\n# Format code with Black\npoetry run black traylinx_auth_client/ tests/\n\n# Lint with flake8\npoetry run flake8 traylinx_auth_client/ tests/\n\n# Type checking with mypy\npoetry run mypy traylinx_auth_client/\n\n# Security scan with bandit\npoetry run bandit -r traylinx_auth_client/\n```\n\n### Building and Publishing\n\n```bash\n# Build package\npoetry build\n\n# Check package contents\ntar -tzf dist/traylinx-auth-client-*.tar.gz\n\n# Test publish to TestPyPI\npoetry config repositories.testpypi https://test.pypi.org/legacy/\npoetry publish -r testpypi\n\n# Publish to PyPI\npoetry publish\n```\n\n### Project Structure\n\n```\ntraylinx_auth_client_py/\n├── traylinx_auth_client/\n│   ├── __init__.py          # Public API exports\n│   ├── main.py              # High-level functions and decorators\n│   ├── client.py            # Core TraylinxAuthClient class\n│   ├── config.py            # Configuration validation with Pydantic\n│   └── exceptions.py        # Custom exception hierarchy\n├── tests/\n│   ├── test_client.py       # Client class tests\n│   ├── test_config.py       # Configuration validation tests\n│   ├── test_exceptions.py   # Exception handling tests\n│   └── test_main.py         # High-level function tests\n├── pyproject.toml           # Project configuration and dependencies\n├── README.md                # This file\n├── CHANGELOG.md             # Version history\n├── CONTRIBUTING.md          # Contribution guidelines\n├── SECURITY.md              # Security policy\n└── LICENSE                  # MIT license\n```\n\n### Adding New Features\n\n1. **Create Feature Branch**: `git checkout -b feature/new-feature`\n2. **Write Tests First**: Add tests in appropriate test file\n3. **Implement Feature**: Add implementation with proper docstrings\n4. **Update Documentation**: Update README and docstrings\n5. **Run Quality Checks**: Ensure tests pass and code quality is maintained\n6. **Submit Pull Request**: Include description of changes and test results\n\n### Testing Guidelines\n\n- **Unit Tests**: Test individual functions and methods\n- **Integration Tests**: Test end-to-end authentication flows\n- **Error Tests**: Test all error conditions and edge cases\n- **Mock External Services**: Use mocks for HTTP requests to auth service\n- **Thread Safety Tests**: Test concurrent access patterns\n\n## 🤝 Contributing\n\nWe welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines.\n\n### Quick Contribution Guide\n\n1. **Fork the repository** on GitHub\n2. **Clone your fork** locally\n3. **Create a feature branch** from `main`\n4. **Make your changes** with tests\n5. **Run the test suite** to ensure everything works\n6. **Submit a pull request** with a clear description\n\n### Contribution Types\n\n- 🐛 **Bug Fixes**: Fix issues and improve reliability\n- ✨ **New Features**: Add new functionality\n- 📚 **Documentation**: Improve docs and examples\n- 🔧 **Performance**: Optimize performance and efficiency\n- 🧪 **Tests**: Add or improve test coverage\n- 🎨 **Code Quality**: Refactoring and code improvements\n\n### Code Standards\n\n- Follow PEP 8 style guidelines\n- Add type hints for all public functions\n- Write comprehensive docstrings\n- Maintain test coverage above 90%\n- Use meaningful variable and function names\n\n## 📄 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n### MIT License Summary\n\n- ✅ Commercial use allowed\n- ✅ Modification allowed  \n- ✅ Distribution allowed\n- ✅ Private use allowed\n- ❌ No warranty provided\n- ❌ No liability accepted\n\n## 🆘 Support \u0026 Community\n\n### Getting Help\n\n- 📖 **Documentation**: [Traylinx Developer Docs](https://docs.traylinx.com)\n- 🐛 **Bug Reports**: [GitHub Issues](https://github.com/traylinx/traylinx-auth-client-py/issues)\n- 💬 **Discussions**: [GitHub Discussions](https://github.com/traylinx/traylinx-auth-client-py/discussions)\n- 📧 **Email Support**: dev@traylinx.com\n\n### Reporting Issues\n\nWhen reporting issues, please include:\n\n1. **Python version** and operating system\n2. **Library version** (`pip show traylinx-auth-client`)\n3. **Minimal code example** that reproduces the issue\n4. **Full error traceback** if applicable\n5. **Expected vs actual behavior**\n\n### Feature Requests\n\nWe welcome feature requests! Please:\n\n1. Check existing issues to avoid duplicates\n2. Describe the use case and problem you're solving\n3. Provide examples of how the feature would be used\n4. Consider contributing the implementation\n\n### Security Issues\n\nFor security-related issues, please follow our [Security Policy](SECURITY.md):\n\n- 🔒 **Private Disclosure**: Email security@traylinx.com\n- ⏱️ **Response Time**: We aim to respond within 24 hours\n- 🛡️ **Responsible Disclosure**: We follow coordinated disclosure practices\n\n---\n\n**Made with ❤️ by the Traylinx Team**\n\n[![GitHub stars](https://img.shields.io/github/stars/traylinx/traylinx-auth-client-py?style=social)](https://github.com/traylinx/traylinx-auth-client-py)\n[![PyPI downloads](https://img.shields.io/pypi/dm/traylinx-auth-client)](https://pypi.org/project/traylinx-auth-client/)\n[![GitHub contributors](https://img.shields.io/github/contributors/traylinx/traylinx-auth-client-py)](https://github.com/traylinx/traylinx-auth-client-py/graphs/contributors)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftraylinx%2Ftraylinx-auth-client-py","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftraylinx%2Ftraylinx-auth-client-py","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftraylinx%2Ftraylinx-auth-client-py/lists"}