TradingAgents/.claude/skills/skill-integration/examples/composition-example.md

8.7 KiB
Raw Blame History

Skill Composition Example

Real-world example of combining multiple skills for a complex task.

Task: Implement Secure User Authentication API

Requirement: Add JWT-based authentication with secure password storage, comprehensive tests, and API documentation.

Skills Involved

This task requires 7 different skills working together:

  1. api-design - REST API patterns
  2. security-patterns - Authentication, JWT, password hashing
  3. database-design - User table schema, query optimization
  4. python-standards - Code style, type hints
  5. testing-guide - Security testing patterns
  6. documentation-guide - API documentation standards
  7. observability - Authentication logging

Progressive Disclosure in Action

Context Load (Startup)

Agent context:
├── implementer agent prompt: ~500 tokens
├── 21 skill metadata: ~1,050 tokens
├── Task description: ~200 tokens
└── Total: ~1,750 tokens (< 1% of budget)

Stage 1: API Design (Minutes 0-5)

Agent thinks: "Need to design authentication endpoints"

Skill activates: api-design (~4,000 tokens)

# Agent designs endpoints following api-design skill
@app.post("/auth/login")
async def login(credentials: LoginRequest) -> TokenResponse:
    pass

@app.post("/auth/refresh")
async def refresh_token(refresh: RefreshRequest) -> TokenResponse:
    pass

@app.get("/auth/me")
async def get_current_user(user: User = Depends(get_current_user)) -> User:
    pass

Context: ~5,750 tokens

Stage 2: Security Implementation (Minutes 5-10)

Agent thinks: "Need JWT validation and password hashing"

Skill activates: security-patterns (~6,000 tokens)

# Agent implements security following security-patterns skill
from passlib.context import CryptContext
from jose import JWTError, jwt

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def verify_password(plain_password: str, hashed_password: str) -> bool:
    return pwd_context.verify(plain_password, hashed_password)

def get_password_hash(password: str) -> str:
    return pwd_context.hash(password)

def create_access_token(data: dict, expires_delta: timedelta) -> str:
    to_encode = data.copy()
    expire = datetime.utcnow() + expires_delta
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

Context: ~11,750 tokens

Stage 3: Database Schema (Minutes 10-15)

Skill activates: database-design (~3,500 tokens)

# Agent designs schema following database-design skill
class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, index=True)
    email = Column(String, unique=True, index=True, nullable=False)
    hashed_password = Column(String, nullable=False)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)

    __table_args__ = (
        Index("idx_email_active", "email", "is_active"),
    )

Context: ~15,250 tokens

Stage 4: Code Style (Minutes 15-20)

Skill already loaded: python-standards (loaded at startup due to agent reference)

# Agent applies python-standards throughout implementation
from typing import Optional, Dict, Any
from datetime import datetime, timedelta

def authenticate_user(
    db: Session, email: str, password: str
) -> Optional[User]:
    """Authenticate user with email and password.

    Args:
        db: Database session
        email: User email address
        password: Plain text password

    Returns:
        User object if authentication successful, None otherwise
    """
    user = db.query(User).filter(User.email == email).first()
    if not user or not verify_password(password, user.hashed_password):
        return None
    return user

Context: ~15,250 tokens (skill already loaded)

Stage 5: Testing (Minutes 20-30)

Skill activates: testing-guide (~5,000 tokens)

# Agent writes tests following testing-guide skill
import pytest
from fastapi.testclient import TestClient

def test_login_success(client: TestClient, test_user):
    """Test successful user login returns access token."""
    response = client.post(
        "/auth/login",
        json={"email": test_user.email, "password": "testpass123"}
    )
    assert response.status_code == 200
    data = response.json()
    assert "access_token" in data
    assert "refresh_token" in data
    assert data["token_type"] == "bearer"

def test_login_invalid_password(client: TestClient, test_user):
    """Test login with invalid password returns 401."""
    response = client.post(
        "/auth/login",
        json={"email": test_user.email, "password": "wrongpassword"}
    )
    assert response.status_code == 401
    assert response.json()["detail"] == "Incorrect email or password"

def test_access_protected_endpoint_without_token(client: TestClient):
    """Test accessing protected endpoint without token returns 401."""
    response = client.get("/auth/me")
    assert response.status_code == 401

Context: ~20,250 tokens

Stage 6: Documentation (Minutes 30-35)

Skill activates: documentation-guide (~4,000 tokens)

# Agent adds API documentation following documentation-guide skill
@app.post(
    "/auth/login",
    response_model=TokenResponse,
    summary="User login",
    description="""
    Authenticate user with email and password.

    Returns access token (15-minute expiry) and refresh token (7-day expiry).

    **Authentication**: None required

    **Rate limiting**: 10 requests per minute per IP

    **Example request**:
    ```json
    {
        "email": "user@example.com",
        "password": "securepassword123"
    }
    ```

    **Example response**:
    ```json
    {
        "access_token": "eyJhbGc...",
        "refresh_token": "eyJhbGc...",
        "token_type": "bearer"
    }
    ```
    """
)
async def login(credentials: LoginRequest) -> TokenResponse:
    pass

Context: ~24,250 tokens

Stage 7: Observability (Minutes 35-40)

Skill activates: observability (~3,000 tokens)

# Agent adds logging following observability skill
import logging
from opentelemetry import trace

tracer = trace.get_tracer(__name__)
logger = logging.getLogger(__name__)

@app.post("/auth/login")
async def login(credentials: LoginRequest) -> TokenResponse:
    with tracer.start_as_current_span("auth.login") as span:
        span.set_attribute("user.email", credentials.email)

        user = authenticate_user(db, credentials.email, credentials.password)

        if not user:
            logger.warning(
                "Failed login attempt",
                extra={"email": credentials.email, "ip": request.client.host}
            )
            raise HTTPException(status_code=401, detail="Incorrect email or password")

        logger.info(
            "Successful login",
            extra={"user_id": user.id, "ip": request.client.host}
        )

        return create_tokens(user)

Context: ~27,250 tokens

Total Token Usage

Without Progressive Disclosure

If all 7 skills loaded upfront:

Agent prompt: 500 tokens
+ 7 skills × 5,000 tokens: 35,000 tokens
+ Task: 200 tokens
= 35,700 tokens before work starts!

With Progressive Disclosure

Skills load as needed throughout implementation:

Startup: 1,750 tokens
+ Stage 1 (api-design): +4,000 tokens
+ Stage 2 (security-patterns): +6,000 tokens
+ Stage 3 (database-design): +3,500 tokens
+ Stage 5 (testing-guide): +5,000 tokens
+ Stage 6 (documentation-guide): +4,000 tokens
+ Stage 7 (observability): +3,000 tokens
= ~27,250 tokens total

Savings: 8,450 tokens (24% reduction)

Key Observations

Skill Coordination

Skills work together naturally:

  • api-design provides endpoint structure
  • security-patterns provides authentication implementation
  • database-design provides schema
  • python-standards ensures code quality throughout
  • testing-guide ensures comprehensive testing
  • documentation-guide ensures clear API docs
  • observability ensures production monitoring

No Conflicts

Skills complement each other:

  • Each covers different domain
  • No contradictory guidance
  • Natural layering (design → implement → test → document)

Efficient Loading

Progressive disclosure loads skills just-in-time:

  • Not all at once (would exceed context)
  • Not too late (available when needed)
  • Automatic (agent doesn't manage loading)

Summary

This example demonstrates:

  • 7 skills working together for complex task
  • Progressive loading keeps context efficient
  • No conflicts between skills
  • 24% token savings vs loading all upfront
  • Natural workflow through implementation stages

Key takeaway: Trust progressive disclosure. Reference all relevant skills, let the system load them efficiently as needed.