pattern-engineer-fastapi
Skill0 starsChanged 5 months agoMITView on GitHub
FastAPI bullets — wire what the contract already decided. `APIRouter` with explicit prefix; `Depends()` injection; Pydantic at the boundary only; app-level exception handlers mapping to the contracted envelope; `RequestIdMiddleware` registered last; named path constants shared by route + tests; `Depends`-based auth guards; async-by-default; lifespan for startup/shutdown; `dependency_overrides` + per-test factory in tests. Activate on FastAPI routes, deps, middleware, handlers, wiring.
In this repository74 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- create-bug-issueSkill
- create-enhancement-issueSkill
- create-feature-issuesSkill
- dream-summary-memorySkill
- memory-conventionSkill
- operation-gitSkill
- pattern-architect-api-endpointSkill
- pattern-architect-data-modelSkill
- pattern-architect-deep-moduleSkill
- pattern-e2e-coding-standardSkill
- pattern-engineer-apiSkill
- pattern-engineer-backend-standardSkill
- pattern-engineer-coding-standardSkill
- pattern-engineer-containerSkill
- pattern-engineer-databaseSkill
- pattern-engineer-frontend-standardSkill
- pattern-engineer-goSkill
- pattern-engineer-javaSkill
- pattern-engineer-kotlinSkill
- pattern-engineer-nodeSkill
- pattern-engineer-non-functionalSkill
- pattern-engineer-observabilitySkill
- pattern-engineer-pythonSkill
- pattern-engineer-rustSkill
- pattern-engineer-securitySkill
- pattern-engineer-ssrSkill
- pattern-engineer-swiftSkill
- pattern-engineer-typescriptSkill
- pattern-engineer-viteSkill
- pattern-exploratory-testingSkill
- pattern-reviewer-apiSkill
- pattern-reviewer-backend-standardSkill
- pattern-reviewer-coding-standardSkill
- pattern-reviewer-containerSkill
- pattern-reviewer-contractSkill
- pattern-reviewer-databaseSkill
- pattern-reviewer-fastapiSkill
- pattern-reviewer-frontend-standardSkill
- pattern-reviewer-goSkill
- pattern-reviewer-javaSkill
- pattern-reviewer-kotlinSkill
- pattern-reviewer-nodeSkill
- pattern-reviewer-non-functionalSkill
- pattern-reviewer-observabilitySkill
- pattern-reviewer-pythonSkill
- pattern-reviewer-rustSkill
- pattern-reviewer-securitySkill
- pattern-reviewer-ssrSkill
- pattern-reviewer-swiftSkill
- pattern-reviewer-test-coverageSkill
- pattern-reviewer-typescriptSkill
- pattern-reviewer-viteSkill
- pattern-test-coverageSkill
- principle-engineer-tddSkill
- scaffold-projectSkill
- workflow-architect-interviewSkill
- workflow-designer-sample-pagesSkill
- workflow-design-interviewSkill
- workflow-e2e-authorSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 1 is distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 16
After loading this skill, also check $MAIN_ROOT/.claude/memory/patterns/pattern-engineer-fastapi.md in the consuming project (resolve …
- Very specific: line 29
Every external dep enters via Depends() — DB session, settings, current-user resolver, rate limiter, idempotency-key extractor.
- Very specific: line 32
Don't reach for Settings() just to read one boolean — break the boolean out into a standalone os.getenv() helper so test fixtures can build …
- Distinctive: line 37
Don't pass Pydantic models deep into the domain layer.
- Very specific: line 39
Use Field(max_length=…, ge=…, le=…) on string and numeric fields to bound input ranges per the contract.
- Very specific: line 57
Use FastAPI's lifespan context manager for startup / shutdown hooks (OTel bootstrap, DB pool open/close, queue connect/disconnect).
- Very specific: line 73
Test via TestClient(app) (synchronous) for unit/integration.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
pattern-engineer-fastapi
FastAPI implementation patterns for routes, dependencies, middleware, exception handlers, and app wiring. The api contract (docs/api-contract/<entity>.yaml) decides path / verb / status / shape — this skill is HOW you wire them in FastAPI without contradicting the contract.
When to activate
Activate when editing FastAPI route handlers (@router.get / @router.post / …), APIRouter mounts, Depends() graphs, Pydantic request/response models, middleware (app.add_middleware(...)), exception handlers (@app.exception_handler(...)), create_app() / main.py wiring, OpenAPI customization, or Depends-based dependency injection. Skip for non-FastAPI Python code.
Project memory overlay
After loading this skill, also check $MAIN_ROOT/.claude/memory/patterns/pattern-engineer-fastapi.md in the consuming project (resolve MAIN_ROOT="$(dirname "$(git rev-parse --path-format=absolute --git-common-dir)")"). If present, load it as an additive overlay to the rules below; if absent, skip silently. See memory-convention for the full contract (additivity, severity floor, conflict surfacing).
Patterns
Routes + routers
- Mount each router with the contracted prefix:
app.include_router(users_router, prefix="/api/v1/users", tags=["users"]). Prefix matches the api contract verbatim. - Path inside the router is sourced from a module-level constant when shared with tests:
USERS_PATH = "/api/v1/users"; both@router.post(USERS_PATH)and the test import it. Constant value = contract path, including trailing-slash spelling. - One router per resource; never collapse unrelated resources into a "kitchen-sink" router.
- Async by default; switch to sync only when a downstream dep is sync-only.
Dependency injection
- Every external dep enters via
Depends()— DB session, settings, current-user resolver, rate limiter, idempotency-key extractor. - Auth guards are
Depends-based, never inline:@router.post(..., dependencies=[Depends(require_admin)])ordef handler(user: User = Depends(get_current_user)). Dependschains stay shallow (2–3 levels); deeper means the seam belongs in a service module.- Don't reach for
Settings()just to read one boolean — break the boolean out into a standaloneos.getenv()helper so test fixtures can build the app without populating the full env.
Request + response schemas
- Pydantic models at the boundary only — request body, response model, query params with constraints. The schema shape comes from the api contract; this skill is HOW you declare it in Pydantic.
- Don't pass Pydantic models deep into the domain layer; convert to dataclasses / domain types at the seam.
response_model=on every route so OpenAPI matches what the contract declared and sensitive fields are stripped consistently.- Use
Field(max_length=…, ge=…, le=…)on string and numeric fields to bound input ranges per the contract. - Status-code-only responses (e.g., a contract-declared 204) use
Response(status_code=204)— the FastAPI idiom for "no body"; never invent{"ok": True}when the contract says no body. - Keep request and response Pydantic models separate: never reuse one model for both. Request-only fields (write-side knobs, raw secrets) and response-only fields (computed derived values, db-issued ids) belong to different models — sharing one leaks write-only fields into the OpenAPI response or makes the response model accept fields the client can't send.
Exception handlers
- Register app-level handlers for project exceptions:
@app.exception_handler(LoginError). - Each handler maps to the contracted error envelope at one place — never inline
HTTPException(status_code=..., detail=...)for a project-wide error class. - Generic 500 handler returns the envelope + correlation id; logs the full exception server-side.
Middleware order
app.add_middleware(...)runs in reverse order on the response. Last-added middleware runs first on the way out.- Therefore:
RequestIdMiddlewareis the lastadd_middlewarecall so it runs first on rejection paths (rate-limit 429, auth 401, etc.) — every body must carry a non-nullrequest_id. - Pin middleware order with a test that walks
app.user_middlewareand asserts the request-id middleware is at the top.
Background tasks + lifespan
- Use FastAPI's
lifespancontext manager for startup / shutdown hooks (OTel bootstrap, DB pool open/close, queue connect/disconnect). Not the deprecated@app.on_event. BackgroundTasksparameter only for fire-and-forget work that can lose to a crash; persistent work uses a real queue.- Lifespan is async; don't put blocking I/O there without a thread pool wrapper.
Operational knobs (env-driven)
- Operational knobs gating external integrations are env-driven — rate limits, worker tick cadence, outbound timeouts. In-memory limiter state that persists across runs is a leading cause of flaky / failing E2E; read these from settings /
os.getenv(), never hard-code.
OpenAPI + docs
- Tag every route (
tags=["users"]) so the auto-generated docs group correctly. summary=anddescription=on routes that aren't self-evident; the auto-generated names are usually fine.- Hide internal routes from the docs:
include_in_schema=Falseon/healthz, debug endpoints.
Testing FastAPI
- Test via
TestClient(app)(synchronous) for unit/integration;httpx.AsyncClient(app=app, base_url=...)for async-needs. - Override
Dependsviaapp.dependency_overrides[real_dep] = fake_dep— never monkeypatch the module. - Build the app per-test via a factory (
create_app(settings=fake_settings)); never share a singleton across tests.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

