Architectural governance for AI-generated FastAPI code
FastAPI projects move fast — new routers, new dependencies, and new endpoints land in a single agent session. Mneme governs the architectural decisions in those repos before generation, so an AI coding agent can't quietly collapse your router / service / repository boundaries or re-litigate settled conventions. There is no bespoke FastAPI parser; the decisions are repo-native rules enforced at the file-write seam and in CI.
Why governance matters in FastAPI
FastAPI is built around standard Python type hints, dependency injection, automatic validation, and generated OpenAPI documentation. That structure is exactly what makes a project legible — and exactly what an AI coding agent drifts away from when it optimizes for "make the endpoint work" over "respect the architecture." The framework gives you a clean place to put routers, services, repositories, and Pydantic schemas; nothing forces an agent to keep them there.
The faster agents generate API surface, the more often the same architectural decisions get re-decided per file: where business logic lives, how the database is reached, which dependencies guard a router, what shape a response takes. Mneme injects the project's settled decisions into the agent's context and checks the diff, so speed doesn't come at the cost of a coherent codebase.
What Mneme can govern
Mneme governs the architectural decisions a FastAPI team has already made — expressed as repo-native rules in a decision corpus, not as a built-in FastAPI rule pack. Common surfaces:
- Layer boundaries — router, service, repository, and schema responsibilities stay separated.
- Thin route handlers — business logic stays out of the presentation layer.
- Dependency injection — shared resources arrive via
Dependsrather than ad hoc construction. - Authentication and authorization — protected routers carry their auth dependencies consistently.
- Validation and serialization — request and response models stay consistent instead of returning raw dicts or ORM objects.
- Async conventions and module structure — the approved package layout and async/sync boundaries are preserved.
- API discipline — versioning and OpenAPI decisions are not silently broken.
Five concrete examples of what the governance layer catches in FastAPI repos under AI-assisted development:
Business logic in a route handler
ArchitectureRule. Route handlers must stay thin. Pricing, tax, and inventory logic belong in service modules.
# AI-generated in routers/checkout.py @router.post("/checkout") async def checkout(payload: CheckoutIn): subtotal = sum(i.price * i.qty for i in payload.items) tax = subtotal * 0.0875 # inventory mutation, payment call, email send inline... return {"total": subtotal + tax}
Database access inside the router
Layer boundaryRule. Persistence goes through repository modules. No raw queries or sessions in route handlers.
# AI-generated in routers/users.py @router.get("/users/{user_id}") async def get_user(user_id: int, db: Session = Depends(get_db)): return db.execute( text(f"SELECT * FROM users WHERE id = {user_id}") ).fetchone()
Ad hoc construction instead of dependency injection
Dependency injectionRule. Clients and sessions arrive through Depends. No module-level singletons constructed in handlers.
# AI-generated in routers/reports.py @router.get("/reports") async def reports(): client = StorageClient(API_KEY) # built inline, not injected engine = create_engine(DATABASE_URL) ...
Protected router missing its auth dependency
SecurityRule. Routers under /admin must declare the auth dependency. No unauthenticated admin surface.
# AI-generated in routers/admin.py router = APIRouter(prefix="/admin") # dependencies=[Depends(require_admin)] dropped @router.delete("/users/{user_id}") async def delete_user(user_id: int): ...
Inconsistent response serialization
Schema disciplineRule. Endpoints declare a response_model. No returning ORM objects or untyped dicts.
# AI-generated in routers/orders.py @router.get("/orders/{order_id}") # response_model omitted async def get_order(order_id: int): return order_repo.get(order_id) # leaks the ORM model + internal fields
Example governance decisions
These are illustrative rules a FastAPI team would author in its own decision corpus. Mneme does not ship them as defaults — it enforces the decisions you record.
Route handlers must remain thin. Business logic belongs in service modules.
An agent that inlines pricing, tax, or orchestration logic into a handler is flagged before the change lands.
Database access must go through repository modules rather than route handlers.
Sessions and queries that appear directly in a router are surfaced as a boundary violation.
Authentication dependencies must be applied consistently to protected routers.
Dropping the auth dependency on an admin or account router is treated as an access-control regression.
How governance fits the workflow
Mneme sits between your architectural decisions and the AI coding tools writing FastAPI code. The loop is the same one Mneme runs for any repository:
-
Decisions and ADRs are recorded
Your architectural decisions live as records in
.mneme/project_memory.json— each with a scope, constraints, and anti-patterns. ADRs can be imported into the same corpus. -
Mneme retrieves the relevant intent
On a prompt or a file write, Mneme retrieves the decisions in scope for the change and injects them into the agent's context — governance before generation, not review after the fact.
-
The AI coding agent changes the code
Claude Code, Cursor, Copilot, or a custom agent edits routers, services, repositories, and schemas with that context in hand.
-
Mneme checks the proposed change
mneme checkevaluates the diff against the corpus: a matched constraint surfaces asWARN, an anti-pattern hit asFAIL. Aligned changes pass cleanly. -
CI gates the merge
In
--mode strictaWARNexits 1 and aFAILexits 2, so the regression blocks the PR;--mode warnannotates without blocking. One corpus serves the editor, the terminal agent, and the CI runner.
Where it fits in a Python codebase
FastAPI governance is Python governance applied to an API-shaped repository. The decision corpus lives at .mneme/project_memory.json; hooks fire on file writes; mneme check --mode strict gates PR diffs in CI. Because Mneme is itself implemented in Python, the broader Python governance surface — native CLI, benchmark coverage, Claude Code hooks — applies directly to FastAPI projects.
See the Claude Code integration and the Cursor integration for editor and terminal setup, the GitHub Actions integration for CI gating, and architectural drift for the problem this prevents.