Skip to main content

Recipe Serve Advanced Features

This guide covers advanced server features including rate limiting, metrics, admin endpoints, workers, and OpenTelemetry tracing.

Rate Limiting

Protect your server from abuse with configurable rate limiting.

Configuration

from praisonai.recipe.serve import create_app, serve

# Create app with rate limiting
app = create_app(config={
    "rate_limit": 100,  # 100 requests per minute per client
    "rate_limit_exempt_paths": ["/health", "/metrics"]
})

# Or via serve()
serve(
    host="127.0.0.1",
    port=8765,
    config={"rate_limit": 100}
)

Rate Limiter Class

from praisonai.recipe.serve import create_rate_limiter, RateLimiter

# Create rate limiter
limiter = create_rate_limiter(requests_per_minute=100)

# Check if request is allowed
allowed, retry_after = limiter.check("client-ip-or-key")

if not allowed:
    print(f"Rate limited. Retry after {retry_after} seconds")

Response Format

When rate limited, clients receive:
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests"
  }
}
With headers:
  • Retry-After: <seconds>

Request Size Limits

Prevent oversized payloads from overwhelming your server.

Configuration

from praisonai.recipe.serve import create_app, DEFAULT_MAX_REQUEST_SIZE

# Default is 10MB
print(f"Default max size: {DEFAULT_MAX_REQUEST_SIZE} bytes")

# Custom size limit
app = create_app(config={
    "max_request_size": 5 * 1024 * 1024  # 5MB
})

Response Format

When request is too large:
{
  "error": {
    "code": "request_too_large",
    "message": "Request body too large. Max: 5242880 bytes"
  }
}

Metrics Endpoint

Expose Prometheus-format metrics for monitoring.

Enable Metrics

from praisonai.recipe.serve import create_app

app = create_app(config={
    "enable_metrics": True
})

Metrics Format

GET /metrics
Response (Prometheus exposition format):
# HELP praisonai_http_requests_total Total HTTP requests
# TYPE praisonai_http_requests_total counter
praisonai_http_requests_total{path="/health",method="GET",status="200"} 42

# HELP praisonai_http_request_duration_seconds HTTP request duration
# TYPE praisonai_http_request_duration_seconds histogram
praisonai_http_request_duration_seconds_sum{path="/health",method="GET"} 0.123456
praisonai_http_request_duration_seconds_count{path="/health",method="GET"} 42

# HELP praisonai_http_errors_total Total HTTP errors
# TYPE praisonai_http_errors_total counter
praisonai_http_errors_total{path="/v1/recipes/run",method="POST",error_type="client_error"} 5

Using with Prometheus

# prometheus.yml
scrape_configs:
  - job_name: 'praisonai-recipe'
    static_configs:
      - targets: ['localhost:8765']
    metrics_path: '/metrics'

Admin Reload Endpoint

Hot-reload recipes without restarting the server.

Enable Admin Endpoints

from praisonai.recipe.serve import create_app

app = create_app(config={
    "enable_admin": True,
    "auth": "api-key",
    "api_key": "admin-secret-key"
})

Reload Recipes

curl -X POST http://localhost:8765/admin/reload \
  -H "X-API-Key: admin-secret-key"
Response:
{
  "status": "reloaded",
  "timestamp": "2024-01-15T10:30:00Z"
}

Programmatic Reload

from praisonai.recipe.core import reload_registry

# Clear cached recipes and reload
reload_registry()

Workers (Multi-Process)

Scale with multiple worker processes.

Configuration

from praisonai.recipe.serve import serve

# Start with 4 workers
serve(
    host="0.0.0.0",
    port=8765,
    workers=4,
    config={"auth": "api-key", "api_key": "secret"}
)

Notes

  • Workers > 1 automatically disables hot reload
  • Each worker has its own rate limiter state (use Redis for distributed limiting)
  • Recommended: 2 * CPU cores + 1

OpenTelemetry Tracing

Distributed tracing with OpenTelemetry.

Configuration

from praisonai.recipe.serve import serve

serve(
    host="127.0.0.1",
    port=8765,
    config={
        "trace_exporter": "otlp",  # otlp, jaeger, zipkin
        "otlp_endpoint": "http://localhost:4317",
        "service_name": "praisonai-recipe"
    }
)

Supported Exporters

ExporterConfig KeyDefault Endpoint
OTLPotlp_endpointhttp://localhost:4317
Jaegerjaeger_host, jaeger_portlocalhost:6831
Zipkinzipkin_endpointhttp://localhost:9411/api/v2/spans

Install Dependencies

# OTLP
pip install opentelemetry-sdk opentelemetry-exporter-otlp

# Jaeger
pip install opentelemetry-sdk opentelemetry-exporter-jaeger

# Zipkin
pip install opentelemetry-sdk opentelemetry-exporter-zipkin

Lazy Import

OpenTelemetry dependencies are lazily imported. If not installed, a warning is logged but the server continues to work.

OpenAPI Specification

Get the OpenAPI spec for your server.

Endpoint

curl http://localhost:8765/openapi.json

Response

{
  "openapi": "3.0.3",
  "info": {
    "title": "PraisonAI Recipe Runner API",
    "version": "2.7.1"
  },
  "paths": {
    "/health": {...},
    "/v1/recipes": {...},
    "/v1/recipes/run": {...},
    "/metrics": {...},
    "/admin/reload": {...}
  }
}

Template Search Paths

Configure where recipes are discovered.

Search Order

  1. PRAISONAI_RECIPE_PATH environment variable
  2. ./recipes in current directory
  3. ~/.praison/recipes in home directory
  4. Agent-Recipes package (if installed)
  5. Built-in templates

Get Search Paths

from praisonai.recipe.core import get_template_search_paths

paths = get_template_search_paths()
for path in paths:
    print(f"Searching: {path}")

Custom Path

export PRAISONAI_RECIPE_PATH="/custom/recipes:/another/path"
praisonai recipe serve

Complete Example

from praisonai.recipe.serve import serve

# Production-ready configuration
serve(
    host="0.0.0.0",
    port=8765,
    workers=4,
    config={
        # Authentication
        "auth": "api-key",
        "api_key": "production-secret-key",
        
        # Rate limiting
        "rate_limit": 100,
        
        # Request size
        "max_request_size": 10 * 1024 * 1024,  # 10MB
        
        # Monitoring
        "enable_metrics": True,
        "enable_admin": True,
        
        # Tracing
        "trace_exporter": "otlp",
        "otlp_endpoint": "http://otel-collector:4317",
        "service_name": "praisonai-recipe-prod",
        
        # CORS
        "cors_origins": "https://app.example.com"
    }
)

Configuration Reference

KeyTypeDefaultDescription
rate_limitint0 (disabled)Requests per minute per client
rate_limit_exempt_pathslist["/health", "/metrics"]Paths exempt from rate limiting
max_request_sizeint10485760 (10MB)Maximum request body size
enable_metricsboolfalseEnable /metrics endpoint
enable_adminboolfalseEnable /admin/* endpoints
trace_exporterstr”none”Tracing exporter (none, otlp, jaeger, zipkin)
otlp_endpointstrhttp://localhost:4317OTLP collector endpoint
service_namestr”praisonai-recipe”Service name for tracing

Next Steps