This workflow corresponds to n8n.io template #17416 — 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": "vw5o99SKHJVkNE4K",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "AI Compliance Validation & Human Escalation System",
"tags": [],
"nodes": [
{
"id": "42f84a4b-4efe-48fe-b81b-417c34c77afa",
"name": "\ud83d\udccc Overview \u2013 How This Workflow Works",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2272,
672
],
"parameters": {
"width": 932,
"height": 688,
"content": "## \ud83d\udd0d AI Compliance Auditor \u2013 Two-Pass Record Screening\n\n### How it works\nA daily schedule reads all records from the `ComplianceRecords` sheet and sends each one through a two-pass AI review. Pass 1 (GPT-4o-mini) screens against four compliance rules: plaintext PII, undocumented high-value transactions, misclassified data, and missing mandatory regulatory fields. Records with no violation are marked Compliant immediately. Flagged records go to Pass 2, where a second AI call determines whether the flag is a false positive, an auto-fixable formatting issue, or a genuine violation that needs a human. Auto-fixes are written back to the sheet; anything requiring human judgment is escalated to the compliance team via Telegram. All outcomes \u2014 compliant, false positive, auto-fixed, and escalated \u2014 are merged and appended to the `AuditLog` sheet for a full daily audit trail.\n\n### Setup steps\n1. Connect **OpenAI API** to both AI nodes.\n2. Connect **Google Sheets OAuth2** and create a sheet with two tabs: `ComplianceRecords` and `AuditLog`. Replace `YOUR_GOOGLE_SHEET_ID` in all Sheets nodes.\n3. Connect **Telegram Bot API** and replace `YOUR_COMPLIANCE_TEAM_CHAT_ID` in the escalation node.\n4. Connect **Slack OAuth2** and replace `YOUR_SLACK_CHANNEL_ID` in both Slack error alert nodes.\n5. Adjust the schedule trigger to your preferred audit frequency.\n6. Activate the schedule trigger."
},
"typeVersion": 1
},
{
"id": "bfc86c49-1f0e-4890-9047-ea9bc07dc607",
"name": "Section \u2013 AI Pass 1 Compliance Screening",
"type": "n8n-nodes-base.stickyNote",
"position": [
-496,
1424
],
"parameters": {
"color": 7,
"width": 968,
"height": 796,
"content": "## \ud83e\udd16 AI Pass 1 \u2013 Compliance Screening\nChecks each record against four rules: plaintext PII, undocumented transactions above 10,000, misclassified data fields, and missing mandatory regulatory fields. Returns a violation flag, category, confidence score, and reasoning. The error output routes AI failures to Slack."
},
"typeVersion": 1
},
{
"id": "8dcded6e-282f-4f66-9cc4-6011cd2ac5f8",
"name": "Section \u2013 Violation Gate",
"type": "n8n-nodes-base.stickyNote",
"position": [
560,
1088
],
"parameters": {
"color": 7,
"width": 808,
"height": 444,
"content": "## \u2705 Violation Gate\nClean records are marked Compliant and routed straight to the final merge. Flagged records continue to Pass 2 for deeper analysis."
},
"typeVersion": 1
},
{
"id": "102226ab-4518-42ad-baa4-40c846f4c2f5",
"name": "Section \u2013 AI Pass 2 Review & Resolution",
"type": "n8n-nodes-base.stickyNote",
"position": [
544,
1680
],
"parameters": {
"color": 7,
"width": 1760,
"height": 828,
"content": "## \ud83d\udd2c AI Pass 2 \u2013 Review & Resolution\nA second AI call decides: false positive (dismiss), auto-fixable (write corrected value back to the sheet), or escalation needed (notify the compliance team via Telegram). Financial approvals, legal determinations, and anything irreversible are never auto-fixed \u2014 always escalated."
},
"typeVersion": 1
},
{
"id": "a6b9b38d-5705-4758-a941-d0e58c331f19",
"name": "Section \u2013 Merge & Audit Log",
"type": "n8n-nodes-base.stickyNote",
"position": [
2368,
1136
],
"parameters": {
"color": 7,
"width": 864,
"height": 604,
"content": "## \ud83d\udccb Merge & Audit Log\nAll four outcome branches (Compliant, False Positive, Auto-Fixed, Escalated) merge here and are appended to the `AuditLog` sheet in a single pass, giving you a timestamped record of every decision made during the run."
},
"typeVersion": 1
},
{
"id": "c054e67c-9fad-45d7-80bd-a93091e467f7",
"name": "\ud83d\udd11 Credentials & Sheet Setup",
"type": "n8n-nodes-base.stickyNote",
"position": [
2480,
1936
],
"parameters": {
"color": 3,
"width": 464,
"height": 442,
"content": "## \ud83d\udd11 Credentials Required\n- **OpenAI API** \u2014 both AI nodes\n- **Google Sheets OAuth2** \u2014 ComplianceRecords + AuditLog tabs\n- **Telegram Bot API** \u2014 compliance team escalations\n- **Slack OAuth2** \u2014 AI error alerts on both AI nodes\n\nSheet columns (ComplianceRecords): `RecordID, RecordType, DataField, Value, Description, Department, Status`\nSheet columns (AuditLog): `Timestamp, RecordID, Status, Category, Details`"
},
"typeVersion": 1
},
{
"id": "040d3f4a-4251-453d-aab6-f1d8cc44f5db",
"name": "AI Compliance Check - Pass 1",
"type": "@n8n/n8n-nodes-langchain.openAi",
"onError": "continueErrorOutput",
"position": [
-384,
1696
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "GPT-4O-MINI"
},
"options": {
"temperature": 0.2
},
"messages": {
"values": [
{
"role": "system",
"content": "You are a compliance auditor AI. Check the given record against this rule set: 1) PII must not be stored in plaintext outside designated encrypted fields. 2) Financial transactions above 10,000 (in local currency) require a documented approval reference. 3) Data records must have a classification tag matching their actual content type. 4) Records must not be missing mandatory regulatory fields (e.g. tax ID, consent flag, KYC reference). Analyze the record and respond with ONLY a raw JSON object, no markdown, no extra text, in this exact shape: {\"violation_flagged\": boolean, \"category\": string, \"confidence\": number between 0 and 1, \"reasoning\": string}"
},
{
"content": "=Record ID: {{ $json.RecordID }}\nRecord Type: {{ $json.RecordType }}\nField: {{ $json.DataField }}\nValue: {{ $json.Value }}\nDescription: {{ $json.Description }}\nDepartment: {{ $json.Department }}"
}
]
}
},
"typeVersion": 1
},
{
"id": "48dde1a7-a264-4e9a-a055-a39d8e4f228f",
"name": "AI Verification & Auto-Fix - Pass 2",
"type": "@n8n/n8n-nodes-langchain.openAi",
"onError": "continueErrorOutput",
"position": [
656,
2048
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "GPT-4O-MINI"
},
"options": {
"temperature": 0.2
},
"messages": {
"values": [
{
"role": "system",
"content": "You are a senior compliance reviewer AI performing a second-pass review on a record already flagged by an initial screening. Your job: (1) Decide if this is a false positive given the full context. (2) If it is a genuine violation, decide if it is SAFELY auto-fixable without human sign-off - for example a misclassified data field, a formatting error, or a missing non-sensitive tag. (3) If auto-fixable, propose the exact corrected value. Never mark anything auto-fixable if it involves financial approval thresholds, legal or regulatory determinations, or anything irreversible - always escalate those instead. Respond with ONLY a raw JSON object, no markdown, no extra text, in this exact shape: {\"is_false_positive\": boolean, \"auto_fixable\": boolean, \"corrected_value\": string or null, \"escalation_reason\": string, \"summary\": string}"
},
{
"content": "=Record ID: {{ $json.RecordID }}\nRecord Type: {{ $json.RecordType }}\nField: {{ $json.DataField }}\nValue: {{ $json.Value }}\nDescription: {{ $json.Description }}\nDepartment: {{ $json.Department }}\n\nInitial flag category: {{ $json.category }}\nInitial flag reasoning: {{ $json.reasoning }}\nInitial confidence: {{ $json.confidence }}"
}
]
}
},
"typeVersion": 1
},
{
"id": "0d0f00a9-8944-4887-b8af-4667d5d6531a",
"name": "Audit Trigger (Schedule)",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-1024,
1696
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 24
}
]
}
},
"typeVersion": 1.2
},
{
"id": "0499d06b-517a-4f96-bf1b-fc2082f5f410",
"name": "Fetch Compliance Records",
"type": "n8n-nodes-base.googleSheets",
"position": [
-800,
1696
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "ComplianceRecords"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "f8a09c73-f661-46a7-a033-d6c32c9de761",
"name": "Parse Pass 1 Result",
"type": "n8n-nodes-base.code",
"position": [
48,
1680
],
"parameters": {
"jsCode": "const originalRecords = $('Fetch Compliance Records').all();\nconst aiResponses = $input.all();\nconst items = [];\n\nfor (let i = 0; i < aiResponses.length; i++) {\n const original = originalRecords[i] ? originalRecords[i].json : {};\n let raw = (aiResponses[i].json.message && aiResponses[i].json.message.content) || aiResponses[i].json.content || '';\n raw = String(raw).trim().replace(/^```json\\s*/i, '').replace(/^```\\s*/i, '').replace(/```$/, '').trim();\n\n let parsed;\n try {\n parsed = JSON.parse(raw);\n } catch (e) {\n parsed = {\n violation_flagged: true,\n category: 'parse_error',\n confidence: 0,\n reasoning: 'Could not parse AI response, escalating by default: ' + raw.slice(0, 200)\n };\n }\n\n items.push({\n json: {\n ...original,\n violation_flagged: parsed.violation_flagged === true,\n category: parsed.category || 'unknown',\n confidence: parsed.confidence !== undefined ? parsed.confidence : null,\n reasoning: parsed.reasoning || ''\n }\n });\n}\n\nreturn items;"
},
"typeVersion": 2
},
{
"id": "a561e0f6-5900-4d14-b9f3-6dc22545210f",
"name": "Violation Flagged?",
"type": "n8n-nodes-base.if",
"position": [
272,
1680
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-violation",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.violation_flagged }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2
},
{
"id": "994de343-178c-4835-ac43-b572df0b0dc2",
"name": "Mark Compliant",
"type": "n8n-nodes-base.set",
"position": [
928,
1280
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a1",
"name": "Status",
"type": "string",
"value": "Compliant"
},
{
"id": "a2",
"name": "Details",
"type": "string",
"value": "=No violation detected (confidence: {{ $json.confidence }})"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "c77eee55-42d2-42bf-8b68-5cad67a5824a",
"name": "Parse Pass 2 Result",
"type": "n8n-nodes-base.code",
"position": [
1040,
2016
],
"parameters": {
"jsCode": "const flaggedRecords = $('Parse Pass 1 Result').all();\nconst aiResponses = $input.all();\nconst items = [];\n\nfor (let i = 0; i < aiResponses.length; i++) {\n const original = flaggedRecords[i] ? flaggedRecords[i].json : {};\n let raw = (aiResponses[i].json.message && aiResponses[i].json.message.content) || aiResponses[i].json.content || '';\n raw = String(raw).trim().replace(/^```json\\s*/i, '').replace(/^```\\s*/i, '').replace(/```$/, '').trim();\n\n let parsed;\n try {\n parsed = JSON.parse(raw);\n } catch (e) {\n parsed = {\n is_false_positive: false,\n auto_fixable: false,\n corrected_value: null,\n escalation_reason: 'Could not parse pass 2 AI response, escalating by default: ' + raw.slice(0, 200),\n summary: 'Parse error on second pass review.'\n };\n }\n\n items.push({\n json: {\n ...original,\n is_false_positive: parsed.is_false_positive === true,\n auto_fixable: parsed.auto_fixable === true,\n corrected_value: parsed.corrected_value || null,\n escalation_reason: parsed.escalation_reason || '',\n summary: parsed.summary || ''\n }\n });\n}\n\nreturn items;"
},
"typeVersion": 2
},
{
"id": "24ae8872-2ce7-4f1e-a2c7-cd8c3d17260a",
"name": "False Positive?",
"type": "n8n-nodes-base.if",
"position": [
1248,
2016
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-fp",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.is_false_positive }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2
},
{
"id": "5428b270-9c06-4a99-915c-ab924ca9ccef",
"name": "Mark False Positive Resolved",
"type": "n8n-nodes-base.set",
"position": [
1472,
1872
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a1",
"name": "Status",
"type": "string",
"value": "False Positive - Resolved"
},
{
"id": "a2",
"name": "Details",
"type": "string",
"value": "={{ $json.summary }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b3b2ce6b-142b-447f-ac86-204476913828",
"name": "Auto-Fixable?",
"type": "n8n-nodes-base.if",
"position": [
1472,
2144
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-autofix",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.auto_fixable }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2
},
{
"id": "9834a45c-dd90-402f-9251-49ac2f28261f",
"name": "Apply Auto-Fix",
"type": "n8n-nodes-base.googleSheets",
"position": [
1696,
2048
],
"parameters": {
"columns": {
"value": {
"Value": "={{ $json.corrected_value }}",
"Status": "Auto-Fixed",
"RecordID": "={{ $json.RecordID }}",
"row_number": 0
},
"schema": [
{
"id": "RecordID",
"type": "string",
"display": true,
"required": false,
"displayName": "RecordID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "RecordType",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "RecordType",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "DataField",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "DataField",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Value",
"type": "string",
"display": true,
"required": false,
"displayName": "Value",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Description",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Description",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Department",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Department",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"RecordID"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "ComplianceRecords"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "dac13217-0d7d-4b70-a7e1-55125e7c78f0",
"name": "Prepare Auto-Fix Log",
"type": "n8n-nodes-base.set",
"position": [
1920,
2048
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a1",
"name": "Status",
"type": "string",
"value": "Auto-Fixed"
},
{
"id": "a2",
"name": "Details",
"type": "string",
"value": "=Corrected value applied: {{ $json.corrected_value }}. Summary: {{ $json.summary }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "a7cb62c6-0ef2-47cd-8dd4-e1fac7e07ecb",
"name": "Escalate to Compliance Team",
"type": "n8n-nodes-base.telegram",
"position": [
1696,
2256
],
"parameters": {
"text": "=\u26a0\ufe0f Compliance Escalation Needed\n\nRecord ID: {{ $json.RecordID }}\nCategory: {{ $json.category }}\nReasoning: {{ $json.reasoning }}\nWhy it couldn't be auto-resolved: {{ $json.escalation_reason }}\n\nPlease review manually.",
"chatId": "YOUR_COMPLIANCE_TEAM_CHAT_ID",
"additionalFields": {}
},
"typeVersion": 1.2
},
{
"id": "11c143e4-3323-443d-8759-1ea96077de95",
"name": "Prepare Escalation Log",
"type": "n8n-nodes-base.set",
"position": [
1920,
2256
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a1",
"name": "Status",
"type": "string",
"value": "Escalated to Human"
},
{
"id": "a2",
"name": "Details",
"type": "string",
"value": "={{ $json.escalation_reason }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "f2789ebb-bb2e-4345-aa75-8b83a3a718f5",
"name": "Combine Results",
"type": "n8n-nodes-base.merge",
"position": [
2528,
1392
],
"parameters": {
"numberInputs": 4
},
"typeVersion": 3.1
},
{
"id": "181b3e1c-82d5-4c3c-badd-b594185ed940",
"name": "Append to Audit Log",
"type": "n8n-nodes-base.googleSheets",
"position": [
2848,
1424
],
"parameters": {
"columns": {
"value": {
"Status": "={{ $json.Status }}",
"Details": "={{ $json.Details }}",
"Category": "={{ $json.category }}",
"RecordID": "={{ $json.RecordID }}",
"Timestamp": "={{ $now.toISO() }}"
},
"schema": [
{
"id": "Timestamp",
"type": "string",
"display": true,
"required": false,
"displayName": "Timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "RecordID",
"type": "string",
"display": true,
"required": false,
"displayName": "RecordID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Category",
"type": "string",
"display": true,
"required": false,
"displayName": "Category",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Details",
"type": "string",
"display": true,
"required": false,
"displayName": "Details",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "AuditLog"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "542f83d6-3d86-4855-ad8d-885fb96d3e2c",
"name": "Slack \u2014 Send Workflow Error Alert",
"type": "n8n-nodes-base.slack",
"position": [
64,
1920
],
"parameters": {
"text": "=\u26a0\ufe0f AI Compliance Check - Pass 1 failed\n\n*Workflow:* {{ $workflow.name }}\n*Failed Node:* {{ $execution.lastNodeExecuted }}\n*Time:* {{ $now.format('MMM D, YYYY \u2013 HH:mm') }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "YOUR_SLACK_CHANNEL_ID",
"cachedResultName": "your-alerts-channel"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"typeVersion": 2.3
},
{
"id": "af74f159-71f0-4c4f-accb-0895edb799ee",
"name": "Slack \u2014 Send Pass 2 Error Alert",
"type": "n8n-nodes-base.slack",
"position": [
1040,
2208
],
"parameters": {
"text": "=\u26a0\ufe0f AI Verification - Pass 2 failed\n\n*Workflow:* {{ $workflow.name }}\n*Failed Node:* {{ $execution.lastNodeExecuted }}\n*Time:* {{ $now.format('MMM D, YYYY \u2013 HH:mm') }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "YOUR_SLACK_CHANNEL_ID",
"cachedResultName": "your-alerts-channel"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"typeVersion": 2.3
},
{
"id": "027fd6fc-e079-4872-8205-2b9086d9ef0e",
"name": "Section \u2013 Error Handling",
"type": "n8n-nodes-base.stickyNote",
"position": [
-848,
2560
],
"parameters": {
"color": 7,
"width": 748,
"height": 488,
"content": "## \u26a0\ufe0f Error Handling\nThree Slack alerts catch failures: a global error trigger covers the whole workflow, and the two AI nodes each have a dedicated error output wired to Slack. Update the channel ID and improve the alert message with context before going live."
},
"typeVersion": 1
},
{
"id": "0c7d17ad-ccbb-42a5-b736-2ed6d8085ff9",
"name": "On Workflow Error",
"type": "n8n-nodes-base.errorTrigger",
"position": [
-688,
2800
],
"parameters": {},
"typeVersion": 1
},
{
"id": "0c221e50-1332-40eb-bc21-eaefb67a4e45",
"name": "Slack \u2013 Post Workflow Error Alert",
"type": "n8n-nodes-base.slack",
"position": [
-416,
2800
],
"parameters": {
"text": "=\u26a0\ufe0f *DentalOS Workflow Error*\n\n*Workflow:* {{ $workflow.name }}\n*Failed Node:* {{ $execution.lastNodeExecuted }}\n*Time:* {{ $now.format('MMM D, YYYY \u2013 HH:mm') }}\n*Execution ID:* {{ $execution.id }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "YOUR_SLACK_CHANNEL_ID",
"cachedResultName": "your-alerts-channel"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"typeVersion": 2.3
},
{
"id": "8bc3a747-2c22-403d-a427-50f139b0bc5e",
"name": "Section \u2013 Trigger & Data Fetch",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1152,
1440
],
"parameters": {
"color": 7,
"width": 560,
"height": 572,
"content": "## \u23f0 Trigger & Data Fetch\nRuns on a daily schedule and reads all rows from the `ComplianceRecords` sheet. Each row is a separate record that flows independently through the rest of the pipeline."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "5559d23e-49f3-49c6-aaf7-d356d37556ab",
"nodeGroups": [],
"connections": {
"Auto-Fixable?": {
"main": [
[
{
"node": "Apply Auto-Fix",
"type": "main",
"index": 0
}
],
[
{
"node": "Escalate to Compliance Team",
"type": "main",
"index": 0
}
]
]
},
"Apply Auto-Fix": {
"main": [
[
{
"node": "Prepare Auto-Fix Log",
"type": "main",
"index": 0
}
]
]
},
"Mark Compliant": {
"main": [
[
{
"node": "Combine Results",
"type": "main",
"index": 0
}
]
]
},
"Combine Results": {
"main": [
[
{
"node": "Append to Audit Log",
"type": "main",
"index": 0
}
]
]
},
"False Positive?": {
"main": [
[
{
"node": "Mark False Positive Resolved",
"type": "main",
"index": 0
}
],
[
{
"node": "Auto-Fixable?",
"type": "main",
"index": 0
}
]
]
},
"On Workflow Error": {
"main": [
[
{
"node": "Slack \u2013 Post Workflow Error Alert",
"type": "main",
"index": 0
}
]
]
},
"Violation Flagged?": {
"main": [
[
{
"node": "AI Verification & Auto-Fix - Pass 2",
"type": "main",
"index": 0
}
],
[
{
"node": "Mark Compliant",
"type": "main",
"index": 0
}
]
]
},
"Parse Pass 1 Result": {
"main": [
[
{
"node": "Violation Flagged?",
"type": "main",
"index": 0
}
]
]
},
"Parse Pass 2 Result": {
"main": [
[
{
"node": "False Positive?",
"type": "main",
"index": 0
}
]
]
},
"Prepare Auto-Fix Log": {
"main": [
[
{
"node": "Combine Results",
"type": "main",
"index": 2
}
]
]
},
"Prepare Escalation Log": {
"main": [
[
{
"node": "Combine Results",
"type": "main",
"index": 3
}
]
]
},
"Audit Trigger (Schedule)": {
"main": [
[
{
"node": "Fetch Compliance Records",
"type": "main",
"index": 0
}
]
]
},
"Fetch Compliance Records": {
"main": [
[
{
"node": "AI Compliance Check - Pass 1",
"type": "main",
"index": 0
}
]
]
},
"Escalate to Compliance Team": {
"main": [
[
{
"node": "Prepare Escalation Log",
"type": "main",
"index": 0
}
]
]
},
"AI Compliance Check - Pass 1": {
"main": [
[
{
"node": "Parse Pass 1 Result",
"type": "main",
"index": 0
}
],
[
{
"node": "Slack \u2014 Send Workflow Error Alert",
"type": "main",
"index": 0
}
]
]
},
"Mark False Positive Resolved": {
"main": [
[
{
"node": "Combine Results",
"type": "main",
"index": 1
}
]
]
},
"Slack \u2014 Send Pass 2 Error Alert": {
"main": [
[
{
"node": "Violation Flagged?",
"type": "main",
"index": 0
}
]
]
},
"AI Verification & Auto-Fix - Pass 2": {
"main": [
[
{
"node": "Parse Pass 2 Result",
"type": "main",
"index": 0
}
],
[
{
"node": "Slack \u2014 Send Pass 2 Error Alert",
"type": "main",
"index": 0
}
]
]
},
"Slack \u2014 Send Workflow Error Alert": {
"main": [
[
{
"node": "Fetch Compliance Records",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow runs daily to audit rows in a Google Sheets ComplianceRecords tab using two OpenAI checks, automatically marking compliant items, fixing safe issues, and escalating unresolved violations to Telegram, while logging every outcome to an AuditLog sheet and posting…
Source: https://n8n.io/workflows/17416/ — 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 new hires in Google Sheets, downloads onboarding documents from Google Drive, uses OpenAI (gpt-4o-mini) to verify each file and determine overall compliance, then notifies HR vi
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
This workflow handles customer order complaints submitted via Telegram by looking up order details in Google Sheets, using OpenAI to classify message sentiment, and routing each case to auto-approval,
This workflow handles COD order confirmation and abandoned-cart recovery by combining webhooks, Google Sheets logging, OpenAI message generation, and Telegram messaging with inline buttons, plus Slack
This workflow runs a Telegram restaurant ordering flow that uses OpenAI to parse orders and suggest an upsell, sends a Razorpay payment link, confirms paid orders via a Razorpay webhook, logs orders a