This workflow corresponds to n8n.io template #15284 — we link there as the canonical source.
This workflow follows the Agent → Datatable 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": "hNaShlhwUzpKwvbl",
"name": "carousel-post-V2",
"tags": [],
"nodes": [
{
"id": "61ef1f25-c8e3-4fe7-8185-14f6b476ee3d",
"name": "Get row(s)",
"type": "n8n-nodes-base.dataTable",
"position": [
-976,
160
],
"parameters": {
"filters": {
"conditions": [
{
"keyName": "status",
"condition": "isEmpty"
}
]
},
"matchType": "allConditions",
"operation": "get",
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "k33InE4n50NAQIQB",
"cachedResultUrl": "/projects/YORR4xM3FFToOHnO/datatables/k33InE4n50NAQIQB",
"cachedResultName": "demo-Jainam-insta-carousel"
}
},
"typeVersion": 1.1
},
{
"id": "35b665c7-3a99-4292-b808-13db12bbe75f",
"name": "Generate an image",
"type": "@n8n/n8n-nodes-langchain.googleGemini",
"position": [
192,
448
],
"parameters": {
"prompt": "={{ $json.image_prompt }}",
"modelId": {
"__rl": true,
"mode": "list",
"value": "models/gemini-2.5-flash-image",
"cachedResultName": "models/gemini-2.5-flash-image (Nano Banana)"
},
"options": {},
"resource": "image"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "d1681035-89be-4798-80fd-425dbb6783f5",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
-736,
352
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-nano",
"cachedResultName": "gpt-4.1-nano"
},
"options": {},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "91072263-2d9e-41e9-af97-abf6e81c235c",
"name": "When clicking \u2018Execute workflow\u2019",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-1184,
160
],
"parameters": {},
"typeVersion": 1
},
{
"id": "03e25f1d-ed95-49b1-ae06-f01949733277",
"name": "Upload a File",
"type": "n8n-nodes-uploadtourl.uploadToUrl",
"position": [
352,
448
],
"parameters": {},
"credentials": {
"uploadToUrlApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "3953f0ca-2757-40f5-920c-e6e3d1170f0e",
"name": "Generate-Prompt",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-672,
160
],
"parameters": {
"text": "=You are an expert AI image prompt engineer. I want to generate images based on this core concept:{{ $json.prompt }}",
"options": {
"systemMessage": "=You are an expert AI image prompt engineer. I want to generate images based on this core concept:{{ $json.prompt }}\nI need you to create {{ $json.number_of_images }} entirely distinct, highly detailed visual prompts based on that concept. Vary the camera angles, lighting conditions, art styles, and compositions so no two images look the same.\n\nYou must reply ONLY with a valid JSON array of objects. Do not include markdown formatting, backticks, or conversational text. Use this exact schema:\n[\n{ \"image_prompt\": \"highly detailed prompt 1...\", \"caption\": \"short instagram caption 1\" },\n{ \"image_prompt\": \"highly detailed prompt 2...\", \"caption\": \"short instagram caption 2\" }\n]\""
},
"promptType": "define"
},
"typeVersion": 3.1
},
{
"id": "7d27b176-68ee-416e-b41c-cc5c47914232",
"name": "Parse_Array",
"type": "n8n-nodes-base.code",
"position": [
-336,
160
],
"parameters": {
"jsCode": "// 1. Grab the stringified JSON from the 'output' field\nconst rawJsonString = $input.first().json.output;\n\n// 2. Parse the string back into a real data array\nconst parsedArray = JSON.parse(rawJsonString);\n\n// 3. Map it into n8n's standard item format so it runs the next node 5 times\nreturn parsedArray.map(item => ({ json: item }));"
},
"typeVersion": 2
},
{
"id": "cabb73db-ea49-46cb-88e4-2e933b98e966",
"name": "Loop For Each Prompt",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-160,
160
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "43bd28ba-d8c6-4b40-8369-6246e95eb21a",
"name": "Publish on Instagram",
"type": "@mookielianhd/n8n-nodes-instagram.instagram",
"position": [
592,
-160
],
"parameters": {
"node": "=17841477181716596",
"caption": "={{ $json.caption }}",
"resource": "carousel",
"carouselInputMode": "fromField",
"carouselMediaArrayField": "image_urls"
},
"credentials": {
"instagramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "b27ae882-08d9-4286-9ff9-758ee47fbe3e",
"name": "Update row(s)",
"type": "n8n-nodes-base.dataTable",
"position": [
896,
-160
],
"parameters": {
"columns": {
"value": {
"status": "=Published id : {{ $json.id }}"
},
"schema": [
{
"id": "prompt",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "prompt",
"defaultMatch": false
},
{
"id": "number_of_images",
"type": "number",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "number_of_images",
"defaultMatch": false
},
{
"id": "status",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "status",
"defaultMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"filters": {
"conditions": [
{
"keyName": "status",
"condition": "isEmpty"
}
]
},
"options": {},
"operation": "update",
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "k33InE4n50NAQIQB",
"cachedResultUrl": "/projects/YORR4xM3FFToOHnO/datatables/k33InE4n50NAQIQB",
"cachedResultName": "demo-Jainam-insta-carousel"
}
},
"typeVersion": 1.1
},
{
"id": "eb75b355-b55e-404f-8cb5-c51f0fb2ba6a",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1232,
-112
],
"parameters": {
"color": 4,
"width": 416,
"height": 432,
"content": "## \ud83d\ude80 Step 1: Trigger & Fetch Content Idea\n\nThis workflow starts manually and pulls content ideas from a Data Table.\n\n\u2022 Fetches rows where \"status\" is empty \n\u2022 Each row contains:\n - Core content idea (prompt) \n - Number of images to generate \n\u2022 Ensures only unpublished posts are processed \n\n\ud83d\udc49 Replace with Cron/Webhook for full automation"
},
"typeVersion": 1
},
{
"id": "2f32e483-2f86-4c3b-9fb6-bde0a08fe7a6",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-768,
-112
],
"parameters": {
"color": 6,
"width": 368,
"height": 592,
"content": "## \ud83e\udde0 Step 2: Generate Image Prompts & Captions\n\nUses AI to expand a single idea into multiple unique prompts.\n\n\u2022 Generates multiple detailed image prompts \n\u2022 Creates matching Instagram captions \n\u2022 Ensures each prompt is visually distinct \n\u2022 Outputs structured JSON (image_prompt + caption) \n\n\ud83d\udc49 This is the \"creative brain\" of the workflow"
},
"typeVersion": 1
},
{
"id": "94cdefb8-f00d-438e-b7be-08f14fe2ddaf",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-352,
-80
],
"parameters": {
"color": "#3B1645",
"width": 368,
"height": 384,
"content": "## \ud83d\udd01 Step 3: Parse & Process Each Prompt\n\nConverts AI output into usable items and loops through them.\n\n\u2022 Parses JSON into individual items \n\u2022 Runs each prompt one by one \n\u2022 Ensures smooth execution and control \n\n\ud83d\udc49 Prepares data for image generation"
},
"typeVersion": 1
},
{
"id": "07475919-c98b-4ab2-a642-24860d98a8a7",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
112,
224
],
"parameters": {
"color": "#515309",
"width": 416,
"height": 384,
"content": "## \ud83c\udfa8 Step 4: Generate Images & Upload (Through \"Upload to URL\")\n\nCreates images and makes them publicly accessible.\n\n\u2022 Generates images using AI (Gemini) \n\u2022 Uploads each image to a public URL \n\u2022 Ensures images are ready for Instagram \n\n\ud83d\udc49 Each loop iteration produces one image"
},
"typeVersion": 1
},
{
"id": "4f75043f-511d-480b-8c3d-def7900f5a42",
"name": "Collect Image URLs",
"type": "n8n-nodes-base.code",
"position": [
176,
-160
],
"parameters": {
"jsCode": "// Read all accumulated URLs collected across every loop iteration\nconst staticData = $getWorkflowStaticData('global');\nconst imageUrls = staticData.collectedUrls || [];\n\n// Reset for the next workflow run\nstaticData.collectedUrls = [];\n\n// Use the caption from the first generated slide\nconst postCaption = $('Parse_Array').first().json.caption;\n\nreturn [{\n json: {\n image_urls: imageUrls,\n caption: postCaption\n }\n}];"
},
"typeVersion": 2
},
{
"id": "a1fe148b-7e93-49b1-977a-266ab1d32b03",
"name": "Rate Control",
"type": "n8n-nodes-base.code",
"position": [
688,
448
],
"parameters": {
"jsCode": "// Accumulate this iteration's uploaded URL into persistent workflow memory\nconst staticData = $getWorkflowStaticData('global');\nif (!staticData.collectedUrls) staticData.collectedUrls = [];\n\nconst uploadedItems = $('Upload a File').all();\nfor (const item of uploadedItems) {\n if (item?.json?.url) {\n staticData.collectedUrls.push(item.json.url);\n }\n}\n\n// Original 15-second pause to respect Instagram rate limits\nawait new Promise(resolve => setTimeout(resolve, 15000));\n\nreturn $input.all();"
},
"typeVersion": 2
},
{
"id": "76f53158-3dfc-4b0c-ab38-69b3c4e296b2",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
480,
-400
],
"parameters": {
"color": "#155B3D",
"width": 304,
"height": 400,
"content": "## \ud83d\udcf8 Step 7: Publish Instagram Carousel\n\nCombines all images into a single Instagram post.\n\n\u2022 Merges all image URLs into one array \n\u2022 Uses caption generated earlier \n\u2022 Publishes as a carousel post \n\n\ud83d\udc49 Fully automated content publishing"
},
"typeVersion": 1
},
{
"id": "38cc32dc-2fa7-4da0-a5e7-a0defc0210ca",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
816,
-416
],
"parameters": {
"color": "#94575A",
"width": 288,
"height": 416,
"content": "## \u2705 Step 8: Update Database\n\nMarks the content as published.\n\n\u2022 Updates Data Table with:\n - Post ID \n - Status = Published \n\u2022 Prevents duplicate posting \n\n\ud83d\udc49 Keeps workflow state clean and trackable"
},
"typeVersion": 1
},
{
"id": "98ca6bc4-d398-46fc-aaf5-5b289ea77cb0",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
64,
-544
],
"parameters": {
"color": "#06605E",
"width": 384,
"height": 544,
"content": "## \ud83d\udce6 Step 6: Combine All Image URLs\n\nThis node prepares the final data for Instagram publishing.\n\n\u2022 Collects all generated image URLs from previous steps \n\u2022 Uses workflow static storage to access accumulated data \n\u2022 Resets stored URLs after execution (prepares for next run) \n\u2022 Extracts caption from the first generated item \n\n\ud83d\udc49 Outputs a single object with:\n- image_urls (array)\n- caption (string)\n\n\ud83d\udc49 This ensures Instagram receives all images in one request"
},
"typeVersion": 1
},
{
"id": "e7a4b92e-ff46-4fa6-a2bf-889caa050f33",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
544,
112
],
"parameters": {
"color": "#894106",
"width": 384,
"height": 496,
"content": "## \u23f1\ufe0f Step 5: Rate Limiting & URL Accumulation\n\nHandles API safety and data persistence during looping.\n\n\u2022 Stores each uploaded image URL into global workflow memory \n\u2022 Ensures URLs persist across loop iterations \n\u2022 Adds a 15-second delay to avoid API rate limits \n\u2022 Prevents failures when generating multiple images \n\n\ud83d\udc49 Critical for stability when working with:\n- AI image generation \n- Upload APIs \n- Instagram publishing \n\n\ud83d\udc49 Without this, the workflow may fail due to rate limits"
},
"typeVersion": 1
},
{
"id": "d43f942b-ee01-4311-84c3-f67bed90ddee",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1040,
-400
],
"parameters": {
"color": "#7D5240",
"width": 592,
"height": 192,
"content": "## \ud83d\udca1 What This Workflow Does\n\nThis workflow automatically creates and publishes Instagram carousel posts using AI.\n\n\u2022 Turns a single idea into multiple images \n\u2022 Generates captions automatically \n\u2022 Uploads images and publishes to Instagram \n\u2022 Updates database after publishing \n\n\ud83d\udc49 Perfect for content automation & social media growth"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "cd78ddde-1ab7-4f87-80e9-354027f55eb4",
"connections": {
"Get row(s)": {
"main": [
[
{
"node": "Generate-Prompt",
"type": "main",
"index": 0
}
]
]
},
"Parse_Array": {
"main": [
[
{
"node": "Loop For Each Prompt",
"type": "main",
"index": 0
}
]
]
},
"Rate Control": {
"main": [
[
{
"node": "Loop For Each Prompt",
"type": "main",
"index": 0
}
]
]
},
"Upload a File": {
"main": [
[
{
"node": "Rate Control",
"type": "main",
"index": 0
}
]
]
},
"Generate-Prompt": {
"main": [
[
{
"node": "Parse_Array",
"type": "main",
"index": 0
}
]
]
},
"Generate an image": {
"main": [
[
{
"node": "Upload a File",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "Generate-Prompt",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Collect Image URLs": {
"main": [
[
{
"node": "Publish on Instagram",
"type": "main",
"index": 0
}
]
]
},
"Loop For Each Prompt": {
"main": [
[
{
"node": "Collect Image URLs",
"type": "main",
"index": 0
}
],
[
{
"node": "Generate an image",
"type": "main",
"index": 0
}
]
]
},
"Publish on Instagram": {
"main": [
[
{
"node": "Update row(s)",
"type": "main",
"index": 0
}
]
]
},
"When clicking \u2018Execute workflow\u2019": {
"main": [
[
{
"node": "Get row(s)",
"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.
googlePalmApiinstagramApiopenAiApiuploadToUrlApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Tired of manually creating Instagram carousel content? This workflow takes a single content idea from a database, uses GPT-4.1 Nano + Gemini 2.5 Flash to generate unique images and captions, uploads them, and publishes a fully formatted Instagram carousel — all without touching…
Source: https://n8n.io/workflows/15284/ — 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 n8n workflow automatically converts new RSS feed articles into ready-to-publish social media posts for LinkedIn and Instagram.
A comprehensive n8n workflow demonstrating advanced AI agent orchestration, stateful conversation management, and multi-modal input processing for nutrition tracking applications.
Automate your personal productivity with this intelligent n8n workflow that integrates Telegram, Google Sheets, and OpenAI (GPT-4o). This system uses multiple AI agents to manage work hours, tasks, fi
📄 Documentation: Notion Guide
This workflow serves as a comprehensive "Workflow Nodes SEO & Documentation Generator". It uses AI to analyze, rename, and document n8n workflows, offering a streamlined way to optimize workflow reada