{
  "id": "EorVl6kyafaJeRF0",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Daily Chronic Care Monitoring with AI Risk Assessment",
  "tags": [],
  "nodes": [
    {
      "id": "8b6b5ee3-8938-45f2-ad49-256bc7efa995",
      "name": "On Workflow Error",
      "type": "n8n-nodes-base.errorTrigger",
      "position": [
        -224,
        1440
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "c439f5de-a13b-4000-ac95-ab999008da2b",
      "name": "Slack: Error Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        32,
        1440
      ],
      "parameters": {
        "text": "=Error occured ",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0AN1UGL0RM",
          "cachedResultName": "all-n8n-automations"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "3f9d0107-9036-4047-a0fa-63d3aefb92e5",
      "name": "Section: Error Handler",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -304,
        1296
      ],
      "parameters": {
        "color": 7,
        "width": 492,
        "height": 328,
        "content": "## \u26a0\ufe0f Error Handler\nCatches any failure across the entire workflow and immediately sends a Slack alert to the ops channel. Wire this to every sub-workflow or critical node to ensure no silent failures."
      },
      "typeVersion": 1
    },
    {
      "id": "043f497f-016a-4cb3-82ca-3a95a3bc7360",
      "name": "\ud83d\udccb Workflow Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -848,
        -128
      ],
      "parameters": {
        "width": 752,
        "height": 480,
        "content": "## \ud83c\udfe5 Chronic Care Daily Monitoring Agent\n\n### How it works\nEvery day at 6 AM, this workflow pulls patient vitals from three Google Sheets tabs \u2014 blood pressure, glucose, and activity/sleep. It merges all readings into one record per patient, then runs a rule-based risk scoring engine (built on AHA and ADA clinical guidelines) to detect anomalies like hypertensive crises, hypoglycaemia, or severe sleep deprivation.\n\nPatients flagged as HIGH or CRITICAL risk trigger a clinical intervention plan, a Telegram alert to the doctor, and a detailed email summary. Low-risk patients receive a routine daily update by email. Every result \u2014 escalated or not \u2014 is logged back to Google Sheets for audit and trend tracking.\n\n### Setup steps\n1. Connect **Google Sheets OAuth2** and point all sheet nodes to your own spreadsheet ID\n2. Set up a **Telegram Bot** via @BotFather and update the doctor's chat ID in the alert node\n3. Connect **Gmail OAuth2** and replace placeholder emails with your clinic's doctor address\n4. Ensure your Google Sheet has tabs: `BloodPressure`, `Glucose`, `Activity`, `PatientMaster`, and `DailyLog`\n5. Set the Schedule Trigger to your preferred daily run time (default: every 24 hours)\n6. Run once in test mode with sample data before activating"
      },
      "typeVersion": 1
    },
    {
      "id": "e82131d8-7e23-4d57-9eed-a2e8dc216485",
      "name": "Section: Trigger",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        64,
        544
      ],
      "parameters": {
        "color": 7,
        "width": 316,
        "height": 380,
        "content": "## \u23f0 Scheduled Trigger\nFires once every 24 hours to kick off the daily monitoring cycle. Adjust the interval or use a cron expression to set a specific time like 6 AM."
      },
      "typeVersion": 1
    },
    {
      "id": "79d00aea-e66e-4c15-855e-3dd366207072",
      "name": "Section: Vitals Ingestion",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 484,
        "height": 1328,
        "content": "## \ud83d\udce5 Vitals Data Ingestion\nReads today's rows from three separate sheet tabs in parallel \u2014 blood pressure, glucose, and activity/sleep. All four streams (including patient master) merge into a single pipeline before processing."
      },
      "typeVersion": 1
    },
    {
      "id": "7979aba3-101f-49a9-87c6-66f01c3f1d63",
      "name": "Section: Merge & Scoring",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        912,
        464
      ],
      "parameters": {
        "color": 7,
        "width": 900,
        "height": 576,
        "content": "## \ud83d\udd04 Merge & Risk Scoring\nCombines all readings into one structured record per patient, then scores each one against clinical thresholds. Scores \u2265 70 or any critical anomaly trigger escalation; everything else takes the routine path."
      },
      "typeVersion": 1
    },
    {
      "id": "09f5f14f-5af6-43a7-b516-04d9d5f6ae8b",
      "name": "Section: Escalation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1872,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 1220,
        "height": 816,
        "content": "## \ud83d\udea8 Escalation \u2014 High/Critical Risk\nGenerates a prioritised intervention plan, then fires both a Telegram message to the doctor and a detailed HTML email. Both outputs merge before writing the escalated record to Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "e4b97035-6092-4882-abcf-380a12878b93",
      "name": "Section: Routine Logging",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1936,
        1040
      ],
      "parameters": {
        "color": 7,
        "width": 748,
        "height": 364,
        "content": "## \ud83d\udfe2 Routine \u2014 Low/Medium Risk\nPatients within safe thresholds get a brief status email and their record appended to the daily log. No clinical action required \u2014 this path keeps the audit trail complete."
      },
      "typeVersion": 1
    },
    {
      "id": "cad0203f-ccdd-4cbe-9530-3875419bfe88",
      "name": "Security Notes",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3120,
        1024
      ],
      "parameters": {
        "color": 3,
        "width": 288,
        "height": 226,
        "content": "## \ud83d\udd10 Credentials & Security\nUse OAuth2 for Google Sheets and Gmail. Create a dedicated Telegram bot via @BotFather. Replace all personal emails, sheet IDs, and chat IDs with placeholders before sharing this template."
      },
      "typeVersion": 1
    },
    {
      "id": "6811a77b-bf6d-4891-9322-c9808de92d80",
      "name": "Daily Schedule Trigger (Every 24h)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        176,
        720
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 24
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "4dafe826-f2a2-423b-b04d-8d509db562f5",
      "name": "Read: Blood Pressure Readings",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        608,
        400
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 462669290,
          "cachedResultName": "BloodPressure"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultName": "chronic_care_google_sheet"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "0ff63aa5-2a6e-4ccc-a702-d99d49eedda9",
      "name": "Read: Glucose Readings",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        608,
        640
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 155610296,
          "cachedResultName": "Glucose"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultName": "chronic_care_google_sheet"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "9300ae3f-051e-4db8-94b8-21d9e4ff7927",
      "name": "Read: Activity & Sleep Data",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        608,
        864
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1087489261,
          "cachedResultName": "Activity"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultName": "chronic_care_google_sheet"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "f7a8dd09-adb9-45aa-b7e9-2e67e578d53d",
      "name": "Merge All Vitals Streams",
      "type": "n8n-nodes-base.merge",
      "position": [
        976,
        704
      ],
      "parameters": {
        "numberInputs": 4
      },
      "typeVersion": 3.2
    },
    {
      "id": "c3ab8f28-165f-4a5c-8726-b5304670663f",
      "name": "Merge: One Structured Record Per Patient",
      "type": "n8n-nodes-base.code",
      "position": [
        1200,
        736
      ],
      "parameters": {
        "jsCode": "// ================================================\n// MERGE ALL SHEETS \u2192 ONE ROW PER PATIENT PER DAY\n// ================================================\n\nconst bpRows       = $('Read: Blood Pressure Readings').all().map(i => i.json);\nconst glucoseRows  = $('Read: Glucose Readings').all().map(i => i.json);\nconst activityRows = $('Read: Activity & Sleep Data').all().map(i => i.json);\nconst patientRows  = $('Read: Patient Master List').all().map(i => i.json);\n\n// Index patients by ID\nconst patientMap = {};\nfor (const p of patientRows) {\n  patientMap[p.PatientID] = p;\n}\n\n// Collect all unique patient IDs seen today\nconst allIDs = new Set([\n  ...bpRows.map(r => r.PatientID),\n  ...glucoseRows.map(r => r.PatientID),\n  ...activityRows.map(r => r.PatientID)\n]);\n\nconst results = [];\n\nfor (const pid of allIDs) {\n  const patient = patientMap[pid] || {};\n\n  const bpList = bpRows.filter(r => r.PatientID === pid);\n  const bp     = bpList.length > 0 ? bpList[bpList.length - 1] : {};\n\n  const glList = glucoseRows.filter(r => r.PatientID === pid);\n  const gl     = glList.length > 0 ? glList[glList.length - 1] : {};\n\n  const acList = activityRows.filter(r => r.PatientID === pid);\n  const ac     = acList.length > 0 ? acList[acList.length - 1] : {};\n\n  results.push({\n    json: {\n      patientId:   pid,\n      patientName: patient.PatientName || bp.PatientName || gl.PatientName || 'Unknown',\n      patientEmail: patient.PatientEmail || '',\n      doctorEmail:  patient.DoctorEmail  || 'user@example.com',\n      condition:    patient.Condition    || '',\n      date:         new Date().toISOString().split('T')[0],\n      targets: {\n        systolic:        parseInt(patient.TargetBP_Sys)         || 130,\n        diastolic:       parseInt(patient.TargetBP_Dia)         || 80,\n        glucoseFasting:  parseInt(patient.TargetGlucose_Fasting)|| 126,\n        steps:           parseInt(patient.TargetSteps)          || 7000\n      },\n      vitals: {\n        bloodPressure: {\n          systolic:  bp.Systolic  ? parseInt(bp.Systolic)  : null,\n          diastolic: bp.Diastolic ? parseInt(bp.Diastolic) : null,\n          pulse:     bp.Pulse     ? parseInt(bp.Pulse)     : null,\n          time:      bp.Time || null\n        },\n        glucose: {\n          level:    gl.GlucoseLevel ? parseFloat(gl.GlucoseLevel) : null,\n          mealType: gl.MealType     || 'unknown',\n          insulin:  gl.InsulinTaken || 'No'\n        }\n      },\n      activity: {\n        steps:         ac.Steps          ? parseInt(ac.Steps)          : null,\n        activeMinutes: ac.ActiveMinutes  ? parseInt(ac.ActiveMinutes)  : null,\n        calories:      ac.CaloriesBurned ? parseInt(ac.CaloriesBurned) : null,\n        weight:        ac.Weight_kg      ? parseFloat(ac.Weight_kg)    : null\n      },\n      sleep: {\n        hours:   ac.SleepHours   ? parseFloat(ac.SleepHours) : null,\n        quality: ac.SleepQuality || null\n      },\n      dataCompleteness: {\n        hasBP:       bp.Systolic     != null,\n        hasGlucose:  gl.GlucoseLevel != null,\n        hasActivity: ac.Steps        != null,\n        hasSleep:    ac.SleepHours   != null\n      }\n    }\n  });\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "d4bbbb4e-fa72-41f6-b0a1-565a0074f326",
      "name": "Risk Scoring Engine (AHA/ADA Guidelines)",
      "type": "n8n-nodes-base.code",
      "position": [
        1440,
        736
      ],
      "parameters": {
        "jsCode": "// ================================================\n// AI RISK SCORING ENGINE\n// AHA + ADA clinical guidelines\n// ================================================\n\nconst d = $input.item.json;\nconst { vitals, activity, sleep, targets } = d;\n\nconst anomalies = [];\nlet riskPoints  = 0;\nlet maxRisk     = 0;\n\nif (vitals.bloodPressure.systolic !== null) {\n  const sys = vitals.bloodPressure.systolic;\n  const dia = vitals.bloodPressure.diastolic;\n  maxRisk += 30;\n\n  if (sys >= 180 || dia >= 120) {\n    anomalies.push({ severity:'critical', category:'blood_pressure',\n      message:`Hypertensive Crisis: ${sys}/${dia} mmHg \u2013 IMMEDIATE ACTION` });\n    riskPoints += 30;\n  } else if (sys >= 140 || dia >= 90) {\n    anomalies.push({ severity:'high', category:'blood_pressure',\n      message:`Stage 2 Hypertension: ${sys}/${dia} mmHg` });\n    riskPoints += 20;\n  } else if (sys >= 130 || dia >= 80) {\n    anomalies.push({ severity:'medium', category:'blood_pressure',\n      message:`Stage 1 Hypertension: ${sys}/${dia} mmHg` });\n    riskPoints += 10;\n  } else if (sys < 90 || dia < 60) {\n    anomalies.push({ severity:'high', category:'blood_pressure',\n      message:`Hypotension: ${sys}/${dia} mmHg` });\n    riskPoints += 15;\n  }\n}\n\nif (vitals.glucose.level !== null) {\n  const g  = vitals.glucose.level;\n  const ft = vitals.glucose.mealType.toLowerCase().includes('fast');\n  maxRisk += 30;\n\n  if (g < 70) {\n    anomalies.push({ severity:'critical', category:'glucose',\n      message:`HYPOGLYCEMIA: ${g} mg/dL \u2013 URGENT` });\n    riskPoints += 30;\n  } else if (g >= (ft ? 180 : 250)) {\n    anomalies.push({ severity:'critical', category:'glucose',\n      message:`Severe Hyperglycemia: ${g} mg/dL (${vitals.glucose.mealType})` });\n    riskPoints += 30;\n  } else if (g >= (ft ? 126 : 200)) {\n    anomalies.push({ severity:'high', category:'glucose',\n      message:`Hyperglycemia: ${g} mg/dL (${vitals.glucose.mealType})` });\n    riskPoints += 20;\n  } else if (g >= (ft ? 100 : 140)) {\n    anomalies.push({ severity:'medium', category:'glucose',\n      message:`Pre-diabetic range: ${g} mg/dL (${vitals.glucose.mealType})` });\n    riskPoints += 10;\n  }\n}\n\nif (activity.steps !== null) {\n  maxRisk += 10;\n  if (activity.steps < 2000) {\n    anomalies.push({ severity:'medium', category:'activity',\n      message:`Very low activity: ${activity.steps} steps (target: ${targets.steps})` });\n    riskPoints += 7;\n  } else if (activity.steps < 4000) {\n    anomalies.push({ severity:'low', category:'activity',\n      message:`Below activity target: ${activity.steps} steps` });\n    riskPoints += 3;\n  }\n}\n\nif (sleep.hours !== null) {\n  maxRisk += 10;\n  if (sleep.hours < 5) {\n    anomalies.push({ severity:'medium', category:'sleep',\n      message:`Insufficient sleep: ${sleep.hours}h (target: 7-9h)` });\n    riskPoints += 8;\n  } else if (sleep.hours < 6) {\n    anomalies.push({ severity:'low', category:'sleep',\n      message:`Low sleep: ${sleep.hours}h` });\n    riskPoints += 4;\n  }\n  if (sleep.quality === 'Very Poor') {\n    anomalies.push({ severity:'medium', category:'sleep',\n      message:`Very poor sleep quality reported` });\n    riskPoints += 4;\n  }\n}\n\nconst riskScore = maxRisk > 0 ? Math.min(100, Math.round((riskPoints / maxRisk) * 100)) : 0;\nconst hasCritical = anomalies.some(a => a.severity === 'critical');\nconst hasHigh     = anomalies.some(a => a.severity === 'high');\n\nlet riskLevel, escalate;\nif (hasCritical || riskScore >= 70) { riskLevel = 'CRITICAL'; escalate = true; }\nelse if (hasHigh || riskScore >= 40) { riskLevel = 'HIGH';     escalate = true; }\nelse if (riskScore >= 20)            { riskLevel = 'MEDIUM';   escalate = false; }\nelse                                  { riskLevel = 'LOW';      escalate = false; }\n\nreturn [{ json: {\n  ...d,\n  analysis: {\n    riskScore, riskLevel, escalate,\n    anomalies,\n    totalAnomalies: anomalies.length,\n    criticalCount:  anomalies.filter(a => a.severity === 'critical').length,\n    timestamp: new Date().toISOString()\n  }\n}}];"
      },
      "typeVersion": 2
    },
    {
      "id": "c08cb301-7be5-4dde-8597-57dac4eaa952",
      "name": "Route: Escalate to Clinician?",
      "type": "n8n-nodes-base.if",
      "position": [
        1664,
        736
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-1",
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $json.analysis.escalate }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "05523450-d6b1-4437-9e2b-c2c2df2ad4aa",
      "name": "Generate Clinical Intervention Plan",
      "type": "n8n-nodes-base.code",
      "position": [
        1968,
        592
      ],
      "parameters": {
        "jsCode": "// ================================================\n// CLINICAL INTERVENTION RECOMMENDATIONS\n// ================================================\n\nconst d = $input.item.json;\nconst { analysis, vitals, activity, sleep } = d;\nconst recs = [];\n\nconst bp  = vitals.bloodPressure;\nconst glu = vitals.glucose;\n\nif (bp.systolic >= 180) {\n  recs.push({ priority:1, action:'IMMEDIATE',\n    rec:'Emergency evaluation. Hypertensive crisis protocol. Check for headache, chest pain, or vision changes. Consider IV antihypertensive.',\n    followUp:'2 hours' });\n} else if (bp.systolic >= 140) {\n  recs.push({ priority:2, action:'REVIEW MEDICATION',\n    rec:'Review antihypertensive adherence and dosing. Consider adjusting ACE inhibitor/ARB. Home BP monitoring twice daily.',\n    followUp:'24 hours' });\n  recs.push({ priority:4, action:'LIFESTYLE',\n    rec:'DASH diet counselling. Sodium restriction <2,300mg/day. 30 min aerobic activity 5x/week.',\n    followUp:'1 week' });\n} else if (bp.systolic >= 130) {\n  recs.push({ priority:3, action:'MONITOR',\n    rec:'Stage 1 hypertension. Reinforce lifestyle changes. Reassess in 1 month.',\n    followUp:'1 month' });\n}\n\nif (bp.systolic !== null && bp.systolic < 90) {\n  recs.push({ priority:1, action:'IMMEDIATE',\n    rec:'Hypotension detected. Check for dehydration, medication side effects, or orthostatic hypotension. Increase fluid intake.',\n    followUp:'4 hours' });\n}\n\nif (glu.level !== null) {\n  const g = glu.level;\n  if (g < 70) {\n    recs.push({ priority:1, action:'IMMEDIATE',\n      rec:'Hypoglycaemia protocol: 15-20g fast-acting carbs now (juice/glucose tablets). Recheck in 15 min. Review insulin dosing.',\n      followUp:'15 minutes' });\n  } else if (g > 250) {\n    recs.push({ priority:2, action:'CONTACT PATIENT',\n      rec:'Severe hyperglycaemia. Check ketones if T1D. Review medication adherence. Assess for illness/stress trigger.',\n      followUp:'4 hours' });\n  } else if (g > 180) {\n    recs.push({ priority:3, action:'REVIEW MEDICATION',\n      rec:'Uncontrolled hyperglycaemia. Review current diabetes medication. Consider dose adjustment or adding GLP-1 agonist.',\n      followUp:'48 hours' });\n  }\n}\n\nif (activity.steps !== null && activity.steps < 2000) {\n  recs.push({ priority:4, action:'LIFESTYLE',\n    rec:'Severe sedentary behaviour. Prescribe structured 20-min daily walks. Consider physiotherapy referral.',\n    followUp:'1 week' });\n}\n\nif (sleep.hours !== null && sleep.hours < 5) {\n  recs.push({ priority:4, action:'LIFESTYLE',\n    rec:'Severe sleep deprivation worsens BP and glucose control. Screen for sleep apnoea. CBT-I or sleep hygiene programme.',\n    followUp:'2 weeks' });\n}\n\nrecs.sort((a,b) => a.priority - b.priority);\n\nreturn [{ json: {\n  ...d,\n  interventions: {\n    recommendations: recs,\n    totalRecs: recs.length,\n    immediateActions: recs.filter(r => r.action === 'IMMEDIATE').length,\n    generatedAt: new Date().toISOString()\n  }\n}}];"
      },
      "typeVersion": 2
    },
    {
      "id": "4c3ae566-bd08-4628-be98-d38338727037",
      "name": "Telegram: Send Risk Alert to Doctor",
      "type": "n8n-nodes-base.telegram",
      "position": [
        2288,
        432
      ],
      "parameters": {
        "text": "=\ud83d\udea8 *{{ $json.analysis.riskLevel }} RISK \u2013 {{ $json.patientName }}*\n\n\ud83d\udc64 *Patient:* {{ $json.patientName }} ({{ $json.patientId }})\n\ud83c\udfe5 *Condition:* {{ $json.condition }}\n\ud83d\udcc5 *Date:* {{ $json.date }}\n\u26a0\ufe0f *Risk Score:* {{ $json.analysis.riskScore }}/100\n\n\ud83d\udcca *VITALS*\n{{ $json.vitals.bloodPressure.systolic !== null ? '\ud83e\ude7a BP: ' + $json.vitals.bloodPressure.systolic + '/' + $json.vitals.bloodPressure.diastolic + ' mmHg\\n' : '\ud83e\ude7a BP: not logged\\n' }}{{ $json.vitals.glucose.level !== null ? '\ud83e\ude78 Glucose: ' + $json.vitals.glucose.level + ' mg/dL (' + $json.vitals.glucose.mealType + ')\\n' : '\ud83e\ude78 Glucose: not logged\\n' }}\ud83d\udeb6 Steps: {{ $json.activity.steps ?? 'not logged' }}\n\ud83d\ude34 Sleep: {{ $json.sleep.hours ?? 'not logged' }}h ({{ $json.sleep.quality ?? '-' }})\n\n\ud83d\udd34 *ANOMALIES ({{ $json.analysis.totalAnomalies }})*\n{{ $json.analysis.anomalies.map(a => (a.severity==='critical'?'\ud83d\udd34':a.severity==='high'?'\ud83d\udfe0':'\ud83d\udfe1') + ' ' + a.message).join('\\n') }}\n\n_Chronic Care Monitoring Agent_",
        "chatId": "YOUR_DOCTOR_TELEGRAM_CHAT_ID",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "27d9c611-1813-4d02-be15-dca8cf158672",
      "name": "Gmail: Send Escalation Alert Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2288,
        720
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "=<h2>\ud83d\udea8 Patient Risk Alert</h2><p><strong>Patient:</strong> {{ $json.patientName }} ({{ $json.patientId }})</p><p><strong>Condition:</strong> {{ $json.condition }}</p><p><strong>Date:</strong> {{ $json.date }}</p><hr><h3>Risk Assessment</h3><p><strong>Risk Level:</strong> {{ $json.analysis.riskLevel }}<br><strong>Risk Score:</strong> {{ $json.analysis.riskScore }}/100<br><strong>Total Anomalies:</strong> {{ $json.analysis.totalAnomalies }}</p><hr><h3>Vitals</h3><ul><li>Blood Pressure: {{ $json.vitals.bloodPressure.systolic }}/{{ $json.vitals.bloodPressure.diastolic }} mmHg</li><li>Pulse: {{ $json.vitals.bloodPressure.pulse }} bpm</li><li>Glucose: {{ $json.vitals.glucose.level }} mg/dL ({{ $json.vitals.glucose.mealType }})</li><li>Steps: {{ $json.activity.steps }}</li><li>Sleep: {{ $json.sleep.hours }} hrs</li></ul><hr><h3>Detected Issues</h3><ul>{{ $json.analysis.anomalies.map(a => `<li><b>${a.severity.toUpperCase()}</b> - ${a.message}</li>`).join('') }}</ul><hr><h3>Recommended Action</h3><p>Please review this patient immediately and determine whether intervention, medication adjustment, or patient outreach is required.</p><p>Generated by Chronic Care Monitoring AI Workflow</p>",
        "options": {},
        "subject": "=\ud83d\udea8 {{ $json.analysis.riskLevel }} Risk Alert - {{ $json.patientName }} ({{ $json.patientId }})"
      },
      "typeVersion": 2.2
    },
    {
      "id": "ce9b25cd-0b8f-4049-a3dd-3f5560b809a8",
      "name": "Merge: Telegram + Email Outputs",
      "type": "n8n-nodes-base.merge",
      "position": [
        2592,
        560
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "a0779d72-77a3-451d-ae8f-96a0b0b58db5",
      "name": "Log: Write Escalated Record to Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2880,
        560
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $('Risk Scoring Engine (AHA/ADA Guidelines)').item.json.date }}",
            "Steps": "={{ $('Risk Scoring Engine (AHA/ADA Guidelines)').item.json.activity.steps }}",
            "Systolic": "={{ $('Risk Scoring Engine (AHA/ADA Guidelines)').item.json.vitals.bloodPressure.systolic }}",
            "Anomalies": "={{ $('Risk Scoring Engine (AHA/ADA Guidelines)').item.json.analysis.anomalies }}",
            "Diastolic": "={{ $('Risk Scoring Engine (AHA/ADA Guidelines)').item.json.vitals.bloodPressure.diastolic }}",
            "Escalated": "={{ $('Risk Scoring Engine (AHA/ADA Guidelines)').item.json.analysis.escalate }}",
            "PatientID": "={{ $('Risk Scoring Engine (AHA/ADA Guidelines)').item.json.patientId }}",
            "RiskLevel": "={{ $('Risk Scoring Engine (AHA/ADA Guidelines)').item.json.analysis.riskLevel }}",
            "RiskScore": "={{ $('Risk Scoring Engine (AHA/ADA Guidelines)').item.json.analysis.riskScore }}",
            "Timestamp": "={{ $('Risk Scoring Engine (AHA/ADA Guidelines)').item.json.analysis.timestamp }}",
            "SleepHours": "={{ $('Risk Scoring Engine (AHA/ADA Guidelines)').item.json.sleep.hours }}",
            "PatientName": "={{ $('Risk Scoring Engine (AHA/ADA Guidelines)').item.json.patientName }}",
            "AnomalyCount": "={{ $('Risk Scoring Engine (AHA/ADA Guidelines)').item.json.analysis.totalAnomalies }}"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "PatientID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "PatientID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "PatientName",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "PatientName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "RiskScore",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "RiskScore",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "RiskLevel",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "RiskLevel",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Escalated",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Escalated",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Systolic",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Systolic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Diastolic",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Diastolic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "HeartRate",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "HeartRate",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Glucose",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Glucose",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "GlucoseMeal",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "GlucoseMeal",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Steps",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Steps",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SleepHours",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "SleepHours",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "AnomalyCount",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "AnomalyCount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Anomalies",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Anomalies",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Recommendations",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Recommendations",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "PatientID"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "DailyLog"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultName": "chronic_care_google_sheet"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "49d49c16-47c4-4c3b-8957-4cb32bd225b3",
      "name": "Log: Write Normal Record to Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2064,
        1232
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $json.date }}",
            "Steps": "={{ $json.activity.steps }}",
            "Glucose": "={{ $json.vitals.glucose.level }}",
            "Systolic": "={{ $json.vitals.bloodPressure.systolic }}",
            "Anomalies": "={{ $json.analysis.anomalies.map(a => a.message).join(' | ') }}",
            "Diastolic": "={{ $json.vitals.bloodPressure.diastolic }}",
            "Escalated": "=false",
            "PatientID": "={{ $json.patientId }}",
            "RiskLevel": "={{ $json.analysis.riskLevel }}",
            "RiskScore": "={{ $json.analysis.riskScore }}",
            "Timestamp": "={{ $json.analysis.timestamp }}",
            "SleepHours": "={{ $json.sleep.hours }}",
            "GlucoseMeal": "={{ $json.vitals.glucose.mealType }}",
            "PatientName": "={{ $json.patientName }}",
            "AnomalyCount": "={{ $json.analysis.totalAnomalies }}"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "PatientID",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "PatientID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "PatientName",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "PatientName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "RiskScore",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "RiskScore",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "RiskLevel",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "RiskLevel",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Escalated",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Escalated",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Systolic",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Systolic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Diastolic",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Diastolic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "HeartRate",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "HeartRate",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Glucose",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Glucose",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "GlucoseMeal",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "GlucoseMeal",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Steps",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Steps",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SleepHours",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "SleepHours",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "AnomalyCount",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "AnomalyCount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Anomalies",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Anomalies",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Recommendations",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Recommendations",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1523249484,
          "cachedResultName": "DailyLog"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultName": "chronic_care_google_sheet"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "a31e5e9c-ae9d-4c40-8c37-8a0e9643204d",
      "name": "Gmail: Send Routine Status Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2480,
        1232
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "=<h2>\ud83d\udfe2 Patient Status Update</h2>\n\n<p><strong>Patient:</strong> {{ $json.patientName }} ({{ $json.patientId }})</p>\n\n<p><strong>Condition:</strong> {{ $json.condition }}</p>\n\n<p><strong>Date:</strong> {{ $json.date }}</p>\n\n<hr>\n\n<h3>Risk Summary</h3>\n\n<p>\n<strong>Risk Level:</strong> {{ $json.analysis.riskLevel }}<br>\n<strong>Risk Score:</strong> {{ $json.analysis.riskScore }}/100<br>\n<strong>Escalation Required:</strong> No\n</p>\n\n<hr>\n\n<h3>Latest Vitals</h3>\n\n<ul>\n<li>Blood Pressure: {{ $json.vitals.bloodPressure.systolic }}/{{ $json.vitals.bloodPressure.diastolic }} mmHg</li>\n<li>Pulse: {{ $json.vitals.bloodPressure.pulse }} bpm</li>\n<li>Glucose: {{ $json.vitals.glucose.level }} mg/dL ({{ $json.vitals.glucose.mealType }})</li>\n<li>Steps: {{ $json.activity.steps }}</li>\n<li>Sleep: {{ $json.sleep.hours }} hrs</li>\n</ul>\n\n<hr>\n\n<h3>Observation</h3>\n\n<p>\nPatient remains within acceptable monitoring thresholds today.\nNo immediate clinical intervention is required.\nContinue routine monitoring and follow the current care plan.\n</p>\n\n<p>Generated by Chronic Care Monitoring AI Workflow</p>",
        "options": {},
        "subject": "=\u2705 Daily Monitoring Update - {{ $json.patientName }} ({{ $json.patientId }})"
      },
      "typeVersion": 2.2
    },
    {
      "id": "0c093c43-1f42-4a74-8e62-72e9386836c4",
      "name": "\ud83d\udc65 Read: Patient Master List",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "Reads all patients from Patients tab to get targets and contact info.",
      "position": [
        608,
        1088
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1992383121,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/133Pn_5kWnuAeaqyerfFdH62_eQa6shbZqeXP1qAx_TE/edit#gid=1992383121",
          "cachedResultName": "Patients"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "133Pn_5kWnuAeaqyerfFdH62_eQa6shbZqeXP1qAx_TE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/133Pn_5kWnuAeaqyerfFdH62_eQa6shbZqeXP1qAx_TE/edit?usp=drivesdk",
          "cachedResultName": "chronic_care_google_sheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "75c2f495-eda7-4ff3-b3af-ae0e93c59750",
  "connections": {
    "On Workflow Error": {
      "main": [
        [
          {
            "node": "Slack: Error Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read: Glucose Readings": {
      "main": [
        [
          {
            "node": "Merge All Vitals Streams",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge All Vitals Streams": {
      "main": [
        [
          {
            "node": "Merge: One Structured Record Per Patient",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read: Activity & Sleep Data": {
      "main": [
        [
          {
            "node": "Merge All Vitals Streams",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Read: Blood Pressure Readings": {
      "main": [
        [
          {
            "node": "Merge All Vitals Streams",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route: Escalate to Clinician?": {
      "main": [
        [
          {
            "node": "Generate Clinical Intervention Plan",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log: Write Normal Record to Sheet",
            "type": "main",
            "index": 0
          },
          {
            "node": "Gmail: Send Routine Status Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udc65 Read: Patient Master List": {
      "main": [
        [
          {
            "node": "Merge All Vitals Streams",
            "type": "main",
            "index": 3
          }
        ]
      ]
    },
    "Merge: Telegram + Email Outputs": {
      "main": [
        [
          {
            "node": "Log: Write Escalated Record to Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log: Write Normal Record to Sheet": {
      "main": [
        [
          {
            "node": "Gmail: Send Routine Status Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily Schedule Trigger (Every 24h)": {
      "main": [
        [
          {
            "node": "Read: Blood Pressure Readings",
            "type": "main",
            "index": 0
          },
          {
            "node": "Read: Glucose Readings",
            "type": "main",
            "index": 0
          },
          {
            "node": "Read: Activity & Sleep Data",
            "type": "main",
            "index": 0
          },
          {
            "node": "\ud83d\udc65 Read: Patient Master List",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail: Send Escalation Alert Email": {
      "main": [
        [
          {
            "node": "Merge: Telegram + Email Outputs",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Generate Clinical Intervention Plan": {
      "main": [
        [
          {
            "node": "Telegram: Send Risk Alert to Doctor",
            "type": "main",
            "index": 0
          },
          {
            "node": "Gmail: Send Escalation Alert Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram: Send Risk Alert to Doctor": {
      "main": [
        [
          {
            "node": "Merge: Telegram + Email Outputs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge: One Structured Record Per Patient": {
      "main": [
        [
          {
            "node": "Risk Scoring Engine (AHA/ADA Guidelines)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Risk Scoring Engine (AHA/ADA Guidelines)": {
      "main": [
        [
          {
            "node": "Route: Escalate to Clinician?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}