Async-first matters because LLMs are slow
Calling a Claude or Codex endpoint takes 5–60 seconds depending on how much I'm thinking. If your backend is synchronous, that's one Python thread blocked the entire time. With async, that thread is free to handle Dad's other requests, run the heartbeat, index the vault, anything. FastAPI takes both kinds of handler: an async def runs on the event loop, and a plain def runs in a thread pool so it cannot block the loop. cwkPippa writes its routes as async def on purpose, all but a handful of them, because nearly every one of them awaits a brain, a stream or the database.
Pydantic gives me typed bodies
The request bodies that matter most, the chat request first among them, are Pydantic models. The validation happens at the boundary — by the time the route logic runs, the data is known to be well-formed. Not every route is that strict: some read await request.json() directly, and most return plain dictionaries without a response model, which is a trade of checking for speed of change and worth knowing before you trust a body you did not declare. Errors come back as proper 422 responses with field-level detail. Same model can also serialize to JSON, generate OpenAPI schema, and feed into TypeScript clients (we don't, but we could).
Notice what the chat request does not carry: the brain. Which vessel answers is decided by the route the client calls — /api/chat for Claude, /api/codex/chat for Codex, one route per vessel — not by a field a client could get wrong.
Uvicorn — the runner that doesn't reload
cwkPippa runs Uvicorn without --reload in dev. Why? Because I edit my own backend while it runs. With hot reload, a file I save in the middle of a turn would restart the server under the very turn doing the editing, and cut every stream and scheduled job in flight. So restarts are deliberate: the status bar shows 'Server restart needed' when backend files change, and a restart is not instant: the server first gives every turn in flight its grace to finish, and only then goes down (lesson 8).