This workflow corresponds to n8n.io template #16428 — we link there as the canonical source.
This workflow follows the Error Trigger → Google Sheets recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "c9h3BSEdms82WnPD",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "AI Post-Therapy Wellness Tracking Workflow",
"tags": [],
"nodes": [
{
"id": "0652ac1d-cb5d-4d21-a382-29e9dd16b458",
"name": "Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-464,
-272
],
"parameters": {
"width": 700,
"height": 588,
"content": "## \ud83e\udde0 Mental Health Check-In Automation\n\n### How it works\nThis workflow automates post-therapy check-ins for mental health practices. Every hour, it scans a Google Sheet for completed therapy sessions that haven't received a follow-up yet. For each eligible session, an AI generates a warm, personalised Telegram message referencing the patient's session notes and treatment goals.\n\nWhen patients reply, a second flow captures their response, runs sentiment analysis, and flags any at-risk replies to the therapist via Slack \u2014 no manual monitoring needed.\n\n### Setup steps\n1. **Google Sheets** \u2014 Connect your OAuth2 account and update the `documentId` in all Sheets nodes to point to your tracker spreadsheet.\n2. **Telegram** \u2014 Connect your bot credentials. Update `chatId` in the send node to match real patient chat IDs stored in your sheet.\n3. **OpenAI** \u2014 Add your API key. The workflow uses `gpt-4o-mini` by default \u2014 swap if needed.\n4. **Slack** \u2014 Connect OAuth2 and update the `channelId` in both Slack nodes to your therapist alert channel.\n5. **Test** \u2014 Pin a sample Telegram message in the Trigger node and run the reply branch manually before going live.\n\n> \u26a0\ufe0f This workflow handles sensitive patient data. Ensure your Google Sheet is access-controlled and shared only with authorised staff."
},
"typeVersion": 1
},
{
"id": "ff63ad86-03f9-4ff9-a8f6-01280b467696",
"name": "Section: AI Check-In Generation",
"type": "n8n-nodes-base.stickyNote",
"position": [
1600,
-48
],
"parameters": {
"color": 7,
"width": 1088,
"height": 408,
"content": "## \ud83d\udcac AI Check-In Message Generation\n\nFor each eligible session, GPT-4o-mini crafts a warm, non-clinical Telegram message personalised with the patient's name, therapist, session notes, and treatment goal. The message is then sent and the sheet is updated to prevent re-sending."
},
"typeVersion": 1
},
{
"id": "6f5593a1-f5fa-4888-b76b-9983f7e3ef58",
"name": "Section: Patient Reply Capture",
"type": "n8n-nodes-base.stickyNote",
"position": [
576,
416
],
"parameters": {
"color": 7,
"width": 1040,
"height": 680,
"content": "## \ud83d\udce5 Patient Reply Capture\n\nA Telegram webhook listens for incoming patient messages. When one arrives, it looks up the patient in the master sheet by their Telegram ID, then fetches their latest session record. Both are merged to give the AI full context for sentiment analysis."
},
"typeVersion": 1
},
{
"id": "a7171af4-ea4d-49a9-8f8f-3144b0c97a60",
"name": "Section: Sentiment Analysis",
"type": "n8n-nodes-base.stickyNote",
"position": [
1632,
416
],
"parameters": {
"color": 7,
"width": 784,
"height": 680,
"content": "## \ud83d\udd0d Sentiment Analysis\n\nThe patient's reply is analysed by GPT-4o-mini, which classifies sentiment as `positive`, `neutral`, or `at-risk`. It also identifies risk indicators and suggests a recommended action. Output is parsed from JSON before routing."
},
"typeVersion": 1
},
{
"id": "6fac06a6-965a-421b-a6a0-06fde2696a11",
"name": "Section: Escalation & Logging",
"type": "n8n-nodes-base.stickyNote",
"position": [
2464,
416
],
"parameters": {
"color": 7,
"width": 592,
"height": 776,
"content": "## \ud83d\udea8 Escalation & Wellness Logging\n\nAt-risk replies trigger an urgent Slack alert to the therapist with full context \u2014 no AI filters this decision further. All other replies are appended to the Wellness Log sheet for longitudinal tracking. Workflow errors are also routed to Slack."
},
"typeVersion": 1
},
{
"id": "95afa0cf-c2a2-4eae-9174-0e5f0bf12ebb",
"name": "Credentials & Security",
"type": "n8n-nodes-base.stickyNote",
"position": [
3088,
1232
],
"parameters": {
"color": 3,
"width": 316,
"height": 224,
"content": "## \ud83d\udd10 Credentials & Security\n\nUse OAuth2 for Google Sheets and Slack. Use API key auth for OpenAI and Telegram bot token for both Telegram nodes. Never hardcode tokens \u2014 store all credentials in n8n's credential manager. Restrict sheet access to authorised staff only."
},
"typeVersion": 1
},
{
"id": "6e594434-19bb-4aa5-b392-46634b5902ff",
"name": "Schedule Trigger (Every Hour)",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
944,
160
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 * * * *"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "d4a08778-cb76-42a1-a219-237613bd782d",
"name": "Read Completed Sessions",
"type": "n8n-nodes-base.googleSheets",
"position": [
1168,
160
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1222247293,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU/edit#gid=1222247293",
"cachedResultName": "Sessions"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU/edit?usp=drivesdk",
"cachedResultName": "Mental health checkin tracker"
}
},
"typeVersion": 4.2
},
{
"id": "d04fd82c-f041-4e1a-ab52-ed9f544c7247",
"name": "AI: Generate Personalised Check-In Message",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
1664,
160
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "GPT-4O-MINI"
},
"options": {},
"messages": {
"values": [
{
"content": "=You are a compassionate mental health care assistant. Generate a warm, personalised follow-up check-in message for a therapy patient.\n\nPatient Name: {{ $json.patient_name }}\nTherapist: {{ $json.therapist_name }}\nSession Date: {{ $json.session_datetime }}\nSession Notes Summary: {{ $json.session_notes }}\nPrimary Concern: {{ $json.primary_concern }}\nTreatment Goal: {{ $json.treatment_goal }}\n\nWrite a caring, non-clinical Telegram message (2-3 short paragraphs max) that:\n1. Warmly checks in on how they are feeling since the session\n2. Gently references something specific from their session notes (without being clinical)\n3. Encourages them to share how they are doing\n4. Ends with a simple open question like 'How are you feeling today?'\n\nDo NOT mention diagnoses, medications, or specific clinical terms. Keep it warm and human."
}
]
}
},
"typeVersion": 1.4
},
{
"id": "e64de30c-ed06-4a95-bbfd-a001116eb594",
"name": "Telegram: Send Check-In to Patient",
"type": "n8n-nodes-base.telegram",
"position": [
2128,
160
],
"parameters": {
"text": "={{ $json.message.content }}",
"chatId": "={{ $json.patient_telegram_chat_id }}",
"additionalFields": {
"parse_mode": "Markdown"
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "35423a72-e6e6-4b18-9cd6-52d848d5bbd5",
"name": "Sheets: Mark Check-In Sent",
"type": "n8n-nodes-base.googleSheets",
"position": [
2464,
160
],
"parameters": {
"columns": {
"value": {
"session_id": "={{ $('Filter: Due for Check-In (24h passed)1').item.json.session_id }}",
"checkin_sent": "yes",
"checkin_sent_at": "={{ $('Schedule Trigger (Every Hour)').item.json.timestamp }}",
"checkin_message_sent": "={{ $('AI: Generate Personalised Check-In Message').item.json.message.content }}"
},
"schema": [
{
"id": "session_id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "session_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "patient_name",
"type": "string",
"display": true,
"required": false,
"displayName": "patient_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "patient_telegram_chat_id",
"type": "string",
"display": true,
"required": false,
"displayName": "patient_telegram_chat_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "therapist_name",
"type": "string",
"display": true,
"required": false,
"displayName": "therapist_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "therapist_slack_id",
"type": "string",
"display": true,
"required": false,
"displayName": "therapist_slack_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "session_datetime",
"type": "string",
"display": true,
"required": false,
"displayName": "session_datetime",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "session_duration_min",
"type": "string",
"display": true,
"required": false,
"displayName": "session_duration_min",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "primary_concern",
"type": "string",
"display": true,
"required": false,
"displayName": "primary_concern",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "treatment_goal",
"type": "string",
"display": true,
"required": false,
"displayName": "treatment_goal",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "session_notes",
"type": "string",
"display": true,
"required": false,
"displayName": "session_notes",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "session_status",
"type": "string",
"display": true,
"required": false,
"displayName": "session_status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "checkin_sent",
"type": "string",
"display": true,
"required": false,
"displayName": "checkin_sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "checkin_sent_at",
"type": "string",
"display": true,
"required": false,
"displayName": "checkin_sent_at",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "checkin_message_sent",
"type": "string",
"display": true,
"required": false,
"displayName": "checkin_message_sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "patient_reply",
"type": "string",
"display": true,
"required": false,
"displayName": "patient_reply",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "reply_received_at",
"type": "string",
"display": true,
"required": false,
"displayName": "reply_received_at",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "sentiment_score",
"type": "string",
"display": true,
"required": false,
"displayName": "sentiment_score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "sentiment_confidence",
"type": "string",
"display": true,
"required": false,
"displayName": "sentiment_confidence",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "wellness_status",
"type": "string",
"display": true,
"required": false,
"displayName": "wellness_status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"session_id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1222247293,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU/edit#gid=1222247293",
"cachedResultName": "Sessions"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU/edit?usp=drivesdk",
"cachedResultName": "Mental health checkin tracker"
}
},
"typeVersion": 4.2
},
{
"id": "bc4d9d84-7bae-4d83-9b12-058f7f7933ee",
"name": "Code: Parse Sentiment JSON",
"type": "n8n-nodes-base.code",
"position": [
2208,
768
],
"parameters": {
"jsCode": "const raw = $json.message.content;\nlet parsed;\ntry {\n parsed = JSON.parse(raw);\n} catch(e) {\n const match = raw.match(/\\{[\\s\\S]*\\}/);\n parsed = match ? JSON.parse(match[0]) : { sentiment: 'neutral', confidence: 0.5, risk_indicators: [], emotional_tone: 'unknown', recommended_action: 'monitor', summary: 'Could not parse response' };\n}\nconst sessionData = $('Sheets: Lookup Patient by Telegram ID').item.json;\nreturn {\n ...parsed,\n patient_name: sessionData.patient_name,\n therapist_name: sessionData.therapist_name,\n therapist_slack_id: sessionData.therapist_slack_id,\n session_id: sessionData.session_id,\n patient_reply: $('Telegram Trigger: Capture Patient Reply').item.json.message.text,\n session_datetime: sessionData.session_datetime\n};"
},
"typeVersion": 2
},
{
"id": "6bd15b85-520d-42d2-80ae-86bce9a6d670",
"name": "IF: At-Risk Detected?",
"type": "n8n-nodes-base.if",
"position": [
2544,
768
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "at-risk-check",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.sentiment }}",
"rightValue": "at-risk"
}
]
}
},
"typeVersion": 2
},
{
"id": "1d243917-c13e-4f83-b61d-27c238c9e85a",
"name": "Slack: Alert Therapist (Human-in-Loop)",
"type": "n8n-nodes-base.slack",
"position": [
2832,
640
],
"parameters": {
"text": "=\ud83d\udea8 *URGENT: At-Risk Patient Response Detected*\n\n*Patient:* {{ $json.patient_name }}\n*Session Date:* {{ $json.session_datetime }}\n*Sentiment:* {{ $json.sentiment.toUpperCase() }} ({{ Math.round($json.confidence * 100) }}% confidence)\n*Emotional Tone:* {{ $json.emotional_tone }}\n\n*Patient's Reply:*\n> {{ $json.patient_reply }}\n\n*Risk Indicators:* {{ $json.risk_indicators.join(', ') || 'See reply above' }}\n\n*AI Summary:* {{ $json.summary }}\n\n\u26a1 *Recommended Action: IMMEDIATE FOLLOW-UP*\nPlease reach out to {{ $json.patient_name }} directly as soon as possible.",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "YOUR_SLACK_CHANNEL_ID",
"cachedResultName": "therapist-alerts"
},
"otherOptions": {
"mrkdwn": true
},
"authentication": "oAuth2"
},
"typeVersion": 2.2
},
{
"id": "01a2d004-b4d9-4699-92b4-cf1b9da5ac13",
"name": "Sheets: Append to Wellness Log",
"type": "n8n-nodes-base.googleSheets",
"position": [
2848,
992
],
"parameters": {
"columns": {
"value": {
"log_id": "={{ $('Code: Parse Merge Output').item.json.session_id }}",
"sentiment": "={{ $('Code: Parse Sentiment JSON').item.json.sentiment }}",
"confidence": "={{ $('Code: Parse Sentiment JSON').item.json.confidence }}",
"session_id": "={{ $('Code: Parse Merge Output').item.json.session_id }}",
"patient_name": "={{ $('Code: Parse Merge Output').item.json.patient_name }}",
"log_timestamp": "={{ $('Code: Parse Merge Output').item.json.session_datetime }}",
"patient_reply": "={{ $('Code: Parse Sentiment JSON').item.json.patient_reply }}",
"emotional_tone": "={{ $('Code: Parse Sentiment JSON').item.json.emotional_tone }}",
"therapist_name": "={{ $('Code: Parse Merge Output').item.json.therapist_name }}",
"wellness_status": "Good"
},
"schema": [
{
"id": "log_id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "log_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "log_timestamp",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "log_timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "session_id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "session_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "patient_name",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "patient_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "therapist_name",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "therapist_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "sentiment",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "sentiment",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "confidence",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "confidence",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "emotional_tone",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "emotional_tone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "patient_reply",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "patient_reply",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ai_summary",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ai_summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "wellness_status",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "wellness_status",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"log_id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 855010652,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU/edit#gid=855010652",
"cachedResultName": "Wellness_Log"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU/edit?usp=drivesdk",
"cachedResultName": "Mental health checkin tracker"
}
},
"typeVersion": 4.2
},
{
"id": "d369ae69-4994-451d-806f-9b80f4f7ee4e",
"name": "Filter: Due for Check-In (24h passed)1",
"type": "n8n-nodes-base.filter",
"position": [
1408,
160
],
"parameters": {
"options": {
"looseTypeValidation": true
},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "checkin-sent-check",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ ($json.checkin_sent ?? 'No').toString().trim() }}",
"rightValue": "No"
},
{
"id": "session-datetime-exists",
"operator": {
"type": "string",
"operation": "notEmpty"
},
"leftValue": "={{ $json.session_datetime }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2
},
{
"id": "f89d90e3-57d4-4539-b598-abccfad118e8",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
1408,
768
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "69cb3757-8393-4b80-a220-bed09f2f0ba9",
"name": "Read Completed Sessions (Reply Branch)",
"type": "n8n-nodes-base.googleSheets",
"position": [
1136,
912
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1222247293,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU/edit#gid=1222247293",
"cachedResultName": "Sessions"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU/edit?usp=drivesdk",
"cachedResultName": "Mental health checkin tracker"
}
},
"typeVersion": 4.2
},
{
"id": "258210a6-ea6c-4644-8b44-b14e26f7bcf2",
"name": "AI: Sentiment Analysis on Reply",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
1872,
768
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "GPT-4O-MINI"
},
"options": {},
"messages": {
"values": [
{
"content": "=You are a clinical sentiment analysis assistant for a mental health practice. Analyze the following patient reply to a post-therapy check-in message and return ONLY a JSON object.\n\nPatient Name: {{ $json.patient_name }}\nOriginal Check-In Message: {{ $json.checkin_message_sent }}\nPatient's Reply: {{ $('Telegram Trigger: Capture Patient Reply').item.json.message.text }}\nPrimary Concern: {{ $json.primary_concern }}\n\nReturn ONLY this JSON structure (no markdown, no explanation):\n{\n \"sentiment\": \"positive\" | \"neutral\" | \"at-risk\",\n \"confidence\": 0.0-1.0,\n \"risk_indicators\": [\"list of concerning phrases if any\"],\n \"emotional_tone\": \"brief description\",\n \"recommended_action\": \"monitor\" | \"follow_up\" | \"immediate_escalation\",\n \"summary\": \"one sentence summary for therapist\"\n}"
}
]
}
},
"typeVersion": 1.4
},
{
"id": "311af8de-cfd5-4437-a463-6b4fed772914",
"name": "Sheets: Lookup Patient by Telegram ID",
"type": "n8n-nodes-base.googleSheets",
"position": [
1136,
560
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "={{ $json.message.from.id }}",
"lookupColumn": "telegram_chat_id"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 2084876190,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU/edit#gid=2084876190",
"cachedResultName": "Patients_Master"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ggOoUJFmRWUyLxuw7Ss-Qg0QJrXDLFpfgcpG0UlQxnU/edit?usp=drivesdk",
"cachedResultName": "Mental health checkin tracker"
}
},
"typeVersion": 4.2
},
{
"id": "2cf0c8df-eeff-4c4c-aedb-66e0187224b7",
"name": "Telegram Trigger: Capture Patient Reply",
"type": "n8n-nodes-base.telegramTrigger",
"position": [
800,
752
],
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"typeVersion": 1.1
},
{
"id": "00814374-eb72-407f-9008-a26baa25fcd9",
"name": "Code: Parse Merge Output",
"type": "n8n-nodes-base.code",
"position": [
1664,
768
],
"parameters": {
"jsCode": "const items = $input.all();\nconst telegramText = $('Telegram Trigger: Capture Patient Reply').item.json.message.text;\nconst telegramChatId = String($('Telegram Trigger: Capture Patient Reply').item.json.message.from.id);\n\nconst patientRecord = items.find(i => i.json.patient_id && !i.json.session_id)?.json;\nconst sessionItems = items.filter(i => i.json.session_id);\n\nif (!patientRecord) throw new Error('No patient record found in Merge output');\nif (sessionItems.length === 0) throw new Error('No session records found in Merge output');\n\nconst matched = sessionItems.filter(i =>\n String(i.json.patient_telegram_chat_id) === String(patientRecord.telegram_chat_id)\n);\n\nconst pool = matched.length > 0 ? matched : sessionItems;\n\nconst sent = pool.filter(i => (i.json.checkin_sent || '').toLowerCase() === 'yes');\nconst candidates = sent.length > 0 ? sent : pool;\n\ncandidates.sort((a, b) =>\n new Date(b.json.checkin_sent_at || 0) - new Date(a.json.checkin_sent_at || 0)\n);\n\nconst s = candidates[0].json;\n\nreturn [{ json: {\n session_id: s.session_id,\n patient_name: s.patient_name,\n patient_telegram_chat_id: s.patient_telegram_chat_id,\n therapist_name: s.therapist_name,\n therapist_slack_id: s.therapist_slack_id,\n session_datetime: s.session_datetime,\n primary_concern: s.primary_concern,\n treatment_goal: s.treatment_goal,\n session_notes: s.session_notes,\n session_status: s.session_status,\n checkin_sent: s.checkin_sent,\n checkin_sent_at: s.checkin_sent_at,\n checkin_message_sent: s.checkin_message_sent,\n patient_id: patientRecord.patient_id,\n diagnosis: patientRecord.diagnosis,\n assigned_therapist: patientRecord.assigned_therapist,\n telegram_message_text: telegramText,\n telegram_chat_id_live: telegramChatId\n}}];"
},
"typeVersion": 2
},
{
"id": "961d590b-8ace-40d4-8570-4d6ce77ddf8f",
"name": "Section: Trigger & Filter",
"type": "n8n-nodes-base.stickyNote",
"position": [
880,
-48
],
"parameters": {
"color": 7,
"width": 680,
"height": 408,
"content": "## \u23f1\ufe0f Trigger & Session Filter\n\nRuns every hour and reads all sessions from the Google Sheet. Only sessions where a check-in hasn't been sent yet (`checkin_sent = No`) are passed forward \u2014 preventing duplicate messages."
},
"typeVersion": 1
},
{
"id": "eb472f2a-254e-4af8-baa3-06b642f66a3e",
"name": "On Workflow Error",
"type": "n8n-nodes-base.errorTrigger",
"position": [
704,
1312
],
"parameters": {},
"typeVersion": 1
},
{
"id": "ae0a3154-8050-422b-9c5c-696a00f09e76",
"name": "Slack \u2013 Send Error Alert",
"type": "n8n-nodes-base.slack",
"position": [
960,
1312
],
"parameters": {
"text": "=error in the workflow",
"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": "bccf8ce3-d7c0-4cb1-b555-2428cedca408",
"name": "Section: Error Handler",
"type": "n8n-nodes-base.stickyNote",
"position": [
608,
1152
],
"parameters": {
"color": 7,
"width": 556,
"height": 368,
"content": "## \u26a0\ufe0f Error Handler\nCatches any failure in the workflow and posts a Slack alert with the error message, failing node name, and execution ID. Wire the error output of any critical node here to prevent silent failures going unnoticed."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "74e2880d-d940-4afa-a577-fb04d912cbe0",
"connections": {
"Merge": {
"main": [
[
{
"node": "Code: Parse Merge Output",
"type": "main",
"index": 0
}
]
]
},
"On Workflow Error": {
"main": [
[
{
"node": "Slack \u2013 Send Error Alert",
"type": "main",
"index": 0
}
]
]
},
"IF: At-Risk Detected?": {
"main": [
[
{
"node": "Slack: Alert Therapist (Human-in-Loop)",
"type": "main",
"index": 0
}
],
[
{
"node": "Sheets: Append to Wellness Log",
"type": "main",
"index": 0
}
]
]
},
"Read Completed Sessions": {
"main": [
[
{
"node": "Filter: Due for Check-In (24h passed)1",
"type": "main",
"index": 0
}
]
]
},
"Code: Parse Merge Output": {
"main": [
[
{
"node": "AI: Sentiment Analysis on Reply",
"type": "main",
"index": 0
}
]
]
},
"Code: Parse Sentiment JSON": {
"main": [
[
{
"node": "IF: At-Risk Detected?",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger (Every Hour)": {
"main": [
[
{
"node": "Read Completed Sessions",
"type": "main",
"index": 0
}
]
]
},
"AI: Sentiment Analysis on Reply": {
"main": [
[
{
"node": "Code: Parse Sentiment JSON",
"type": "main",
"index": 0
}
]
]
},
"Telegram: Send Check-In to Patient": {
"main": [
[
{
"node": "Sheets: Mark Check-In Sent",
"type": "main",
"index": 0
}
]
]
},
"Sheets: Lookup Patient by Telegram ID": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Filter: Due for Check-In (24h passed)1": {
"main": [
[
{
"node": "AI: Generate Personalised Check-In Message",
"type": "main",
"index": 0
}
]
]
},
"Read Completed Sessions (Reply Branch)": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"Telegram Trigger: Capture Patient Reply": {
"main": [
[
{
"node": "Sheets: Lookup Patient by Telegram ID",
"type": "main",
"index": 0
},
{
"node": "Read Completed Sessions (Reply Branch)",
"type": "main",
"index": 0
}
]
]
},
"AI: Generate Personalised Check-In Message": {
"main": [
[
{
"node": "Telegram: Send Check-In to Patient",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
slackOAuth2ApitelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow uses Google Sheets, OpenAI, Telegram, and Slack to send post-therapy check-in messages, analyze patient replies for sentiment and risk, alert therapists to at-risk responses, and log non-urgent replies for ongoing wellness tracking. Runs every hour on a schedule…
Source: https://n8n.io/workflows/16428/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow monitors your Gmail support inbox every minute, automatically sending each unread email to OpenAI for intelligent analysis. The AI evaluates sentiment (Positive/Neutral/Negative/Critical
Auto-create and publish AI social videos with Telegram, GPT-4 and Blotato. Uses httpRequest, stickyNote, telegramTrigger, telegram. Event-driven trigger; 42 nodes.
This workflow is designed for business analysts, market researchers, lead generation specialists, and sales teams who need to gather detailed business intelligence from Google Maps. It's particularly
This workflow runs daily, pulls birthdays from Google Contacts, generates personalized birthday copy with OpenAI, sends greetings via Gmail, WhatsApp Business Cloud, and Telegram when available, and p
YouTube to X Post- AlexK1919. Uses twitter, stickyNote, youTube, toolCalculator. Scheduled trigger; 28 nodes.