This workflow corresponds to n8n.io template #18093 — we link there as the canonical source.
This workflow follows the Agent → 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": "DJ6SDGB0vM8Mtick",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Smart Electricity Bill Advisor",
"tags": [],
"nodes": [
{
"id": "6eba27dc-5e4d-4302-b83c-6d1168219b83",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
7216,
2640
],
"parameters": {
"width": 480,
"height": 896,
"content": "## Smart Electricity Bill Advisor\n\n### How it works\n\nThis workflow receives or periodically rechecks electricity bill submissions, enriches them with account context, and uses AI to extract and validate bill details. Valid bills are compared against historical usage, analyzed for anomalies, and turned into a customer advisory report. Depending on severity, it either logs and returns the report or initiates an escalation path with delayed alerting and audit logging.\n\n### Setup steps\n\n- Configure the webhook URL and payload fields for new bill submissions, including account ID, customer details, billing period, and bill content or reference.\n- Set the monthly schedule trigger to the desired recheck cadence.\n- Add OpenAI credentials for the AI agent nodes and confirm the prompts return structured extraction and advisory outputs.\n- Configure Google Sheets API credentials and spreadsheet/range values for historical bill lookup and report logging.\n- Set up SendGrid or equivalent API credentials for the escalation alert HTTP request.\n- Review wait durations and webhook response behavior so they match the expected user experience for normal, invalid, and escalated bills.\n\n### Customization\n\nYou can adjust validation rules, anomaly thresholds, AI prompts, escalation severity criteria, wait durations, email templates, and Google Sheets ranges to match local utility policies or customer communication standards."
},
"typeVersion": 1
},
{
"id": "50881dc0-a2cb-4792-a6f7-b986c9bdce33",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
8016,
2848
],
"parameters": {
"color": 7,
"width": 416,
"height": 528,
"content": "## Receive bill requests\n\nEntry cluster that accepts new bill submissions through a webhook or scheduled monthly recheck, then normalizes the basic account and billing context for downstream processing."
},
"typeVersion": 1
},
{
"id": "27845031-1acb-4c0d-9a73-51b50047e23e",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
8464,
2960
],
"parameters": {
"color": 7,
"width": 768,
"height": 544,
"content": "## Extract bill data\n\nUses the AI agent and nearby OpenAI chat model to extract and validate structured bill data, waits for completion, then parses the AI response into usable workflow fields."
},
"typeVersion": 1
},
{
"id": "1de90c9d-dd65-4d79-8069-58137c337d4a",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
9264,
2960
],
"parameters": {
"color": 7,
"width": 416,
"height": 464,
"content": "## Validate bill outcome\n\nBranches based on whether the parsed bill data is valid and immediately returns an invalid-data webhook response for failed validation."
},
"typeVersion": 1
},
{
"id": "9a1406bd-b367-4ae2-b557-0c79e95d05b0",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
9440,
2608
],
"parameters": {
"color": 7,
"width": 416,
"height": 320,
"content": "## Fetch usage history\n\nRetrieves historical bill records from Google Sheets via HTTP and runs custom analysis to detect abnormal consumption patterns."
},
"typeVersion": 1
},
{
"id": "7f90bb86-c349-4f8d-8f04-f328be4b5775",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
8464,
1984
],
"parameters": {
"color": 7,
"width": 1952,
"height": 592,
"content": "## Generate advisory report\n\nGenerates an AI-written advisory report from the validated bill and anomaly analysis, then formats the report and routing payloads for the next decision point."
},
"typeVersion": 1
},
{
"id": "2d3bedde-08ba-42ca-bb44-e66795578b08",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
10384,
2704
],
"parameters": {
"color": 7,
"width": 544,
"height": 480,
"content": "## Route severity decision\n\nDetermines whether the advisory requires high-severity escalation and sends an immediate pending-escalation webhook response when escalation is needed."
},
"typeVersion": 1
},
{
"id": "e03336c5-97b9-4c15-a9c0-95aa6b40560e",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
10960,
2928
],
"parameters": {
"color": 7,
"width": 768,
"height": 320,
"content": "## Send escalation alert\n\nHandles the high-severity escalation branch by waiting through a cooling-off period, sending an alert email through SendGrid, and logging the escalated report to Google Sheets."
},
"typeVersion": 1
},
{
"id": "0a594c57-d5a6-471a-8d07-fda9d61b35dd",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
10640,
3280
],
"parameters": {
"color": 7,
"width": 816,
"height": 304,
"content": "## Log reviewed report\n\nHandles the non-escalated reviewed-report path by logging the completed report, waiting for the result, and returning the final report-ready webhook response."
},
"typeVersion": 1
},
{
"id": "87d8f92f-0641-4ead-b0ea-933f6d517a55",
"name": "When New Bill Submitted",
"type": "n8n-nodes-base.webhook",
"position": [
8064,
3024
],
"parameters": {
"path": "electricity-bill-report",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 1.1
},
{
"id": "98a36c4b-5bfd-4df1-8b90-966be5b78f6e",
"name": "Every Month Bill Recheck",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
8064,
3216
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 6 1 * *"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "169d7ee6-2c65-42ab-8607-a8b0b9d2ccf0",
"name": "Set Bill Context Data",
"type": "n8n-nodes-base.set",
"position": [
8288,
3120
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"name": "accountId",
"type": "string",
"value": "={{ $json.accountId || $json.body?.accountId || '' }}"
},
{
"name": "customerName",
"type": "string",
"value": "={{ $json.customerName || $json.body?.customerName || '' }}"
},
{
"name": "customerEmail",
"type": "string",
"value": "={{ $json.customerEmail || $json.body?.customerEmail || '' }}"
},
{
"name": "billingPeriod",
"type": "string",
"value": "={{ $json.billingPeriod || $json.body?.billingPeriod || '' }}"
},
{
"name": "meterReading",
"type": "string",
"value": "={{ $json.meterReading || $json.body?.meterReading || '' }}"
},
{
"name": "priorMeterReading",
"type": "string",
"value": "={{ $json.priorMeterReading || $json.body?.priorMeterReading || '' }}"
},
{
"name": "unitsConsumed",
"type": "string",
"value": "={{ $json.unitsConsumed || $json.body?.unitsConsumed || '' }}"
},
{
"name": "tariffCategory",
"type": "string",
"value": "={{ $json.tariffCategory || $json.body?.tariffCategory || '' }}"
},
{
"name": "billAmount",
"type": "string",
"value": "={{ $json.billAmount || $json.body?.billAmount || '' }}"
},
{
"name": "billId",
"type": "string",
"value": "={{ $json.billId || 'BILL-' + Date.now().toString() }}"
},
{
"name": "requestTimestamp",
"type": "string",
"value": "={{ new Date().toISOString() }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "3a1fc4ea-f68c-4887-9bd3-ec3376d08a12",
"name": "Bill Data Validator Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
8560,
3120
],
"parameters": {
"text": "=You are an intake assistant for a smart electricity bill advisory system. Read the raw bill submission below and return ONLY a JSON object (no markdown, no commentary) with these fields:\n\n- tariffCategoryNormalized (string, e.g. \"Domestic\", \"Commercial\", \"Industrial\")\n- ratePerUnit (number, calculate as billAmount / unitsConsumed if not explicitly derivable, else null)\n- billingMonth (string, MM)\n- billingYear (string, YYYY)\n- isValid (boolean, true only if accountId, unitsConsumed, billAmount, billingPeriod, and customerEmail are all present and the numeric fields are valid numbers)\n- missingFields (array of strings, names of any required fields that are missing or unusable)\n\nRaw bill submission:\nAccount ID: {{ $json.accountId }}\nCustomer Name: {{ $json.customerName }}\nCustomer Email: {{ $json.customerEmail }}\nBilling Period: {{ $json.billingPeriod }}\nMeter Reading: {{ $json.meterReading }}\nPrior Meter Reading: {{ $json.priorMeterReading }}\nUnits Consumed: {{ $json.unitsConsumed }}\nTariff Category: {{ $json.tariffCategory }}\nBill Amount: {{ $json.billAmount }}",
"options": {},
"promptType": "define"
},
"typeVersion": 1.6
},
{
"id": "caeba6b1-da8b-4a47-a44f-be3a5a245b57",
"name": "OpenAI GPT-4.1 Mini",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
8608,
2432
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "e87a67b2-0a1c-441e-ba55-f2acae7db1df",
"name": "Wait for Extraction Completion",
"type": "n8n-nodes-base.wait",
"position": [
8864,
3120
],
"parameters": {},
"typeVersion": 1.1
},
{
"id": "287d4ed5-c964-41c4-80d2-b1fb6f96ac66",
"name": "Parse Bill Validation",
"type": "n8n-nodes-base.code",
"position": [
9088,
3120
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Safely parse the AI's structured validation output and merge with the original bill context\nconst item = $input.item.json;\nconst raw = item.output || item.text || item.response || '{}';\n\nlet parsed = {};\ntry {\n const cleaned = String(raw).replace(/```json|```/g, '').trim();\n parsed = JSON.parse(cleaned);\n} catch (e) {\n parsed = { isValid: false, missingFields: ['unparseable_ai_response'] };\n}\n\nconst original = $('Set Bill Context Data').item.json;\n\nreturn {\n json: {\n ...original,\n tariffCategoryNormalized: parsed.tariffCategoryNormalized || original.tariffCategory,\n ratePerUnit: parsed.ratePerUnit || null,\n billingMonth: parsed.billingMonth || (original.billingPeriod || '').slice(5, 7),\n billingYear: parsed.billingYear || (original.billingPeriod || '').slice(0, 4),\n isValid: !!parsed.isValid && !!original.customerEmail && !!original.accountId,\n missingFields: parsed.missingFields || []\n }\n};"
},
"typeVersion": 2
},
{
"id": "34edc817-ccf5-49db-99c8-8c95a15ff5c5",
"name": "Check Bill Data Validity",
"type": "n8n-nodes-base.if",
"position": [
9312,
3120
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"operator": {
"type": "boolean",
"operation": "true"
},
"leftValue": "={{ $json.isValid }}"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "b12104d5-3278-4c9c-9415-7ad12d4a9551",
"name": "Reply Invalid Bill Data",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
9536,
3264
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: false, status: 'invalid', billId: $json.billId, missingFields: $json.missingFields }) }}"
},
"typeVersion": 1.1
},
{
"id": "dce482fa-ac8d-453d-a676-e14b89fdff6b",
"name": "Fetch Historical Bills",
"type": "n8n-nodes-base.httpRequest",
"position": [
9488,
2768
],
"parameters": {
"url": "https://sheets.googleapis.com/v4/spreadsheets/YOUR_SHEET_ID/values/BillsLog!A2:P5000",
"options": {},
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleSheetsOAuth2Api"
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "e5abeb27-5fc2-4cb4-b090-436aafd3d8ea",
"name": "Analyze Consumption Anomaly",
"type": "n8n-nodes-base.code",
"position": [
9712,
2768
],
"parameters": {
"mode": "runOnceForEachItem",
"language": "python",
"pythonCode": "# Parse historical bill rows for this account and compute a weighted anomaly score\nimport statistics\n\nitem = _input.item['json']\nrows = item.get('values', [])\naccount_id = item.get('accountId', '')\ncurrent_period = item.get('billingPeriod', '')\ncurrent_units = float(item.get('unitsConsumed') or 0)\ncurrent_month = (current_period or '')[5:7]\n\nhistory = []\nfor row in rows:\n if len(row) < 13:\n continue\n if row[3] != account_id:\n continue\n if row[6] == current_period:\n continue\n try:\n history.append({\n 'billingPeriod': row[6],\n 'unitsConsumed': float(row[9] or 0),\n 'billAmount': float(row[12] or 0),\n 'tariffCategory': row[10] or ''\n })\n except (ValueError, IndexError):\n continue\n\nhistory.sort(key=lambda h: h['billingPeriod'])\nrecent = history[-12:]\n\nif len(recent) < 2:\n return {**item, 'historyCount': len(recent), 'anomalyScore': 0, 'severity': 'Insufficient History', 'isEscalationRequired': False}\n\nunits_list = [h['unitsConsumed'] for h in recent]\navg_units = statistics.mean(units_list)\nstd_units = statistics.pstdev(units_list) if len(units_list) > 1 else 0\n\nz_score = (current_units - avg_units) / std_units if std_units > 0 else 0\npercent_increase = ((current_units - avg_units) / avg_units * 100) if avg_units > 0 else 0\n\nseasonal = next((h for h in reversed(recent) if h['billingPeriod'][5:7] == current_month), None)\nseasonal_increase = 0\nif seasonal and seasonal['unitsConsumed'] > 0:\n seasonal_increase = (current_units - seasonal['unitsConsumed']) / seasonal['unitsConsumed'] * 100\n\ncategories = [h['tariffCategory'] for h in recent if h['tariffCategory']]\ncommon_category = max(set(categories), key=categories.count) if categories else ''\ncurrent_category = item.get('tariffCategoryNormalized', '')\ntariff_slab_jump = bool(common_category and current_category and common_category != current_category)\n\nn = len(units_list)\nif n >= 3:\n x_mean = (n - 1) / 2\n y_mean = avg_units\n numerator = sum((i - x_mean) * (u - y_mean) for i, u in enumerate(units_list))\n denominator = sum((i - x_mean) ** 2 for i in range(n))\n trend_slope = numerator / denominator if denominator else 0\nelse:\n trend_slope = 0\n\nconsumption_component = min(abs(z_score) * 20, 40)\nif seasonal:\n seasonal_component = min(max(seasonal_increase, 0) / 100 * 25, 25)\nelse:\n seasonal_component = min(max(percent_increase, 0) / 100 * 25, 25)\ntariff_component = 20 if tariff_slab_jump else 0\ntrend_component = min(max(trend_slope, 0) * 3, 15)\n\nanomaly_score = round(consumption_component + seasonal_component + tariff_component + trend_component, 2)\n\nif anomaly_score >= 70:\n severity = 'High'\nelif anomaly_score >= 40:\n severity = 'Moderate'\nelse:\n severity = 'Normal'\n\nreturn {\n **item,\n 'historyCount': len(recent),\n 'avgUnits': round(avg_units, 2),\n 'stdDevUnits': round(std_units, 2),\n 'zScore': round(z_score, 2),\n 'percentIncreaseVsAvg': round(percent_increase, 2),\n 'seasonalIncreasePercent': round(seasonal_increase, 2),\n 'tariffSlabJump': tariff_slab_jump,\n 'trendSlope': round(trend_slope, 3),\n 'anomalyScore': anomaly_score,\n 'severity': severity,\n 'isEscalationRequired': severity == 'High'\n}"
},
"typeVersion": 2
},
{
"id": "a494fa41-f8c3-425e-97aa-b6c6761fb7b5",
"name": "Advisory Report Generator Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
9968,
2096
],
"parameters": {
"text": "=You are a smart electricity bill advisor. Based on the anomaly analysis below, write a clear, helpful advisory report (under 180 words) for the customer.\n\nBill ID: {{ $json.billId }}\nAccount: {{ $json.accountId }}\nBilling Period: {{ $json.billingPeriod }}\nUnits Consumed: {{ $json.unitsConsumed }} (12-month average: {{ $json.avgUnits }})\nPercent Increase vs Average: {{ $json.percentIncreaseVsAvg }}%\nSeasonal Increase (same month last year): {{ $json.seasonalIncreasePercent }}%\nTariff Slab Change Detected: {{ $json.tariffSlabJump }}\nAnomaly Score: {{ $json.anomalyScore }}/100\nSeverity: {{ $json.severity }}\n\nExplain in plain language whether this bill looks unusual, the most likely causes (e.g. seasonal appliance use, tariff slab change, possible meter fault, increased occupancy), and 2-3 concrete money-saving or next-step recommendations. If severity is High, recommend requesting a meter inspection. Do NOT include disclaimers about being an AI.",
"options": {},
"promptType": "define"
},
"typeVersion": 1.6
},
{
"id": "fb88cbea-aa8c-4136-9dea-e39e453ba67e",
"name": "Format Advisory and Route",
"type": "n8n-nodes-base.code",
"position": [
10272,
2096
],
"parameters": {
"jsCode": "// Parse the AI advisory output and build the final report + escalation payloads\nconst item = $input.first().json;\nconst advisoryText = item.output || item.response || item.text ||\n `We reviewed your latest bill (${item.billId}) and did not detect a significant anomaly in your consumption pattern.`;\n\nconst severity = item.severity || 'Normal';\nconst isEscalationRequired = !!item.isEscalationRequired;\n\nconst emailSubject = `Unusual Consumption Alert \u2014 Account ${item.accountId} (Bill ${item.billId})`;\nconst emailBody = advisoryText;\n\nreturn [{\n json: {\n ...item,\n advisoryText,\n emailSubject,\n emailBody,\n logDate: new Date().toISOString().split('T')[0],\n logTimestamp: new Date().toISOString(),\n status: isEscalationRequired ? 'Escalated' : (severity === 'Moderate' ? 'Reviewed - Moderate' : 'Reviewed - Normal')\n }\n}];"
},
"typeVersion": 2
},
{
"id": "cd1e6eb3-b542-4b47-b3bd-477c4a04fff6",
"name": "Check Escalation Need",
"type": "n8n-nodes-base.if",
"position": [
10432,
3024
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"operator": {
"type": "boolean",
"operation": "true"
},
"leftValue": "={{ $json.isEscalationRequired }}"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "f82f76bd-abf6-4d4d-a095-897fed90d817",
"name": "Reply Escalation Pending",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
10784,
2864
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: true, status: 'escalation_pending', billId: $json.billId, anomalyScore: $json.anomalyScore, severity: $json.severity, message: 'A significant consumption anomaly was detected. Your case has been queued for review and you will receive a follow-up.' }) }}"
},
"typeVersion": 1.1
},
{
"id": "76c1d641-e737-40cc-be81-b5d1c6be2671",
"name": "Wait 24 Hours Before Alert",
"type": "n8n-nodes-base.wait",
"position": [
11008,
3088
],
"parameters": {
"unit": "hours",
"amount": 24
},
"typeVersion": 1.1
},
{
"id": "6031f06c-dbba-41fa-8f33-3fcbb202077b",
"name": "Send Escalation Alert Email",
"type": "n8n-nodes-base.httpRequest",
"position": [
11360,
3088
],
"parameters": {
"url": "https://api.sendgrid.com/v3/mail/send",
"method": "POST",
"options": {},
"sendBody": true,
"authentication": "predefinedCredentialType",
"bodyParameters": {
"parameters": [
{}
]
},
"nodeCredentialType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "b6df95de-4e38-4cb8-bff9-bc20ce381be5",
"name": "Log Escalated Report in Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
11584,
3088
],
"parameters": {
"columns": {
"value": {},
"mappingMode": "autoMapInputData"
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "BillsLog"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_SHEET_ID"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5,
"continueOnFail": true
},
{
"id": "432e80f5-3def-4c16-ad62-eb2d459fc036",
"name": "Log Reviewed Report in Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
10688,
3408
],
"parameters": {
"columns": {
"value": {},
"mappingMode": "autoMapInputData"
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "BillsLog"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_SHEET_ID"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5,
"continueOnFail": true
},
{
"id": "8a95cb1c-1090-4809-b2c1-07b57f09e2e0",
"name": "Reply Report Ready",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
11312,
3408
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: true, status: 'reviewed', billId: $json.billId, severity: $json.severity, anomalyScore: $json.anomalyScore, advisoryReport: $json.advisoryText }) }}"
},
"typeVersion": 1.1
},
{
"id": "9a9e9f8c-58fc-4fbe-8137-6f482e0e8fb4",
"name": "Wait for Processing Result",
"type": "n8n-nodes-base.wait",
"position": [
10992,
3408
],
"parameters": {},
"typeVersion": 1.1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "87f9865a-4d98-4663-b05d-3e5f1731815b",
"nodeGroups": [],
"connections": {
"OpenAI GPT-4.1 Mini": {
"ai_languageModel": [
[
{
"node": "Bill Data Validator Agent",
"type": "ai_languageModel",
"index": 0
},
{
"node": "Advisory Report Generator Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Check Escalation Need": {
"main": [
[
{
"node": "Reply Escalation Pending",
"type": "main",
"index": 0
},
{
"node": "Wait 24 Hours Before Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "Log Reviewed Report in Sheets",
"type": "main",
"index": 0
}
]
]
},
"Parse Bill Validation": {
"main": [
[
{
"node": "Check Bill Data Validity",
"type": "main",
"index": 0
}
]
]
},
"Set Bill Context Data": {
"main": [
[
{
"node": "Bill Data Validator Agent",
"type": "main",
"index": 0
}
]
]
},
"Fetch Historical Bills": {
"main": [
[
{
"node": "Analyze Consumption Anomaly",
"type": "main",
"index": 0
}
]
]
},
"When New Bill Submitted": {
"main": [
[
{
"node": "Set Bill Context Data",
"type": "main",
"index": 0
}
]
]
},
"Check Bill Data Validity": {
"main": [
[
{
"node": "Fetch Historical Bills",
"type": "main",
"index": 0
}
],
[
{
"node": "Reply Invalid Bill Data",
"type": "main",
"index": 0
}
]
]
},
"Every Month Bill Recheck": {
"main": [
[
{
"node": "Set Bill Context Data",
"type": "main",
"index": 0
}
]
]
},
"Bill Data Validator Agent": {
"main": [
[
{
"node": "Wait for Extraction Completion",
"type": "main",
"index": 0
}
]
]
},
"Format Advisory and Route": {
"main": [
[
{
"node": "Check Escalation Need",
"type": "main",
"index": 0
}
]
]
},
"Wait 24 Hours Before Alert": {
"main": [
[
{
"node": "Send Escalation Alert Email",
"type": "main",
"index": 0
}
]
]
},
"Wait for Processing Result": {
"main": [
[
{
"node": "Reply Report Ready",
"type": "main",
"index": 0
}
]
]
},
"Analyze Consumption Anomaly": {
"main": [
[
{
"node": "Advisory Report Generator Agent",
"type": "main",
"index": 0
}
]
]
},
"Send Escalation Alert Email": {
"main": [
[
{
"node": "Log Escalated Report in Sheets",
"type": "main",
"index": 0
}
]
]
},
"Log Reviewed Report in Sheets": {
"main": [
[
{
"node": "Wait for Processing Result",
"type": "main",
"index": 0
}
]
]
},
"Wait for Extraction Completion": {
"main": [
[
{
"node": "Parse Bill Validation",
"type": "main",
"index": 0
}
]
]
},
"Advisory Report Generator Agent": {
"main": [
[
{
"node": "Format Advisory and Route",
"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.
googleSheetsOAuth2ApihttpHeaderAuthopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow accepts electricity bill submissions via webhook or a monthly schedule, uses OpenAI to validate and summarize the bill, pulls up to 12 months of billing history and either returns an advisory report immediately or escalates high-severity cases via SendGrid email…
Source: https://n8n.io/workflows/18093/ — 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.
VEP WAPP. Uses openAi, lmChatOpenAi, toolCalculator, agent. Webhook trigger; 100 nodes.
⏺ 🚀 How it works
AI Customer Service Automation - Portfolio. Uses googleSheets, httpRequest, agent, memoryBufferWindow. Webhook trigger; 91 nodes.
This n8n workflow orchestrates a powerful suite of AI Agents and automations to manage and optimize various aspects of an e-commerce operation, particularly for platforms like Shopify. It leverages La
leads. Uses supabase, gmail, formTrigger, httpRequest. Webhook trigger; 62 nodes.