Skip to content

0006 — Praetor on FastAPI + LangGraph

  • Status: Accepted
  • Date: 2026-05-15
  • Deciders: @sinidious

Context

Praetor — the central brain — has to:

  • Serve HTTP and WebSocket endpoints for the dashboard and the HA Bridge.
  • Drive a deterministic, inspectable conversation/agent flow.
  • Persist intermediate state so we can audit and replay decisions (ADR-0012).
  • Stay readable to a maintainer who is not a full-time platform engineer.

Hand-rolling an asyncio event loop with a custom state machine is plausible but throws away years of community work on agent frameworks. LangGraph in particular models agent runtimes as explicit, typed graphs of nodes — a natural fit for an audit-friendly orchestrator.

Decision

Praetor is a Python service built on FastAPI for the HTTP/WS surface and LangGraph for the orchestration graph. Specifically:

  • FastAPI owns request lifecycle, auth, and OpenAPI generation.
  • LangGraph owns the agent state machine. Each user turn enters a graph with explicit nodes (intent classification, policy check, worker dispatch, response synthesis) and edges that can branch on state.
  • LangGraph's checkpointer writes to SQLite, the same database that backs the audit log. This gives us replay and inspection without building a parallel persistence layer.
  • The LLM Gateway (ADR-0011) sits between LangGraph nodes and any provider; nodes never import provider SDKs directly.

Alternatives considered

  • LangChain alone — too unstable an API surface; LangGraph's graph-of-state model is the part we actually want.
  • CrewAI / AutoGen — opinionated multi-agent orchestrators; the opinion ("agents talk to agents in natural language") works against auditability.
  • A hand-written asyncio state machine — fewest dependencies, highest control. Rejected because we'd reinvent checkpointing, serialization, and the node abstraction.
  • Temporal / Prefect — overkill for a homelab single-node service; good if Praetor ever needs multi-node durable workflows.

Consequences

Positive

  • Every conversation has a typed graph, a persisted state, and a replayable history.
  • FastAPI's dependency injection and OpenAPI generation cut a lot of boilerplate.
  • LangGraph's node concept maps almost 1:1 to "things we want to audit and policy-check."

Negative

  • LangGraph is young; APIs may break between minor versions. We pin carefully and treat updates as PRs, not background work.
  • Anyone learning the codebase has to learn LangGraph first.

Neutral

  • Workers (ADR-0009) are not LangGraph nodes. They are separate processes that LangGraph nodes dispatch to over NATS. This keeps the graph small and the workers swappable.

References