Back to list
LPDigital-Agent

backend-architect

by LPDigital-Agent

Galderma TrackWise AI Autopilot Demo - 9-agent mesh on AWS Bedrock AgentCore

0🍴 0📅 Jan 21, 2026

SKILL.md


name: backend-architect description: Backend architecture specialist for Faiston NEXO. Use PROACTIVELY for FastAPI endpoints, Lambda handlers, DynamoDB schemas, S3 presigned URLs, Cognito auth, and AgentCore integration. allowed-tools: Read, Write, Edit, Grep, Glob, Bash

Backend Architect Skill

Backend architecture specialist for Faiston NEXO serverless infrastructure.

For detailed patterns and templates, see reference.md.

Faiston NEXO Stack

ComponentTechnology
FrameworkFastAPI + Python 3.11
RuntimeAWS Lambda (Mangum adapter)
DatabaseDynamoDB (single-table design)
StorageS3 (presigned URLs, CORS)
AuthCognito JWT validation
AI AgentsAgentCore (direct invocation)
GatewayAPI Gateway v2 (HTTP API)
IaCTerraform

Key Files

PurposePath
FastAPI Appserver/main.py
Lambda Handlerserver/lambda_handler.py
Community Routesserver/community/routes.py
AgentCore Entryserver/agentcore/main.py
CORS Configterraform/main/locals.tf
Lambda Configterraform/main/lambda.tf

FastAPI Patterns

Endpoint Structure

# server/community/routes.py
from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel, Field

router = APIRouter(prefix="/api", tags=["community"])

class PostCreate(BaseModel):
    title: str = Field(..., min_length=1, max_length=200)
    content: str = Field(..., min_length=1)
    category: str = Field(default="geral")

class PostResponse(BaseModel):
    post_id: str
    title: str
    content: str
    created_at: str

@router.post("/posts", response_model=PostResponse, status_code=status.HTTP_201_CREATED)
async def create_post(post: PostCreate, user_id: str = Depends(get_current_user)):
    """Create a new community post."""
    # DynamoDB put_item
    return {"post_id": "...", **post.model_dump()}

Error Handling

from fastapi import HTTPException
from fastapi.responses import JSONResponse

# Use HTTPException for client errors
raise HTTPException(status_code=404, detail="Post not found")

# Global exception handler
@app.exception_handler(Exception)
async def global_exception_handler(request, exc):
    return JSONResponse(
        status_code=500,
        content={"detail": "Internal server error"}
    )

Lambda/Mangum Pattern

# server/lambda_handler.py
from mangum import Mangum
from server.main import app

# Mangum adapter for Lambda
handler = Mangum(app, lifespan="off")

Lambda Configuration (terraform/main/lambda.tf):

  • Timeout: 30 seconds (API Gateway max: 29s)
  • Memory: 512MB minimum
  • Handler: lambda_handler.handler

DynamoDB Patterns

Single-Table Design

# PK/SK pattern for community posts
{
    "PK": "POST#category#duvidas",
    "SK": "2025-01-01T12:00:00#post123",
    "post_id": "post123",
    "title": "Question about Python",
    "content": "...",
    "user_id": "user456",
    "GSI1PK": "USER#user456",
    "GSI1SK": "POST#2025-01-01T12:00:00"
}

Query Patterns

import boto3
from boto3.dynamodb.conditions import Key

table = boto3.resource("dynamodb").Table("faiston-nexo-community")

# Get posts by category (sorted by date desc)
response = table.query(
    KeyConditionExpression=Key("PK").eq(f"POST#category#{category}"),
    ScanIndexForward=False,  # Descending order
    Limit=20
)

# Get posts by user (using GSI)
response = table.query(
    IndexName="GSI1",
    KeyConditionExpression=Key("GSI1PK").eq(f"USER#{user_id}")
)

S3 Presigned URLs

CRITICAL: Use regional endpoint to avoid 307 redirects:

from botocore.config import Config

s3_client = boto3.client(
    's3',
    region_name='us-east-2',
    config=Config(
        signature_version='s3v4',
        s3={'addressing_style': 'virtual'}
    )
)

# Generate upload URL
upload_url = s3_client.generate_presigned_url(
    'put_object',
    Params={
        'Bucket': 'faiston-nexo-assets',
        'Key': f'audio/{episode_id}/{filename}',
        'ContentType': 'audio/mpeg'
    },
    ExpiresIn=3600
)

# Generate download URL
download_url = s3_client.generate_presigned_url(
    'get_object',
    Params={'Bucket': bucket, 'Key': key},
    ExpiresIn=7200
)

Cognito JWT Validation

from jose import jwt, JWTError
import httpx

COGNITO_REGION = "us-east-2"
COGNITO_USER_POOL_ID = "us-east-2_6Vzhr0J6M"
COGNITO_CLIENT_ID = "dqqebean5q4fq14bkp2bofnsj"

# JWKS URL
JWKS_URL = f"https://cognito-idp.{COGNITO_REGION}.amazonaws.com/{COGNITO_USER_POOL_ID}/.well-known/jwks.json"

async def validate_token(token: str) -> dict:
    """Validate Cognito JWT token."""
    # Fetch JWKS (cache in production)
    async with httpx.AsyncClient() as client:
        jwks = await client.get(JWKS_URL)

    # Decode and validate
    payload = jwt.decode(
        token,
        jwks.json(),
        algorithms=["RS256"],
        audience=COGNITO_CLIENT_ID
    )
    return payload

CORS Configuration

IMPORTANT: CORS is configured ONLY in terraform/main/locals.tf:

locals {
  cors_allowed_origins = [
    "http://localhost:8081",
    "https://nexo.faiston.com"
  ]
}

Do NOT add CORS middleware to FastAPI - it causes duplicate headers!

Architecture Decisions

When to Use Lambda vs AgentCore

Use CaseSolutionReason
CRUD operationsLambda + API GatewayFast, simple, cost-effective
AI agent chatAgentCore directNo timeout, streaming support
File uploadLambda + S3 presignedSecure, scalable
Long operationsAgentCore>30s operations

API Gateway Limits

  • Timeout: 29 seconds max
  • Payload: 10 MB max
  • For larger/longer: Use AgentCore direct invocation

Output Format

  • Be extremely concise, sacrifice grammar for brevity
  • Lead with the recommendation, follow with brief reasoning
  • Use bullet points and structured formats
  • Include code snippets or schemas when helpful
  • Flag critical issues with clear warnings

Remember: Never deploy from local console - use GitHub Actions only!

Score

Total Score

40/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon