14 — Sequence Diagrams: Full MVP Journey¶
Flow 1: Registration & Consent¶
Aisha → Frontend → Clerk Auth → POST /api/v1/patients → PostgreSQL (patient record)
→ event: patient_registered → POST /api/v1/consent (4 purposes) → PostgreSQL (consent records)
→ event: consent_granted → Intake Agent initialized → SSE: welcome message
Flow 2: Document Upload & Auto-Chain¶
Aisha uploads X-ray report
→ Frontend: POST /uploads/presign → { upload_url, doc_id, storage_key }
→ Frontend: PUT upload_url (direct to R2, bypasses API)
→ Frontend: POST /uploads/confirm → document_reference created (status: uploaded)
→ event: document_uploaded → QStash dispatches OCR job
→ SSE: status = parsing
→ PyMuPDF extracts text → status = parsed
→ event: document_parsed
AUTO-CHAIN:
→ Clinical Context Agent triggers
→ extract_clinical_entities (Claude Haiku): "Primary osteoarthritis, right knee"
→ map_to_medical_codes: M17.11 (confidence: 0.95), Kellgren-Lawrence Grade 4
→ generate_fhir_resources: FHIR Condition, FHIR Procedure (27447)
→ store_resources: validated via fhir.resources → PostgreSQL
→ event: fhir_resource_created
EHR UPDATE:
→ Neo4j: Patient→DIAGNOSED_WITH→Condition(M17.11)→INDICATED_FOR→Procedure(27447)
→ Qdrant: patient clinical embedding re-indexed
→ EHR Builder: patient record updated
→ intake_progress recalculated (e.g., 0.35 → 0.55)
→ SSE: ehr_update + intake_progress events
→ Left panel refreshes with new condition
Flow 3: Chat Data Extraction¶
Aisha types: "I also have Type 2 diabetes and mild hypertension"
→ POST /api/v1/patients/{id}/chat
→ Orchestrator: classify_intent → "intake_update"
→ Intake Agent: collect_information node
→ Extracts: E11 (diabetes, confidence 0.88), I10 (hypertension, confidence 0.85)
→ FHIR Condition resources created and validated
→ event: clinical_entities_extracted
EHR MERGE:
→ EHR Builder: merge new conditions (additive, no overwrite of existing M17.11)
→ Conflict check: no conflict (new conditions, not updates)
→ intake_progress: 0.55 → 0.68
→ SSE: ehr_update + progress update
AGENT RESPONSE:
→ Intake Agent: suggest_actions node
→ "Thanks, Aisha. I've noted your diabetes and hypertension. Given your diabetes,
we'll need a recent HbA1c test result. Do you have one?"
→ suggested_actions: [{type: "upload", label: "Upload HbA1c", icon: "📋"}]
→ SSE: agent_response with content + actions
Key: Single chat message triggers clinical extraction, FHIR creation, graph update, progress recalculation, and intelligent follow-up — all within one conversational turn.
Flow 4: Matching Pipeline¶
intake_progress >= 0.75 (threshold)
→ POST /api/v1/patients/{id}/match
→ Feature flag check: agent_enhanced_matching = ENABLED
STAGE 0 — QDRANT (Semantic Discovery):
→ Voyage AI embeds patient profile (M17.11 + E11 + I10 + preferences)
→ Qdrant ANN search → 25 candidate providers with similarity scores
STAGE 1 — NEO4J (Hard Constraints):
→ Graph traversal: procedure=27447, accredited, visa corridor UAE→{India,Turkey,Thailand,Spain}
→ 25 → 14 candidates (11 eliminated: wrong specialty, no visa corridor, inactive)
STAGE 2 — POSTGRESQL (Weighted Scoring):
→ clinical_fit(0.4) + outcomes(0.2) + cost(0.15) + travel(0.15) + preferences(0.1)
→ 14 providers scored and ranked
STAGE 3 — LLM (Agent-Enhanced):
→ Match Agent: analyze_clinical_picture (Claude Sonnet)
Reviews: M17.11 + E11 + I10 + medications + BMI
Notes: "Diabetes requires endocrinology consult. Metformin bridging protocol needed."
→ Match Agent: rerank_edge_cases (Claude Sonnet, top 5)
Adjusts: Provider X moved up (has integrated diabetes management program)
→ Explanation Agent: generate_explanations (Claude Haiku, Arabic locale)
For each top provider: clinical + cultural + cost reasoning
RESULT:
→ event: match_completed
→ SSE: match results streamed to frontend
→ Provider cards with confidence scores, costs, differentiators, AI reasoning
→ Aisha sees results in conversation thread
→ Can ask: "Why was Apollo ranked first?" → routes to Explanation Agent
Flow 5: Follow-Up & Iteration¶
Aisha: "Can you re-match but prioritize cost over outcomes?"
→ POST /chat → Orchestrator: "preference_update" + "match_query"
→ Update preference weights: cost → 0.30, outcomes → 0.10
→ Re-execute matching pipeline with adjusted weights
→ New results with cost-optimized ranking
→ Explanation Agent generates updated reasoning