Architecture
- Thin client / serverless backend split: the Streamlit UI holds no AI logic, only HTTP calls to the Modal backend.
- 5 FastAPI endpoints (health, threads, history, ingest, chat) guarded by bearer tokens; /chat streams tokens.
- Agentic tool loop via a LangGraph StateGraph with a chat node and a ToolNode, routed by tools_condition.
- Per-thread PDF retrieval scoped by a Qdrant payload filter, so a chat can only ever see its own document.