This workflow corresponds to n8n.io template #15706 — 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 →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "3d0920f4-1405-48d3-b439-4154d6d27926",
"name": "When clicking 'Execute workflow'",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-384,
432
],
"parameters": {},
"typeVersion": 1
},
{
"id": "2a500a15-dd6e-4840-9136-3b96109f25f6",
"name": "Combine Forecast and AI Output",
"type": "n8n-nodes-base.code",
"position": [
880,
416
],
"parameters": {
"jsCode": "const forecast = $('Build Forecast Dataset').first().json;\nconst aiOutput = $('Demand Forecast Agent').first().json.output || '';\n\nreturn [{\n json: {\n report_date: forecast.report_date,\n total_products: forecast.total_products,\n critical_count: forecast.critical_count,\n low_stock_count: forecast.low_stock_count,\n reorder_count: forecast.reorder_count,\n ok_count: forecast.ok_count,\n critical_items: forecast.critical_items,\n low_stock_items: forecast.low_stock_items,\n reorder_items: forecast.reorder_items,\n all_products: forecast.all_products,\n summary_text: forecast.summary_text,\n ai_output: aiOutput,\n has_critical: forecast.critical_count > 0\n }\n}];"
},
"typeVersion": 2
},
{
"id": "1af1c39b-3d42-454c-820d-96b410504c33",
"name": "Set Forecast Configuration",
"type": "n8n-nodes-base.set",
"position": [
-160,
432
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "1",
"name": "lookback_days",
"type": "number",
"value": 90
},
{
"id": "2",
"name": "forecast_days",
"type": "number",
"value": 30
},
{
"id": "3",
"name": "low_stock_threshold_days",
"type": "number",
"value": 14
},
{
"id": "4",
"name": "critical_stock_threshold_days",
"type": "number",
"value": 7
},
{
"id": "5",
"name": "report_date",
"type": "string",
"value": "={{ $now.format(\"yyyy-MM-dd\") }}"
},
{
"id": "6",
"name": "spreadsheet_id",
"type": "string",
"value": "1we-2q1E6iVC3Jum9_zycLN3WVndlt6TcHk-zee8GtTU"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "6b77e18f-6683-4f05-98f7-30d3c04d3f86",
"name": "Fetch Sales History",
"type": "n8n-nodes-base.googleSheets",
"position": [
64,
336
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Sales_History"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Set Forecast Configuration').first().json.spreadsheet_id }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
},
{
"id": "9564dfcd-613f-4ac2-84df-4a318c56defd",
"name": "Fetch Current Inventory",
"type": "n8n-nodes-base.googleSheets",
"position": [
64,
528
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Current_Inventory"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Set Forecast Configuration').first().json.spreadsheet_id }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
},
{
"id": "eb825449-d2a4-4916-beae-4ed884f7df3d",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
272,
416
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "aae6a52b-3104-411c-85f3-8d904b989368",
"name": "Build Forecast Dataset",
"type": "n8n-nodes-base.code",
"position": [
416,
416
],
"parameters": {
"jsCode": "const salesItems = $('Fetch Sales History').all();\nconst inventoryItems = $('Fetch Current Inventory').all();\nconst config = $('Set Forecast Configuration').first().json;\n\nconst salesByProduct = {};\nfor (const item of salesItems) {\n const s = item.json;\n const pid = s.product_id || s.SKU || s.sku;\n if (!pid) continue;\n if (!salesByProduct[pid]) salesByProduct[pid] = { sales_data: [], total_units: 0 };\n const units = parseFloat(s.units_sold || s.quantity || s.qty || 0);\n salesByProduct[pid].sales_data.push({ date: s.date, units });\n salesByProduct[pid].total_units += units;\n}\n\nconst inventoryProducts = [];\nfor (const item of inventoryItems) {\n const inv = item.json;\n const pid = inv.product_id || inv.SKU || inv.sku;\n if (!pid) continue;\n\n const salesData = salesByProduct[pid] || { sales_data: [], total_units: 0 };\n const avgDailySales = salesData.total_units / (config.lookback_days || 90);\n const currentStock = parseFloat(inv.current_stock || inv.quantity || 0);\n const leadTime = parseFloat(inv.lead_time_days || 7);\n const reorderPoint = parseFloat(inv.reorder_point || (avgDailySales * leadTime * 1.5));\n const daysOfStock = avgDailySales > 0 ? Math.floor(currentStock / avgDailySales) : 999;\n const projectedStockout = avgDailySales > 0 ? new Date(Date.now() + daysOfStock * 86400000).toISOString().split('T')[0] : 'N/A';\n const reorderQty = Math.ceil(avgDailySales * (config.forecast_days || 30) * 1.2);\n\n let status = 'OK';\n if (daysOfStock <= config.critical_stock_threshold_days) status = 'CRITICAL';\n else if (daysOfStock <= config.low_stock_threshold_days) status = 'LOW';\n else if (currentStock <= reorderPoint) status = 'REORDER';\n\n inventoryProducts.push({\n product_id: pid,\n product_name: inv.product_name || inv.name || pid,\n current_stock: currentStock,\n avg_daily_sales: Math.round(avgDailySales * 100) / 100,\n days_of_stock: daysOfStock,\n projected_stockout_date: projectedStockout,\n reorder_quantity: reorderQty,\n reorder_point: Math.round(reorderPoint),\n lead_time_days: leadTime,\n unit_cost: parseFloat(inv.unit_cost || 0),\n supplier: inv.supplier || 'Unknown',\n status,\n sales_30d: Math.round(avgDailySales * 30),\n sales_90d: salesData.total_units\n });\n}\n\ninventoryProducts.sort((a, b) => a.days_of_stock - b.days_of_stock);\n\nconst critical = inventoryProducts.filter(p => p.status === 'CRITICAL');\nconst lowStock = inventoryProducts.filter(p => p.status === 'LOW');\nconst reorderNeeded = inventoryProducts.filter(p => p.status === 'REORDER');\n\nreturn [{\n json: {\n report_date: config.report_date,\n total_products: inventoryProducts.length,\n critical_count: critical.length,\n low_stock_count: lowStock.length,\n reorder_count: reorderNeeded.length,\n ok_count: inventoryProducts.filter(p => p.status === 'OK').length,\n critical_items: critical,\n low_stock_items: lowStock,\n reorder_items: reorderNeeded,\n all_products: inventoryProducts,\n summary_text: inventoryProducts.slice(0, 20).map(p =>\n p.product_id + ' | ' + p.product_name + ' | Stock: ' + p.current_stock +\n ' | Days: ' + p.days_of_stock + ' | AvgDaily: ' + p.avg_daily_sales +\n ' | Stockout: ' + p.projected_stockout_date + ' | ' + p.status\n ).join('\\n')\n }\n}];"
},
"typeVersion": 2
},
{
"id": "b288a667-baeb-4214-a410-8d2036211fdc",
"name": "Demand Forecast Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
592,
416
],
"parameters": {
"text": "=You are an expert supply chain analyst. Analyze this inventory snapshot and produce a demand forecast briefing.\n\nREPORT DATE: {{ $json.report_date }}\nTOTAL PRODUCTS: {{ $json.total_products }}\nCRITICAL (< 7 days): {{ $json.critical_count }}\nLOW STOCK (< 14 days): {{ $json.low_stock_count }}\nNEEDS REORDER: {{ $json.reorder_count }}\n\nINVENTORY DATA:\n{{ $json.summary_text }}\n\nCRITICAL ITEMS:\n{{ JSON.stringify($json.critical_items || []) }}\n\nProduce a report in markdown:\n\n# Daily Inventory & Demand Forecast\n## {{ $json.report_date }}\n\n### CRITICAL ALERTS (Immediate Action)\n[Each critical item: product, days remaining, recommended order qty]\n\n### Reorder Recommendations (Next 7 Days)\n[Prioritized list with quantities]\n\n### Demand Trend Analysis\n[Unusual patterns, seasonality signals, anomalies]\n\n### 30-Day Forecast\n[Overall inventory health projection]\n\n### Cost Impact\n[Estimated cost of recommended reorders]\n\n### Supply Chain Risk Flags\n[Concentration risks, single-supplier dependencies]\n\nBe specific with numbers, prioritize by business impact.",
"options": {
"systemMessage": "You are an expert supply chain analyst. Provide data-driven inventory recommendations that minimize stockouts while optimizing working capital."
},
"promptType": "define"
},
"typeVersion": 3.1
},
{
"id": "11e92896-dcec-4a88-a79b-ba47f1caddca",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
592,
656
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini"
},
"options": {},
"builtInTools": {}
},
"credentials": {},
"typeVersion": 1.3
},
{
"id": "3d06a0e4-7fda-42f1-8f7b-634f4a1ba175",
"name": "Critical Stock Exists?",
"type": "n8n-nodes-base.if",
"position": [
1104,
448
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "1",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.has_critical }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2
},
{
"id": "612ad727-1322-40a9-8c38-e27a1c4f2e94",
"name": "Send a message",
"type": "n8n-nodes-base.slack",
"position": [
1328,
320
],
"parameters": {
"text": "=*CRITICAL INVENTORY ALERT* Date: {{ $json.report_date }} Critical Items (less than 7 days stock): {{ $json.critical_count }} Low Stock Items: {{ $json.low_stock_count }} Needs Reorder: {{ $json.reorder_count }} *Critical Products:* {{ ($json.critical_items || []).map(p => '\u2022 ' + p.product_name + ' (' + p.product_id + ') - ' + p.days_of_stock + ' days left - Reorder ' + p.reorder_quantity + ' units from ' + p.supplier).join('\\n') }} *AI Forecast Summary:* {{ ($json.ai_output || '').substring(0, 500) }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C0ASJMR4MMJ",
"cachedResultName": "sales-team"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.4
},
{
"id": "454af903-aa55-4470-89d2-41990fc783c6",
"name": "Write Forecast to Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
1552,
416
],
"parameters": {
"columns": {
"value": {
"AI Analysis": "={{ $json.summary_text }}",
"Report Date": "={{ $json.report_date }}",
"Reorder Count": "={{ $json.reorder_count }}",
"Critical Count": "={{ $json.critical_count }}",
"Total Products": "={{ $json.total_products }}",
"Low Stock Count": "={{ $json.low_stock_count }}"
},
"schema": [
{
"id": "Report Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Report Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total Products",
"type": "string",
"display": true,
"required": false,
"displayName": "Total Products",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Critical Count",
"type": "string",
"display": true,
"required": false,
"displayName": "Critical Count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Low Stock Count",
"type": "string",
"display": true,
"required": false,
"displayName": "Low Stock Count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Reorder Count",
"type": "string",
"display": true,
"required": false,
"displayName": "Reorder Count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "AI Analysis",
"type": "string",
"display": true,
"required": false,
"displayName": "AI Analysis",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 919236352,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1we-2q1E6iVC3Jum9_zycLN3WVndlt6TcHk-zee8GtTU/edit#gid=919236352",
"cachedResultName": "Forcast_Analysis"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Set Forecast Configuration').first().json.spreadsheet_id }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
},
{
"id": "45dfc131-e4c7-4b96-884d-fbc8e310cb54",
"name": "Generate Purchase Orders",
"type": "n8n-nodes-base.code",
"position": [
1552,
592
],
"parameters": {
"jsCode": "const forecastData = $('Build Forecast Dataset').first().json;\nconst itemsToReorder = [\n ...(forecastData.critical_items || []),\n ...(forecastData.low_stock_items || []),\n ...(forecastData.reorder_items || [])\n];\n\nconst seen = new Set();\nconst uniqueOrders = itemsToReorder.filter(item => {\n if (seen.has(item.product_id)) return false;\n seen.add(item.product_id);\n return true;\n});\n\nconst purchaseOrders = uniqueOrders.map(item => ({\n po_number: 'PO-' + item.product_id + '-' + new Date().toISOString().split('T')[0].replace(/-/g,''),\n product_id: item.product_id,\n product_name: item.product_name,\n supplier: item.supplier,\n order_quantity: item.reorder_quantity,\n unit_cost: item.unit_cost,\n total_cost: Math.round(item.reorder_quantity * item.unit_cost * 100) / 100,\n priority: item.status,\n days_of_stock: item.days_of_stock,\n projected_stockout: item.projected_stockout_date,\n created_date: forecastData.report_date,\n status: 'PENDING_APPROVAL'\n}));\n\nconst totalCost = purchaseOrders.reduce((sum, po) => sum + po.total_cost, 0);\nreturn [{\n json: {\n purchase_orders: purchaseOrders,\n po_count: purchaseOrders.length,\n total_reorder_cost: Math.round(totalCost * 100) / 100,\n report_date: forecastData.report_date\n }\n}];"
},
"typeVersion": 2
},
{
"id": "604a503d-5c60-48ea-bf23-d279758dbed6",
"name": "Log Forecast Completion",
"type": "n8n-nodes-base.set",
"position": [
1760,
496
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "1",
"name": "status",
"type": "string",
"value": "completed"
},
{
"id": "2",
"name": "report_date",
"type": "string",
"value": "={{ $('Build Forecast Dataset').first().json.report_date }}"
},
{
"id": "3",
"name": "products_analyzed",
"type": "number",
"value": "={{ $('Build Forecast Dataset').first().json.total_products }}"
},
{
"id": "4",
"name": "critical_alerts",
"type": "number",
"value": "={{ $('Build Forecast Dataset').first().json.critical_count }}"
},
{
"id": "7",
"name": "completed_at",
"type": "string",
"value": "={{ $now.toISO() }}"
},
{
"id": "bd3c635e-1fc1-4ecc-97d3-61056e8a8c6d",
"name": "pos_generated",
"type": "string",
"value": "=={{ $json.po_count !== undefined ? $json.po_count : 'N/A' }}"
},
{
"id": "9d78838a-e618-4e5c-9969-1c269e1f6ab4",
"name": "total_reorder_value",
"type": "string",
"value": "=={{ $json.total_reorder_cost !== undefined ? $json.total_reorder_cost : 'N/A' }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "99920140-c6a2-4a4a-9afb-0a17db66dcfa",
"name": "Main Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1040,
48
],
"parameters": {
"color": 7,
"width": 560,
"height": 1260,
"content": "## \ud83d\udce6 Inventory Forecasting & Auto Reorder Pipeline\n\nAutomatically analyzes sales history and current stock levels to forecast demand, flag critical shortages, generate purchase orders, and alert the team \u2014 all in one daily run.\n\n**Perfect for:** Operations managers, supply chain teams, and inventory analysts who need to eliminate manual reorder decisions and prevent stockouts.\n\n---\n\n## How it works\n\n1. **When clicking 'Execute workflow'** \u2014 Manually triggers the full inventory pipeline run.\n2. **Set Forecast Configuration** \u2014 Defines lookback period (90 days), forecast horizon (30 days), stock threshold limits, and the source Google Sheets spreadsheet ID.\n3. **Fetch Sales History** \u2014 Reads the Sales_History sheet to retrieve historical units sold per product.\n4. **Fetch Current Inventory** \u2014 Reads the Current_Inventory sheet to retrieve live stock levels, lead times, and supplier details.\n5. **Merge** \u2014 Combines the parallel sales and inventory data streams into a single dataset.\n6. **Build Forecast Dataset** \u2014 Calculates average daily sales, days of stock remaining, projected stockout dates, reorder points, and assigns each product a status (CRITICAL, LOW, REORDER, or OK).\n7. **Demand Forecast Agent** \u2014 Sends the inventory snapshot to an AI agent (GPT-4o mini) to generate a structured demand forecast report with risk flags and cost impact analysis.\n8. **OpenAI Chat Model** \u2014 Provides the GPT-4o mini language model to power the Demand Forecast Agent.\n9. **Combine Forecast and AI Output** \u2014 Merges the structured forecast dataset with the AI-generated narrative report into a single output object.\n10. **Critical Stock Exists?** \u2014 Checks if any products have fewer than 7 days of stock remaining and branches the flow accordingly.\n11. **Send a message** \u2014 *(Critical path only)* Posts a critical inventory alert to the Slack #sales-team channel listing affected products, days remaining, and reorder quantities.\n12. **Generate Purchase Orders** \u2014 Creates structured purchase order records for all CRITICAL, LOW, and REORDER items with PO numbers, quantities, costs, and supplier details.\n13. **Write Forecast to Sheet** \u2014 Appends the daily forecast summary row to the Forecast_Analysis Google Sheet.\n14. **Log Forecast Completion** \u2014 Records the final run metadata including products analyzed, critical alert count, POs generated, and total reorder value.\n\n---\n\n## Setup (~10 minutes)\n\n1. **Google Sheets OAuth2** \u2014 Connect your Google account in the *Fetch Sales History*, *Fetch Current Inventory*, and *Write Forecast to Sheet* nodes.\n2. **Spreadsheet ID** \u2014 Update the `spreadsheet_id` value in *Set Forecast Configuration* to match your Google Sheet.\n3. **Sheet tab names** \u2014 Ensure your spreadsheet has tabs named `Sales_History`, `Current_Inventory`, and `Forcast_Analysis` with matching column headers.\n4. **OpenAI API** \u2014 Add your OpenAI API key in the *OpenAI Chat Model* node.\n5. **Slack OAuth2** \u2014 Connect your Slack workspace in the *Send a message* node.\n6. **Slack channel** \u2014 Update the channel ID in *Send a message* to your preferred alert channel.\n> Stock thresholds (critical: 7 days, low: 14 days) and the 90-day lookback window can be adjusted in **Set Forecast Configuration** without touching any other node."
},
"typeVersion": 1
},
{
"id": "42795950-423c-44bf-a4a3-7c34013e0294",
"name": "Section 1: Trigger & Data Intake",
"type": "n8n-nodes-base.stickyNote",
"position": [
-432,
192
],
"parameters": {
"color": 5,
"width": 716,
"height": 556,
"content": "## 1\ufe0f\u20e3 Trigger & Data Intake\n\nThe **When clicking 'Execute workflow'** node starts the pipeline on demand. **Set Forecast Configuration** defines all key parameters including the lookback window, forecast horizon, stock alert thresholds, and the Google Sheets source ID. **Fetch Sales History** and **Fetch Current Inventory** then pull data from their respective sheet tabs in parallel before **Merge** combines both streams into a unified dataset ready for analysis."
},
"typeVersion": 1
},
{
"id": "2509e58c-e635-4a65-a88f-faff05a67475",
"name": "Section 2: AI Forecasting",
"type": "n8n-nodes-base.stickyNote",
"position": [
304,
208
],
"parameters": {
"color": 3,
"width": 776,
"height": 544,
"content": "## 2\ufe0f\u20e3 AI Demand Forecasting\n\n**Build Forecast Dataset** processes the merged data to calculate days of stock remaining, average daily sales velocity, projected stockout dates, and reorder quantities for every product \u2014 assigning each a CRITICAL, LOW, REORDER, or OK status. The **Demand Forecast Agent**, powered by the **OpenAI Chat Model** (GPT-4o mini), then receives the full snapshot and generates a structured markdown report covering critical alerts, reorder priorities, trend analysis, 30-day projections, and supply chain risk flags. **Combine Forecast and AI Output** merges the structured dataset with the AI narrative into a single payload for downstream routing."
},
"typeVersion": 1
},
{
"id": "86baa62c-ae2a-4dc1-bc38-6f0491b8f189",
"name": "Section 3: Alerts & Purchase Orders",
"type": "n8n-nodes-base.stickyNote",
"position": [
1104,
64
],
"parameters": {
"color": 6,
"width": 408,
"height": 680,
"content": "## 3\ufe0f\u20e3 Alerts & Purchase Orders\n\n**Critical Stock Exists?** evaluates whether any product has entered the critical threshold (under 7 days of stock) and branches the flow. When critical items are detected, **Send a message** fires an immediate formatted alert to the Slack #sales-team channel listing each affected product with days remaining and recommended order quantities. In parallel, **Generate Purchase Orders** builds structured PO records for all items flagged as CRITICAL, LOW, or REORDER, assigning each a unique PO number, supplier, order quantity, and estimated total cost."
},
"typeVersion": 1
},
{
"id": "37949701-a3f4-41bd-9cf3-697951dd3df8",
"name": "Section 4: Output & Logging",
"type": "n8n-nodes-base.stickyNote",
"position": [
1536,
160
],
"parameters": {
"color": 4,
"width": 520,
"height": 584,
"content": "## 4\ufe0f\u20e3 Output & Logging\n\n**Write Forecast to Sheet** appends a daily summary row to the Forecast_Analysis tab in Google Sheets, capturing report date, product counts by status, and the full AI analysis text for historical tracking. **Log Forecast Completion** finalizes the run by assembling a completion record that includes the number of products analyzed, critical alert count, purchase orders generated, and total estimated reorder value."
},
"typeVersion": 1
}
],
"connections": {
"Merge": {
"main": [
[
{
"node": "Build Forecast Dataset",
"type": "main",
"index": 0
}
]
]
},
"Send a message": {
"main": [
[
{
"node": "Write Forecast to Sheet",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "Demand Forecast Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Fetch Sales History": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Demand Forecast Agent": {
"main": [
[
{
"node": "Combine Forecast and AI Output",
"type": "main",
"index": 0
}
]
]
},
"Build Forecast Dataset": {
"main": [
[
{
"node": "Demand Forecast Agent",
"type": "main",
"index": 0
},
{
"node": "Generate Purchase Orders",
"type": "main",
"index": 0
}
]
]
},
"Critical Stock Exists?": {
"main": [
[
{
"node": "Send a message",
"type": "main",
"index": 0
}
],
[
{
"node": "Write Forecast to Sheet",
"type": "main",
"index": 0
}
]
]
},
"Fetch Current Inventory": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"Write Forecast to Sheet": {
"main": [
[
{
"node": "Log Forecast Completion",
"type": "main",
"index": 0
}
]
]
},
"Generate Purchase Orders": {
"main": [
[
{
"node": "Log Forecast Completion",
"type": "main",
"index": 0
}
]
]
},
"Set Forecast Configuration": {
"main": [
[
{
"node": "Fetch Sales History",
"type": "main",
"index": 0
},
{
"node": "Fetch Current Inventory",
"type": "main",
"index": 0
}
]
]
},
"Combine Forecast and AI Output": {
"main": [
[
{
"node": "Critical Stock Exists?",
"type": "main",
"index": 0
}
]
]
},
"When clicking 'Execute workflow'": {
"main": [
[
{
"node": "Set Forecast Configuration",
"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.
googleSheetsOAuth2ApislackOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
How it works
Source: https://n8n.io/workflows/15706/ — 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.
Stop manually sending follow-ups. This workflow automates your entire cold email outreach with AI-powered personalization, smart scheduling, and automatic reply detection.
This workflow streamlines academic assessment through a multi-agent AI system that interprets rubrics, grades submissions, checks for plagiarism, performs quality moderation, generates feedback, and e
This workflow automates invoice processing directly from your email inbox.
[](https://www.youtube.com/watch?v=MD1krFvVKdU) Automatically extract, evaluate, and shortlist multiple resumes against a selected job description using GPT-4. This smart, scalable n8n workflow helps
Streamline Facebook Messenger inbox management with an AI-powered categorization and response system. 💬⚙️ This workflow automatically classifies new messages as Lead, Query, or Spam using GPT-4, route