Skip to content

Steer-04: Clinical Context Autochain — Document → Parse → Extract → FHIR → Graph → Embedding

Read first: specs/sdd-mvp/04-agent-pipeline.md, specs/sdd-mvp/07-document-pipeline.md, specs/sdd-mvp/05-ehr-builder.md

Context & Goal

Wire the complete auto-chain: when a document is uploaded and parsed, the Clinical Context Agent automatically triggers, extracts entities, creates FHIR resources, updates the Neo4j graph, indexes in Qdrant, and updates the EHR — all async, non-blocking, with SSE status updates at each step.


Backend (curaway-ai/curaway-backend)

Step 1: Verify Document Upload Pipeline

Ensure the existing upload pipeline emits correct events: - POST /uploads/confirm → creates document_reference (status: uploaded) → emits document_uploaded - QStash handler receives callback → runs PyMuPDF → updates status to parsed → emits document_parsed - If PyMuPDF fails → try Unstructured.io → try Claude Vision → status failed if all fail

Step 2: Auto-Chain Trigger

In QStash document parse handler (or as a new QStash callback): - On document_parsed event, check if extracted_text has clinical content (> 100 chars, not just headers) - If clinical content: dispatch Clinical Context Agent via QStash (non-blocking) - Update document analysis_status to analyzing - Emit document_analyzing event (SSE: status update)

Step 3: Clinical Context Agent Integration

Ensure Clinical Context Agent: 1. Receives document_id + patient_id + tenant_id + extracted_text 2. Runs LangGraph: extract_clinical_entitiesmap_to_medical_codesgenerate_fhir_resourcesstore_resources 3. Each FHIR resource stored → emits fhir_resource_created event 4. Updates document analysis_status to completed 5. Emits clinical_entities_extracted event with summary

Step 4: Post-FHIR Graph + Embedding Updates

Create event handler for fhir_resource_created: - Neo4j: Add/update nodes and relationships - New Condition → (Patient)-[:DIAGNOSED_WITH]->(Condition) + (Condition)-[:INDICATED_FOR]->(Procedure) if procedure can be inferred - New Procedure → link to patient - New AllergyIntolerance → (Patient)-[:HAS_ALLERGY]->(Allergy) - Qdrant: Re-generate patient clinical embedding (concatenate all conditions + procedures + meds as text → Voyage AI embed → upsert) - EHR Builder: Call merge_clinical_entities() to update patient record

Step 5: End-to-End Chain Test

Create integration test that: 1. Uploads a sample radiology report (mock PyMuPDF extraction) 2. Verifies document status transitions: uploaded → parsing → parsed → analyzing → analyzed 3. Verifies FHIR Condition created with correct ICD code 4. Verifies Neo4j has new patient→condition relationship 5. Verifies intake_progress increased 6. Verifies SSE events emitted at each step

Backend Verification

python -m pytest tests/test_clinical_autochain.py -v
# Manual: upload a PDF, watch events table for the full chain

Frontend (curaway-ai/curaway-frontend)

Step 1: Document Status Cards in Conversation

Update src/components/chat/DocumentCard.tsx: - Show real-time status transitions via SSE document_update events - States: uploading (progress bar) → parsing (spinner) → analyzing (pulsing) → complete (green check + extracted entities) - On complete: show extracted findings summary (conditions found, labs extracted) - "View Details" link opens document detail in left panel

Step 2: Upload Flow in Chat Input

Update src/components/chat/ChatInput.tsx: - File attachment button (📎) triggers native file picker - On file select: show file name + upload progress in conversation - Execute presign → upload → confirm flow - Insert DocumentCard into conversation thread - SSE takes over for status updates after confirm

Step 3: Analysis Results Rendering

When document analysis completes, render results inline: - Condition badges with ICD codes - Lab value table (if observations extracted) - Medication list (if medications found) - Anomaly flags (expired, out of range) with warning styling

Frontend Verification

npm run build
npx tsc --noEmit
# Manual: upload a PDF in chat, watch status transitions, verify findings display

Checklist

  • [ ] No new migrations (document_references table exists)
  • [ ] Seed data: sample radiology report for testing
  • [ ] Error codes: CHAIN_PARSE_001, CHAIN_EXTRACT_001, CHAIN_GRAPH_001
  • [ ] Feature flag: clinical_autochain — disable to decouple document parsing from agent extraction
  • [ ] Env vars: verify VOYAGE_AI_API_KEY, QDRANT_URL, NEO4J_URI all set
  • [ ] Swagger: no new endpoints, but document status field values documented
  • [ ] Unit tests: full chain integration test
  • [ ] PostHog: document_uploaded_in_chat, analysis_completed, findings_viewed
  • [ ] Loading states: each status transition has distinct visual
  • [ ] Mobile: document cards responsive, upload works from mobile camera roll
  • [ ] CLAUDE.md: update with autochain flow description
  • [ ] Rollback: disable clinical_autochain flag → documents parsed but not auto-analyzed