plugin/skills/python-fastapi-patterns/SKILL.md
Use this skill when designing or implementing Python backend code in FastAPI projects, reviewing Python pull requests, or onboarding new contributors to FastAPI conventions — a Python backend patterns knowledge base covering Python 3.12+, FastAPI layered architecture, Pydantic v2 schemas, SQLAlchemy 2.0 async ORM, Alembic migrations, async/await, dependency injection, pytest with httpx.AsyncClient, OAuth2/JWT security, ruff and mypy strict, structured logging and Prometheus metrics.
npx skillsauth add avav25/ai-assets python-fastapi-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Reference knowledge for Python 3.12+ backend services built on FastAPI. This skill is auto-loaded by the python-engineer agent and available to any other agent or skill that needs deep Python/FastAPI patterns — architects reviewing service designs, reviewers checking Python PRs, or DB engineers reviewing SQLAlchemy models.
Domain-driven module structure — each domain has its own package:
router.py — path operations and HTTP layer onlyschemas.py — Pydantic request/response modelsmodels.py — SQLAlchemy ORM modelsservice.py — business logicdependencies.py — FastAPI Depends callablesexceptions.py — domain-specific exceptionsconstants.py — enums, error codesGlobal modules: main.py, database.py, config.py, exceptions.py. Tests mirror source structure under tests/<module_name>/.
Layering rule: routers handle HTTP concerns only (path ops, status codes, response models). Business logic lives in the service layer. Repositories (or service-internal data accessors) own SQLAlchemy session use. Never pass raw dicts across layer boundaries.
Configuration: use pydantic-settings with BaseSettings for typed config, split per domain. Environment-specific files (.env.dev, .env.prod, .env.test) load via env_file. Externalize all secrets (DATABASE_URL, REDIS_URL, JWT_SECRET). Local dev uses model_config = SettingsConfigDict(env_file=".env").
mypy --strict — no implicit Any, no untyped defsstr | None (not Optional[str]), list[int] (not List[int])TypeVar, Generic, Protocol for reusable abstractionsTypeAlias for complex types, Literal for constrained string values@overload for functions with different return types based on inputUserCreate, UserUpdate, UserResponse, UserInDBField() with min_length, max_length, ge, le, pattern for validationmodel_config = ConfigDict(from_attributes=True) for ORM compatibility@field_validator for field-level, @model_validator for cross-fieldAnnotated[type, Field(...)] pattern for reusable field definitionsmodel_validate on untrusted data without an explicit schemaORM (2.0 style):
AsyncSession with async_sessionmaker — never sync Session in FastAPIMappedAsBase and Mapped[] type annotationsmapped_column() with explicit types: Mapped[int], Mapped[str | None]relationship() with lazy="selectin" or explicit selectinload() / joinedload()select() statement API — never the legacy query() APIDatabase wiring:
create_async_engine(url, pool_size=20, max_overflow=10)Depends(get_async_session) — yields a session, auto-closesasync with session.begin()selectinload() for collections, joinedload() for single relationsexecution_options(readonly=True) where supportedAlembic migrations:
env.py via sqlalchemy.ext.asyncioalembic/versions/alembic revision --autogenerate -m "description"naming_convention on MetaData for consistent constraint namesalembic upgrade head from an empty DBDepends() for all cross-cutting concerns: auth, DB session, pagination, permissionscurrent_user = Depends(get_current_user) → admin_user = Depends(require_admin)Annotated[type, Depends(dep)] for clean, reusable dependency declarationsConventions:
/api/v1/users, /api/v1/users/{user_id}/ordersAPIRouter with prefix and tags per domain moduleskip/limit or cursor-based for large datasets. Return total countresponse_model on every endpoint — never return raw dicts or ORM objectsError handling:
AppException@app.exception_handler(AppException){"detail": str, "error_code": str, "status_code": int}HTTPException(500)async def for all I/O path operations — FastAPI runs sync defs in a threadpool (less efficient)asyncio.gather() for parallel independent I/O callsrun_in_threadpool() from starlette.concurrency for unavoidable sync librariesProcessPoolExecutor or a task queue (Celery, ARQ)time.sleep() in async context — use asyncio.sleep()BackgroundTasks for fire-and-forget; task queue for reliable processingfastapi.security.OAuth2PasswordBearerpasslib with bcrypt, or argon2-cffi — never plaintextCORSMiddleware — never allow_origins=["*"] in productionslowapi or custom middleware with a Redis backendbleach if rendering user contentSecure, HttpOnly, SameSite on cookiesFor the full OWASP-aligned web checklist, see owasp-coverage skill.
pytest + pytest-asyncio + httpx.AsyncClientasync with AsyncClient(app=app, base_url="http://test") as client:get_async_session with a test session (use transactions + rollback)factory_boy or manual fixtures for test data generationparametrize for input variationspytest-cov, target ≥80% on service and router layersFor broader test pyramid and coverage guidance, see test-strategy skill.
ruff (replaces flake8, isort, black) — single tool, fastmypy --strict in CI — no commits with type errorsruff check, ruff format, mypy as pre-commit hooksruff with isort rules — stdlib → third-party → localstructlog or stdlib logging with a JSON formatter in production. Correlation IDs via middlewareprometheus-fastapi-instrumentator for automatic request metrics/health endpoint returning DB and Redis connectivity status/docs (Swagger) and /redoc. Keep schemas accurate| Workflow | Apply this knowledge |
|---|---|
| Agent(python-engineer) invocation | Auto-loaded via skills: frontmatter |
| /develop with a Python work-package | Spawned agent loads this knowledge |
| /code-review on Python PRs | Reviewer references these patterns |
| /architecture-design for a Python service | Architect references the layering, async, and DB patterns |
| /bugfix on Python services | Developer agent grounds the fix in these conventions |
python-engineer agent (primary), software-engineer (when reviewing Python code), db-engineer (when reviewing SQLAlchemy models)context-engineering (for Python agent harnesses), owasp-coverage (security section), test-strategy (pyramid and coverage targets)development
Use this skill when running the recurring (daily) knowledge-base rescan for a repo that already has knowledge/.knowledge-sync.yml — the main-thread dispatcher that reads the config, computes the git delta since last_scanned_sha, maps changed paths to affected doc areas, early-exits cheaply when nothing changed, then fans out one Agent(content-writer) per affected area, applies the propose/direct update policy, advances the baseline only on success, and writes an L4 run log — all with the G1 untrusted-content choke-point, secret-scan, deny-list, and budget controls woven in. For first-time setup use /knowledge-sync-init.
development
Use this skill when bootstrapping scheduled knowledge-base sync for a repo that has no knowledge/.knowledge-sync.yml yet — to run one-time setup that detects the knowledge_root from CLAUDE.md/AGENTS.md, maps doc areas to source globs, records opt-in external sources (Linear/Notion/WebFetch, all disabled by default), captures a baseline last_scanned_sha, sets the per-area update policy, generates or seeds knowledge/CONVENTIONS.md, provisions the L4 memory dir, and offers to register the daily routine. Routes ongoing recurring sync operations to /knowledge-sync.
tools
Use this skill when bootstrapping a target repository to be ai-skills-aware — on the first run of any ai-skills workflow in a fresh repo, when adopting the ai-skills plugin in an existing repo, or after upgrading to a plugin version that adds new memory paths or templates, including when the user does not say "init" but asks to "set up" or "onboard" the repo — to detect codebase type, create CLAUDE.md + AGENTS.md scaffolding, initialize the .ai-skills-memory/ directory tree from L1 templates, and configure .gitignore. Idempotent — safe to re-run. Accepts `--codebase-type <type>` and `--overwrite`. Not for re-initializing only memory — use `/memory-init` instead.
tools
Use this skill when extending, repairing, or improving plugin assets, when ingesting a `/feedback` report as a fix-cycle backlog, or when you do not remember which lower-level command is right for the job — the umbrella workflow for ai-skills plugin-asset authoring and maintenance: creating, auditing, fixing, improving, refactoring, and migrating skills, agents, rules, hooks, prompts, schemas, and rubrics inside the plugin. Auto-classifies the request, loads the right knowledge skills (`@prompt-engineering`, `@context-engineering`, `@team-protocols`), and spawns the right subagents (`prompt-engineer`, `system-architect`, `python-engineer`, `software-engineer`, `qa-engineer`, `eval-judge`) via the `Agent` tool.