Agent skill
backend-python
Modern Python backend stack: FastAPI, SQLAlchemy 2.0, Pydantic v2, uv, ruff. Use when: building Python APIs, async services, or working with Python backend code. Triggers: "fastapi", "python backend", "sqlalchemy", "pydantic", "uv", "ruff", "python api", "async python".
Install this agent skill to your Project
npx add-skill https://github.com/timequity/vibe-coder/tree/main/skills/backend-python
SKILL.md
Python Backend Stack
Live docs: Add
use context7to prompt for up-to-date FastAPI, SQLAlchemy, Pydantic documentation.
Tooling (2025)
| Tool | Purpose | Why |
|---|---|---|
| uv | Package manager | 10-100x faster than pip |
| ruff | Linter + formatter | Replaces black, isort, flake8 |
| FastAPI | Web framework | Async, auto-docs, Pydantic |
| SQLAlchemy 2.0 | ORM | Async support, type hints |
| Pydantic v2 | Validation | 5-50x faster than v1 |
| pytest | Testing | See testing.md |
Project Setup
# Initialize
uv init my-api
cd my-api
uv add fastapi sqlalchemy[asyncio] pydantic pydantic-settings
uv add --dev ruff pytest pytest-asyncio httpx
# pyproject.toml
[tool.ruff]
line-length = 100
select = ["E", "F", "I", "N", "UP", "B", "A", "C4", "SIM"]
[tool.ruff.format]
quote-style = "double"
[tool.pytest.ini_options]
asyncio_mode = "auto"
Project Structure
src/
├── main.py # FastAPI app
├── config.py # Settings (pydantic-settings)
├── db/
│ ├── __init__.py
│ ├── engine.py # Async engine + session
│ └── models.py # SQLAlchemy models
├── api/
│ ├── __init__.py
│ ├── deps.py # Dependencies (get_db, get_user)
│ └── routes/
│ ├── __init__.py
│ ├── auth.py
│ └── users.py
├── schemas/ # Pydantic models
│ ├── __init__.py
│ └── user.py
└── services/ # Business logic
└── user.py
tests/
├── conftest.py
└── test_users.py
FastAPI Patterns
Basic App
from fastapi import FastAPI
from contextlib import asynccontextmanager
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
await init_db()
yield
# Shutdown
await close_db()
app = FastAPI(lifespan=lifespan)
Route with Dependencies
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
router = APIRouter(prefix="/users", tags=["users"])
@router.get("/{user_id}", response_model=UserOut)
async def get_user(
user_id: int,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
user = await db.get(User, user_id)
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user
Pydantic Schemas
from pydantic import BaseModel, EmailStr, Field
from datetime import datetime
class UserCreate(BaseModel):
email: EmailStr
name: str = Field(min_length=1, max_length=100)
class UserOut(BaseModel):
id: int
email: str
name: str
created_at: datetime
model_config = {"from_attributes": True} # For ORM mode
Settings
from pydantic_settings import BaseSettings
from functools import lru_cache
class Settings(BaseSettings):
database_url: str
secret_key: str
debug: bool = False
model_config = {"env_file": ".env"}
@lru_cache
def get_settings() -> Settings:
return Settings()
SQLAlchemy 2.0 Async
Engine Setup
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker, DeclarativeBase
engine = create_async_engine(
"postgresql+asyncpg://user:pass@localhost/db",
echo=False,
pool_size=5,
max_overflow=10,
)
AsyncSessionLocal = sessionmaker(
engine, class_=AsyncSession, expire_on_commit=False
)
class Base(DeclarativeBase):
pass
Models
from sqlalchemy import String, ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
from datetime import datetime
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
email: Mapped[str] = mapped_column(String(255), unique=True, index=True)
name: Mapped[str] = mapped_column(String(100))
created_at: Mapped[datetime] = mapped_column(default=datetime.utcnow)
posts: Mapped[list["Post"]] = relationship(back_populates="author")
Database Dependency
from typing import AsyncGenerator
async def get_db() -> AsyncGenerator[AsyncSession, None]:
async with AsyncSessionLocal() as session:
try:
yield session
await session.commit()
except Exception:
await session.rollback()
raise
Queries
from sqlalchemy import select
from sqlalchemy.orm import selectinload
# Get one
user = await db.get(User, user_id)
# Query with filter
stmt = select(User).where(User.email == email)
result = await db.execute(stmt)
user = result.scalar_one_or_none()
# Eager load relationships
stmt = select(User).options(selectinload(User.posts)).where(User.id == user_id)
# Pagination
stmt = select(User).offset(skip).limit(limit).order_by(User.created_at.desc())
result = await db.execute(stmt)
users = result.scalars().all()
Error Handling
from fastapi import HTTPException, status
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
return JSONResponse(
status_code=422,
content={"error": {"code": "VALIDATION_ERROR", "details": exc.errors()}},
)
# Custom exceptions
class NotFoundError(Exception):
def __init__(self, resource: str, id: int):
self.resource = resource
self.id = id
@app.exception_handler(NotFoundError)
async def not_found_handler(request, exc):
return JSONResponse(
status_code=404,
content={"error": {"message": f"{exc.resource} {exc.id} not found"}},
)
Anti-patterns
| Don't | Do Instead |
|---|---|
pip install |
uv add |
black + isort + flake8 |
ruff |
| SQLAlchemy 1.x style | SQLAlchemy 2.0 with Mapped[] |
| Pydantic v1 | Pydantic v2 (model_config, not Config) |
| Sync database calls | Async with asyncpg/aiosqlite |
| Global DB session | Dependency injection |
| Business logic in routes | Services layer |
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
mvp-help
Help and documentation for Idea to MVP plugin. Use when: user asks about building MVPs, vibe coding, or available commands. Triggers: "help", "what can you do", "mvp help", "how to build".
verification-gate
Hidden quality gate that runs before showing "Done!" to user - ensures all tests pass, build succeeds, and requirements met before claiming completion
brainstorming
Refine ideas into detailed designs through Socratic dialogue. Use when: user has rough idea, needs to clarify requirements, explore approaches. Triggers: "brainstorm", "discuss idea", "I'm thinking about", "what if", "help me think through", "explore options", "/brainstorm".
subagent-creator
Guide for creating effective subagents (custom agents). Use when users want to create a new subagent that can be dispatched via Task tool for autonomous work. Covers frontmatter fields (name, description, tools, model, permissionMode, skills), prompt design, and when to use subagents vs skills.
backend-rust
Modern Rust backend with Axum, SQLx, tokio + CI/CD automation. Use when: building Rust APIs, high-performance services, or needing build/test/lint/audit automation. Triggers: "axum", "rust backend", "rust api", "sqlx", "tokio", "cargo build", "cargo test", "clippy", "rustfmt", "cargo-audit", "cross-compile", "rust ci", "release build", "rust security", "shuttle", "actix".
test-driven-development
Write failing test first, then minimal code to pass. Red-Green-Refactor cycle. Use when: implementing features, fixing bugs, refactoring code. Triggers: "implement", "add feature", "fix bug", "tdd", "test first", "write tests", "test-driven".
Didn't find tool you were looking for?