Read docs/ARCHITECTURE.md before any non-trivial change.
It covers the request pipeline, agent graph, auth, data model and hosting.
backend/main.py— FastAPI app: auth, SSE/api/chat, persistence, rate limiting.backend/agents/— the LangGraph desk:supervisorroutes → specialists fan out in parallel →synthesizermerges. Wiring lives ingraph.py.frontend/src/ChatPage.tsx— the app; everything else insrc/is small.supabase/migrations/— schema and RLS.
cd backend && pytest # stubs LLM/DB/yfinance in conftest.py — no network, no keys
cd frontend && npm run test- Two OpenAI keys, deliberately.
OPENAI_API_KEYis the Thesys key (sk-th-…) for the synthesizer;DESK_OPENAI_API_KEYis the real OpenAI key for the supervisor and specialists, and must be passed explicitly — seeagents/models.py. Collapsing them 401s. - The synthesizer must stay on Thesys. Its output is the C1 DSL the frontend renders; any other model breaks the UI.
- Scope every DB query by
user['id']. The backend connects asservice_role, which bypasses RLS — the query is the access control. - Only synthesizer text gets persisted. Status lines and stream-error text
are deliberately kept out of
chunksinmain.py. - Tools never raise on user input — they return a "no data" string so the agent can retry with an exchange suffix. Keep that contract.
- Everything Supabase-related degrades gracefully when env vars are unset; local dev and tests rely on that. Don't make it required.