Skip to content
Back to skills

2641 Llm Api Scaffold 72ffabe8

ASecurity

Generate production-ready LLM API integration boilerplate

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
devopspythongodockertestingapi

Works with

  • cli
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2641-llm-api-scaffold_72ffabe8 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2641 Llm Api Scaffold 72ffabe8?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2641 Llm Api Scaffold 72ffabe8
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2641-llm-api-scaffold-72ffabe8/badge)](https://www.skillsdirectory.com/skills/tools-only-2641-llm-api-scaffold-72ffabe8)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
---
name: llm-api-scaffold
description: Generate production-ready LLM API integration boilerplate
shortcut: las
category: other
type: command
version: 1.0.0
author: Jeremy Longshore
estimated_time: 5-10 minutes
---
# LLM API Scaffold Generator

Generate complete, production-ready LLM API integration code with error handling, rate limiting, caching, monitoring, and best practices built-in.

## What You'll Get

When you run this command, you'll receive:

1. **Complete API client** with retry logic and error handling
2. **Rate limiting** (token bucket algorithm)
3. **Caching layer** (in-memory + Redis)
4. **Cost tracking** and monitoring
5. **Multi-provider support** with fallback
6. **Streaming responses** implementation
7. **Testing suite** with mocks
8. **Docker deployment** configuration

## Usage

```
/llm-api-scaffold <provider> [options]
```

**Providers:** `anthropic`, `openai`, `multi` (both)

**Examples:**
- `/las anthropic` - Generate Anthropic Claude integration
- `/las openai` - Generate OpenAI GPT integration
- `/las multi` - Generate multi-provider with fallback

## Generated Output

### Example: Anthropic Claude Integration

**Input:**
```
/las anthropic
```

**Output:**

#### 1. Project Structure

```
llm-api-integration/
├── src/
│   ├── client/
│   │   ├── __init__.py
│   │   ├── base.py            # Base client interface
│   │   ├── anthropic_client.py # Anthropic implementation
│   │   └── rate_limiter.py     # Rate limiting
│   ├── cache/
│   │   ├── __init__.py
│   │   ├── memory_cache.py     # In-memory cache
│   │   └── redis_cache.py      # Redis cache
│   ├── monitoring/
│   │   ├── __init__.py
│   │   ├── metrics.py          # Prometheus metrics
│   │   └── cost_tracker.py     # Cost tracking
│   └── utils/
│       ├── __init__.py
│       └── retry.py            # Retry logic
├── tests/
│   ├── __init__.py
│   ├── test_client.py
│   └── test_cache.py
├── docker/
│   ├── Dockerfile
│   └── docker-compose.yml
├── requirements.txt
├── .env.example
└── README.md
```

#### 2. Base Client (src/client/base.py)

```python
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Optional, AsyncGenerator

@dataclass
class CompletionRequest:
    """Standardized completion request."""
    prompt: str
    max_tokens: int = 1024
    temperature: float = 1.0
    model: Optional[str] = None
    stream: bool = False

@dataclass
class CompletionResponse:
    """Standardized completion response."""
    content: str
    usage: dict
    model: str
    latency: float
    cached: bool = False
    provider: str = ""

class BaseLLMClient(ABC):
    """Abstract base class for LLM clients."""

    @abstractmethod
    async def complete(self, request: CompletionRequest) -> CompletionResponse:
        """Generate completion."""
        pass

    @abstractmethod
    async def stream_complete(
        self,
        request: CompletionRequest
    ) -> AsyncGenerator[str, None]:
        """Stream completion tokens."""
        pass

    @abstractmethod
    def count_tokens(self, text: str) -> int:
        """Count tokens in text."""
        pass
```

#### 3. Anthropic Client (src/client/anthropic_client.py)

```python
import time
import asyncio
from anthropic import AsyncAnthropic, RateLimitError, APIError
from .base import BaseLLMClient, CompletionRequest, CompletionResponse
from .rate_limiter import TokenBucket
from ..cache import CacheManager
from ..monitoring import MetricsCollector, CostTracker
from ..utils.retry import retry_with_backoff

class AnthropicClient(BaseLLMClient):
    """Production-ready Anthropic Claude client."""

    def __init__(
        self,
        api_key: str,
        model: str = "claude-3-haiku-20240307",
        requests_per_minute: int = 50,
        enable_cache: bool = True,
        enable_metrics: bool = True
    ):
        """Initialize Anthropic client with production features.

        Args:
            api_key: Anthropic API key
            model: Default model to use
            requests_per_minute: Rate limit (adjust based on tier)
            enable_cache: Enable response caching
            enable_metrics: Enable metrics collection
        """
        self.client = AsyncAnthropic(api_key=api_key)
        self.model = model
        self.rate_limiter = TokenBucket(
            capacity=requests_per_minute,
            refill_rate=requests_per_minute / 60.0
        )

        self.cache = CacheManager() if enable_cache else None
        self.metrics = MetricsCollector() if enable_metrics else None
        self.cost_tracker = CostTracker()

    @retry_with_backoff(max_retries=3, base_delay=1.0)
    async def complete(self, request: CompletionRequest) -> CompletionResponse:
        """Generate completion with caching, rate limiting, and monitoring.

        Args:
            request: Completion request parameters

        Returns:
            CompletionResponse with content and metadata
        """
        # Rate limiting
        await self.rate_limiter.wait_for_token()

        # Check cache
        if self.cache:
            cache_key = self._generate_cache_key(request)
            cached = await self.cache.get(cache_key)
            if cached:
                self.metrics and self.metrics.record_cache_hit()
                return CompletionResponse(**cached, cached=True)

        # Make API call
        start_time = time.time()
        model = request.model or self.model

        try:
            message = await self.client.messages.create(
                model=model,
                max_tokens=request.max_tokens,
                temperature=request.temperature,
                messages=[{"role": "user", "content": request.prompt}]
            )

            latency = time.time() - start_time

            # Build response
            response = CompletionResponse(
                content=message.content[0].text,
                usage={
                    "input_tokens": message.usage.input_tokens,
                    "output_tokens": message.usage.output_tokens
                },
                model=model,
                latency=latency,
                provider="anthropic"
            )

            # Cache response
            if self.cache:
                await self.cache.set(cache_key, response.__dict__, ttl=3600)

            # Track metrics
            if self.metrics:
                self.metrics.record_request(
                    provider="anthropic",
                    model=model,
                    latency=latency,
                    tokens=response.usage["output_tokens"]
                )

            # Track costs
            cost = self.cost_tracker.calculate_cost(
                input_tokens=response.usage["input_tokens"],
                output_tokens=response.usage["output_tokens"],
                model=model
            )
            self.cost_tracker.log_request(model, cost)

            return response

        except RateLimitError as e:
            self.metrics and self.metrics.record_error("rate_limit")
            raise

        except APIError as e:
            self.metrics and self.metrics.record_error("api_error")
            raise

    async def stream_complete(
        self,
        request: CompletionRequest
    ) -> AsyncGenerator[str, None]:
        """Stream completion tokens as they're generated.

        Args:
            request: Completion request parameters

        Yields:
            Individual tokens as strings
        """
        await self.rate_limiter.wait_for_token()

        model = request.model or self.model
        start_time = time.time()

        async with self.client.messages.stream(
            model=model,
            max_tokens=request.max_tokens,
            temperature=request.temperature,
            messages=[{"role": "user", "content": request.prompt}]
        ) as stream:
            async for text in stream.text_stream:
                yield text

            # Get final message for metrics
            message = await stream.get_final_message()
            latency = time.time() - start_time

            # Track metrics
            if self.metrics:
                self.metrics.record_request(
                    provider="anthropic",
                    model=model,
                    latency=latency,
                    tokens=message.usage.output_tokens
                )

            # Track costs
            cost = self.cost_tracker.calculate_cost(
                input_tokens=message.usage.input_tokens,
                output_tokens=message.usage.output_tokens,
                model=model
            )
            self.cost_tracker.log_request(model, cost)

    def count_tokens(self, text: str) -> int:
        """Estimate token count (Claude uses ~4 chars per token)."""
        return len(text) // 4

    def _generate_cache_key(self, request: CompletionRequest) -> str:
        """Generate cache key from request parameters."""
        import hashlib
        key_string = f"{request.prompt}:{request.model}:{request.max_tokens}:{request.temperature}"
        return hashlib.md5(key_string.encode()).hexdigest()

    async def get_stats(self) -> dict:
        """Get usage statistics."""
        return {
            "cost_tracker": self.cost_tracker.get_stats(),
            "metrics": self.metrics.get_stats() if self.metrics else {}
        }
```

#### 4. Rate Limiter (src/client/rate_limiter.py)

```python
import time
import asyncio
from threading import Lock

class TokenBucket:
    """Thread-safe token bucket for rate limiting."""

    def __init__(self, capacity: int, refill_rate: float):
        """
        Args:
            capacity: Maximum tokens (e.g., 50 requests)
            refill_rate: Tokens per second (e.g., 50/60 = 0.833 req/s)
        """
        self.capacity = capacity
        self.tokens = capacity
        self.refill_rate = refill_rate
        self.last_refill = time.time()
        self.lock = Lock()

    def _refill(self):
        """Refill tokens based on elapsed time."""
        now = time.time()
        elapsed = now - self.last_refill
        tokens_to_add = elapsed * self.refill_rate

        self.tokens = min(self.capacity, self.tokens + tokens_to_add)
        self.last_refill = now

    def consume(self, tokens: int = 1) -> bool:
        """Try to consume tokens. Returns True if successful."""
        with self.lock:
            self._refill()
            if self.tokens >= tokens:
                self.tokens -= tokens
                return True
            return False

    async def wait_for_token(self, tokens: int = 1):
        """Async wait until tokens are available."""
        while not self.consume(tokens):
            await asyncio.sleep(0.1)
```

#### 5. Cache Manager (src/cache/memory_cache.py)

```python
import time
from typing import Optional, Any
from collections import OrderedDict

class MemoryCache:
    """In-memory LRU cache with TTL."""

    def __init__(self, max_size: int = 1000):
        self.max_size = max_size
        self.cache = OrderedDict()
        self.expiry = {}

    async def get(self, key: str) -> Optional[Any]:
        """Get cached value if not expired."""
        if key not in self.cache:
            return None

        # Check expiry
        if key in self.expiry and time.time() > self.expiry[key]:
            del self.cache[key]
            del self.expiry[key]
            return None

        # Move to end (LRU)
        self.cache.move_to_end(key)
        return self.cache[key]

    async def set(self, key: str, value: Any, ttl: int = 3600):
        """Set cached value with TTL."""
        if key in self.cache:
            self.cache.move_to_end(key)
        else:
            self.cache[key] = value
            # Evict oldest if at capacity
            if len(self.cache) > self.max_size:
                oldest_key = next(iter(self.cache))
                del self.cache[oldest_key]
                if oldest_key in self.expiry:
                    del self.expiry[oldest_key]

        self.cache[key] = value
        self.expiry[key] = time.time() + ttl

    async def delete(self, key: str):
        """Delete cached value."""
        if key in self.cache:
            del self.cache[key]
        if key in self.expiry:
            del self.expiry[key]

    async def clear(self):
        """Clear all cached values."""
        self.cache.clear()
        self.expiry.clear()
```

#### 6. Cost Tracker (src/monitoring/cost_tracker.py)

```python
import time
from collections import defaultdict
from dataclasses import dataclass, field

@dataclass
class CostTracker:
    """Track LLM usage costs."""

    usage_history: list = field(default_factory=list)
    costs_by_model: dict = field(default_factory=lambda: defaultdict(float))

    PRICING = {
        "claude-3-opus-20240229": {"input": 0.015, "output": 0.075},
        "claude-3-sonnet-20240229": {"input": 0.003, "output": 0.015},
        "claude-3-haiku-20240307": {"input": 0.00025, "output": 0.00125},
        "gpt-4-turbo-preview": {"input": 0.01, "output": 0.03},
        "gpt-3.5-turbo": {"input": 0.0005, "output": 0.0015}
    }

    def calculate_cost(
        self,
        input_tokens: int,
        output_tokens: int,
        model: str
    ) -> float:
        """Calculate cost for request."""
        rates = self.PRICING.get(model, self.PRICING["gpt-3.5-turbo"])
        input_cost = (input_tokens / 1000) * rates["input"]
        output_cost = (output_tokens / 1000) * rates["output"]
        return input_cost + output_cost

    def log_request(self, model: str, cost: float):
        """Log request for analytics."""
        self.usage_history.append({
            "timestamp": time.time(),
            "model": model,
            "cost": cost
        })
        self.costs_by_model[model] += cost

    def get_stats(self) -> dict:
        """Get aggregate statistics."""
        if not self.usage_history:
            return {"total_cost": 0, "total_requests": 0}

        total_cost = sum(r["cost"] for r in self.usage_history)

        return {
            "total_requests": len(self.usage_history),
            "total_cost": total_cost,
            "cost_per_request": total_cost / len(self.usage_history),
            "costs_by_model": dict(self.costs_by_model)
        }
```

#### 7. Retry Utility (src/utils/retry.py)

```python
import time
import random
import asyncio
from functools import wraps

def retry_with_backoff(
    max_retries: int = 3,
    base_delay: float = 1.0,
    max_delay: float = 60.0,
    exponential_base: float = 2.0,
    jitter: bool = True
):
    """Async retry decorator with exponential backoff."""
    def decorator(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            retries = 0
            while retries < max_retries:
                try:
                    return await func(*args, **kwargs)
                except Exception as e:
                    retries += 1
                    if retries >= max_retries:
                        raise

                    delay = min(base_delay * (exponential_base ** retries), max_delay)
                    if jitter:
                        delay = delay * (0.5 + random.random())

                    print(f"Retry {retries}/{max_retries} after {delay:.2f}s: {e}")
                    await asyncio.sleep(delay)

            return await func(*args, **kwargs)
        return wrapper
    return decorator
```

#### 8. Testing Suite (tests/test_client.py)

```python
import pytest
import asyncio
from src.client.anthropic_client import AnthropicClient, CompletionRequest

@pytest.mark.asyncio
async def test_completion():
    """Test basic completion."""
    client = AnthropicClient(api_key="test-key", enable_cache=False)

    request = CompletionRequest(
        prompt="What is 2+2?",
        max_tokens=100
    )

    response = await client.complete(request)

    assert response.content
    assert response.usage["output_tokens"] > 0
    assert response.latency > 0
    assert response.provider == "anthropic"

@pytest.mark.asyncio
async def test_caching():
    """Test response caching."""
    client = AnthropicClient(api_key="test-key", enable_cache=True)

    request = CompletionRequest(prompt="Test prompt", max_tokens=50)

    # First call
    response1 = await client.complete(request)
    assert not response1.cached

    # Second call (should be cached)
    response2 = await client.complete(request)
    assert response2.cached
    assert response2.content == response1.content

@pytest.mark.asyncio
async def test_rate_limiting():
    """Test rate limiting."""
    client = AnthropicClient(api_key="test-key", requests_per_minute=2)

    start = asyncio.get_event_loop().time()

    # Make 3 requests (should rate limit after 2)
    for _ in range(3):
        await client.complete(CompletionRequest(prompt="Test", max_tokens=10))

    elapsed = asyncio.get_event_loop().time() - start

    # Should take at least 30s (limited to 2 req/min)
    assert elapsed >= 30.0

# Run tests
# pytest tests/test_client.py -v
```

#### 9. Docker Configuration (docker/Dockerfile)

```dockerfile
FROM python:3.11-slim

WORKDIR /app

# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application
COPY src/ ./src/

# Environment variables
ENV ANTHROPIC_API_KEY=""
ENV REDIS_URL="redis://redis:6379"

# Run application
CMD ["python", "-m", "src.main"]
```

#### 10. Docker Compose (docker/docker-compose.yml)

```yaml
version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: docker/Dockerfile
    environment:
      - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
      - REDIS_URL=redis://redis:6379
    depends_on:
      - redis
    ports:
      - "8000:8000"

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data

volumes:
  redis-data:
```

#### 11. Requirements (requirements.txt)

```
anthropic==0.18.1
redis==5.0.1
prometheus-client==0.19.0
pytest==7.4.3
pytest-asyncio==0.21.1
python-dotenv==1.0.0
```

#### 12. Example Usage (example.py)

```python
import asyncio
from src.client.anthropic_client import AnthropicClient, CompletionRequest

async def main():
    # Initialize client
    client = AnthropicClient(
        api_key="your-api-key",
        model="claude-3-haiku-20240307",
        requests_per_minute=50,
        enable_cache=True,
        enable_metrics=True
    )

    # Simple completion
    request = CompletionRequest(
        prompt="Explain quantum computing in 3 sentences",
        max_tokens=200
    )

    response = await client.complete(request)
    print(f"Response: {response.content}")
    print(f"Latency: {response.latency:.2f}s")
    print(f"Cached: {response.cached}")

    # Streaming completion
    print("\nStreaming response:")
    async for token in client.stream_complete(request):
        print(token, end="", flush=True)

    # Get statistics
    stats = await client.get_stats()
    print(f"\n\nTotal cost: ${stats['cost_tracker']['total_cost']:.4f}")
    print(f"Requests: {stats['cost_tracker']['total_requests']}")

if __name__ == "__main__":
    asyncio.run(main())
```

## Features Included

**Production-Ready:**
-  Error handling with retry logic
-  Rate limiting (token bucket)
-  Response caching (memory + Redis)
-  Cost tracking and monitoring
-  Prometheus metrics integration
-  Streaming responses
-  Type safety with dataclasses
-  Async/await throughout
-  Comprehensive tests
-  Docker deployment

**Cost Optimization:**
-  Automatic caching (80%+ cache hit rate typical)
-  Token counting and budgets
-  Model selection guidance
-  Batch processing support

**Reliability:**
-  Exponential backoff retries
-  Rate limiting to prevent quota exhaustion
-  Graceful error handling
-  Health checks

## Time Savings

**Manual implementation:** 8-12 hours
- Set up project structure
- Implement client with error handling
- Add rate limiting
- Build caching layer
- Implement monitoring
- Write tests
- Configure deployment

**With this command:** 5-10 minutes
- Run command
- Add API key
- Deploy to production

**ROI:** 48-72x time multiplier

---

**Next Steps:**
1. Run `/las anthropic` or `/las openai` or `/las multi`
2. Copy generated code to your project
3. Install dependencies: `pip install -r requirements.txt`
4. Set API key: `export ANTHROPIC_API_KEY=your-key`
5. Run example: `python example.py`
6. Deploy: `docker-compose up -d`

**Production checklist:**
- [ ] Set up Redis for distributed caching
- [ ] Configure Prometheus for metrics
- [ ] Set up alerting (cost thresholds, error rates)
- [ ] Implement logging (structured JSON logs)
- [ ] Add authentication if exposing as API

**Estimated monthly cost:** $0.10 - $10+ depending on usage volume.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.