This workflow corresponds to n8n.io template #11082 — we link there as the canonical source.
This workflow follows the Agent → Airtable 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": "5DDtEV5rA1bpu9JO",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Generate AI-friendly product descriptions from Airtable to Airtable",
"tags": [],
"nodes": [
{
"id": "11133939-8502-4868-9120-01541818aed3",
"name": "Every 15 Minutes",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-96,
-80
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 15
}
]
}
},
"typeVersion": 1.2
},
{
"id": "63af4aa5-1ca5-499e-b258-1d5d95d00523",
"name": "Fetch Pending Products",
"type": "n8n-nodes-base.airtable",
"position": [
128,
-80
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "app28w1Y5KEHUZEwl",
"cachedResultUrl": "https://airtable.com/app28w1Y5KEHUZEwl",
"cachedResultName": "Products"
},
"table": {
"__rl": true,
"mode": "list",
"value": "tblGyulGNkzj5iC7R",
"cachedResultUrl": "https://airtable.com/app28w1Y5KEHUZEwl/tblGyulGNkzj5iC7R",
"cachedResultName": "Table 1"
},
"options": {},
"operation": "search"
},
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "e4fd95a6-2fcf-4732-8d36-56814dfe0d9a",
"name": "Split Into Batches",
"type": "n8n-nodes-base.splitInBatches",
"position": [
304,
-80
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "43931121-3745-4070-be97-48732aac01ef",
"name": "Parse AI JSON",
"type": "n8n-nodes-base.code",
"position": [
960,
-64
],
"parameters": {
"jsCode": "const items = [];\n\nfor (const item of $input.all()) {\n const output = item.json.output;\n \n // Extract the record ID from the input item\n // Assuming the record ID comes from a previous Airtable node\n const recordId = $('Split Into Batches').first().json.id || \"Unknown\" ;\n \n // Convert bullet features array to newline-separated string\n const bulletFeaturesText = output.ai_bullet_features.join('\\n');\n \n // Convert feature table to JSON string\n const featureTableJson = JSON.stringify(output.ai_feature_table);\n \n items.push({\n json: {\n id: recordId,\n ai_long_description: output.ai_long_description,\n ai_short_answer_block: output.ai_short_answer_block,\n ai_bullet_features: bulletFeaturesText,\n ai_feature_table_json: featureTableJson,\n ai_status: 'done',\n ai_last_run_at: $now.toISO()\n },\n pairedItem: item.pairedItem\n });\n}\n\nreturn items;"
},
"typeVersion": 2
},
{
"id": "d8114e15-cd5c-4684-b2c0-830fae0d25fb",
"name": "Prepare Airtable Update Data",
"type": "n8n-nodes-base.set",
"position": [
1264,
-64
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a1b2c3d4",
"name": "id",
"type": "string",
"value": "={{ $json.id }}"
},
{
"id": "b2c3d4e5",
"name": "ai_long_description",
"type": "string",
"value": "={{ $json.ai_long_description }}"
},
{
"id": "c3d4e5f6",
"name": "ai_short_answer_block",
"type": "string",
"value": "={{ $json.ai_short_answer_block }}"
},
{
"id": "d4e5f6a7",
"name": "ai_bullet_features",
"type": "string",
"value": "={{ $json.ai_bullet_features }}"
},
{
"id": "e5f6a7b8",
"name": "ai_feature_table_json",
"type": "string",
"value": "={{ $json.ai_feature_table_json }}"
},
{
"id": "f6a7b8c9",
"name": "status",
"type": "string",
"value": "Done"
},
{
"id": "a7b8c9d0",
"name": "ai_last_run_at",
"type": "string",
"value": "={{ $now }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "5acba58d-fe30-4506-a755-a8c9542353fb",
"name": "Update Product In Airtable",
"type": "n8n-nodes-base.airtable",
"position": [
1568,
-64
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "app28w1Y5KEHUZEwl",
"cachedResultUrl": "https://airtable.com/app28w1Y5KEHUZEwl",
"cachedResultName": "Products"
},
"table": {
"__rl": true,
"mode": "list",
"value": "tblGyulGNkzj5iC7R",
"cachedResultUrl": "https://airtable.com/app28w1Y5KEHUZEwl/tblGyulGNkzj5iC7R",
"cachedResultName": "Table 1"
},
"columns": {
"value": {
"id": "={{ $json.id }}",
"Status": "={{ $json.status }}",
"ai_last_run_at": "={{ $json.ai_last_run_at }}",
"ai_bullet_features": "={{ $json.ai_bullet_features }}",
"ai_long_description": "={{ $json.ai_long_description }}",
"ai_feature_table_json": "={{ $json.ai_feature_table_json }}",
"ai_short_answer_block": "={{ $json.ai_short_answer_block }}"
},
"schema": [
{
"id": "id",
"type": "string",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "id",
"defaultMatch": true
},
{
"id": "Name",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Product Name",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Product Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Brand",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Brand",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Category",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Category",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Price",
"type": "number",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Price",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Currency",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Currency",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Geo Region",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Geo Region",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Color",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Color",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Size",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Size",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Material",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Material",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ai_long_description",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "ai_long_description",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ai_short_answer_block",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "ai_short_answer_block",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ai_bullet_features",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "ai_bullet_features",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ai_feature_table_json",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "ai_feature_table_json",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ai_last_run_at",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "ai_last_run_at",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update"
},
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "3d4ad36b-542c-478c-b5a9-9e7799610f1f",
"name": "OpenAI Chat Model - GPT-4o-mini",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
576,
160
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "gpt-4o-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "280aae8c-cb2f-4dff-8b67-a4a82b42a2a6",
"name": "Memory - Conversation Buffer",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
688,
144
],
"parameters": {
"sessionKey": "\"GEO Session e-commerce\"",
"sessionIdType": "customKey"
},
"typeVersion": 1.3
},
{
"id": "0888441d-f52b-4a89-a3e8-abcd23e1cea6",
"name": "Output Parser - Structured JSON",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
816,
144
],
"parameters": {
"jsonSchemaExample": "{\n \"ai_long_description\": \"This cotton crewneck T-shirt by UrbanWear is designed for everyday comfort in warm climates. Made from 100% soft and breathable cotton, it offers a relaxed fit and durable stitching suitable for casual wear, travel, or layering. The fabric helps absorb moisture, keeping the wearer cool throughout the day.\",\n \"ai_short_answer_block\": \"A lightweight and breathable cotton T-shirt from UrbanWear, designed for daily comfort in warm weather. It features durable stitching, a classic crewneck style, and is ideal for casual or layered outfits.\",\n \"ai_bullet_features\": [\n \"100% soft and breathable cotton\",\n \"Relaxed fit with classic crewneck\",\n \"Ideal for daily wear and warm weather\"\n ],\n \"ai_feature_table\": [\n { \"label\": \"Material\", \"value\": \"100% Cotton\" },\n { \"label\": \"Fit Type\", \"value\": \"Relaxed\" },\n { \"label\": \"Neck Style\", \"value\": \"Crewneck\" },\n { \"label\": \"Suitable For\", \"value\": \"Casual & Daily Wear\" }\n ]\n}\n"
},
"typeVersion": 1.3
},
{
"id": "7746b503-e560-46d1-bd47-4589de72d15f",
"name": "AI Agent - GEO Analyzer",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
624,
-64
],
"parameters": {
"text": "=Product data:\n- Name:{{ $json['Product Name'] }}\n- Brand: {{ $json.Brand }}\n- Category: {{ $json.Brand }}\n- Price: {{ $json.Price }}\n- Target region: {{ $json['Geo Region'] }}\n- Existing description (if any):None\n- Key attributes: color: {{ $json.Color }}, size: {{ $json.Size }}, material: {{ $json.Material }}\nGuidelines:\n- Language: English\n- Tone: clear, factual, benefit-focused.\n- Make content easy for AI Answer Engines to use: short, structured, unambiguous.\n- Do NOT hallucinate impossible specs; only infer what is normal/common for this category.\n- Output VALID JSON only. No explanation, no extra text.\n",
"options": {
"systemMessage": "=You are an eCommerce product content specialist.\n\nYour job:\n1. Create AI-friendly product content that works well in AI Overviews and answer engines.\n2. Always return STRICT JSON, no markdown.\n\nReturn this JSON schema:\n{\n \"ai_long_description\": \"string\",\n \"ai_short_answer_block\": \"string (2\u20133 sentences, factual tone)\",\n \"ai_bullet_features\": [\"string\", \"string\", \"string\"],\n \"ai_feature_table\": [\n { \"label\": \"string\", \"value\": \"string\" }\n ]\n}\n"
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 2.1
},
{
"id": "0d9fbb62-70dc-4d8f-8b36-39a892d4d4cb",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-224,
-1024
],
"parameters": {
"width": 480,
"height": 784,
"content": "## AI-Friendly Product Description Generator \u2013 Overview\n\nThis workflow creates high-quality, structured product descriptions using AI. It checks Airtable every 15 minutes for products marked as pending, generates long descriptions, short answer blocks, bullet features, and feature table content, and updates the same Airtable record. This helps eCommerce teams maintain consistent, SEO-friendly product copy with minimal effort.\n\n### How it works\n1. A schedule trigger runs every 15 minutes.\n2. Airtable returns products with status = \u201cpending\u201d.\n3. Products are processed in small batches.\n4. GPT-4o-mini generates structured JSON content for each product.\n5. A structured output parser ensures clean, valid JSON.\n6. A Code node converts AI output into Airtable-safe fields.\n7. Airtable is updated with the generated descriptions and marked \u201cdone\u201d.\n\n### Setup steps\n- Add Airtable credentials and connect to your Product table.\n- Add OpenAI credentials.\n- Confirm Airtable fields match: \n `ai_long_description`, \n `ai_short_answer_block`, \n `ai_bullet_features`, \n `ai_feature_table_json`, \n `status`, \n `ai_last_run_at`.\n- Run a test execution to verify results.\n\n### Customization\nAdjust frequency, tone, prompt style, or field mappings as needed.\n"
},
"typeVersion": 1
},
{
"id": "3d1f16aa-9d98-4835-b92f-b808c800d8bc",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-224,
-192
],
"parameters": {
"color": 2,
"width": 464,
"height": 272,
"content": "## Trigger & Fetch Products\nRuns every 15 minutes and pulls pending product records from Airtable.\n"
},
"typeVersion": 1
},
{
"id": "116c670f-d97d-4d54-a2a4-2c39562a6ae0",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
256,
-192
],
"parameters": {
"color": 2,
"height": 336,
"content": "## Batch Processing\nSplits products into batches to avoid API rate limits.\n"
},
"typeVersion": 1
},
{
"id": "8a5b6e21-9350-4faf-9514-08bead79973f",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
528,
-160
],
"parameters": {
"color": 2,
"width": 560,
"height": 464,
"content": "## AI Content Generation\nGenerates product descriptions and structured content using GPT-4o-mini.\n"
},
"typeVersion": 1
},
{
"id": "42ea25a7-910f-4b7e-b67b-152a67f4f77c",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1184,
-160
],
"parameters": {
"color": 2,
"height": 304,
"content": "## Format AI Output\nConverts structured JSON into clean Airtable fields.\n"
},
"typeVersion": 1
},
{
"id": "35403fb3-67da-4978-b965-22ad5e77d27a",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1488,
-176
],
"parameters": {
"color": 2,
"height": 320,
"content": "## Update Airtable\nUpdates product records with AI output and marks them as completed.\n"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "cc6c0bcc-4035-4410-90ed-a83cf837f417",
"connections": {
"Parse AI JSON": {
"main": [
[
{
"node": "Prepare Airtable Update Data",
"type": "main",
"index": 0
}
]
]
},
"Every 15 Minutes": {
"main": [
[
{
"node": "Fetch Pending Products",
"type": "main",
"index": 0
}
]
]
},
"Split Into Batches": {
"main": [
[],
[
{
"node": "AI Agent - GEO Analyzer",
"type": "main",
"index": 0
}
]
]
},
"Fetch Pending Products": {
"main": [
[
{
"node": "Split Into Batches",
"type": "main",
"index": 0
}
]
]
},
"AI Agent - GEO Analyzer": {
"main": [
[
{
"node": "Parse AI JSON",
"type": "main",
"index": 0
}
]
]
},
"Update Product In Airtable": {
"main": [
[
{
"node": "Split Into Batches",
"type": "main",
"index": 0
}
]
]
},
"Memory - Conversation Buffer": {
"ai_memory": [
[
{
"node": "AI Agent - GEO Analyzer",
"type": "ai_memory",
"index": 0
}
]
]
},
"Prepare Airtable Update Data": {
"main": [
[
{
"node": "Update Product In Airtable",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model - GPT-4o-mini": {
"ai_languageModel": [
[
{
"node": "AI Agent - GEO Analyzer",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Output Parser - Structured JSON": {
"ai_outputParser": [
[
{
"node": "AI Agent - GEO Analyzer",
"type": "ai_outputParser",
"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.
airtableTokenApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Automate your eCommerce content workflow by generating AI-optimized product descriptions directly from Airtable. 🛍️🤖 This automation checks for pending products every 15 minutes, processes them in batches, and uses GPT-4o-mini to create structured long descriptions, short answer…
Source: https://n8n.io/workflows/11082/ — 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-powered workflow automates the entire lifecycle of real estate lead intake, qualification, routing, assignment, and reporting across multiple channels. It brings WhatsApp inquiries and websit
Automate your content repurposing workflow by transforming long-form articles, blogs, and newsletters into short, high-signal, AI-ready social media snippets. ✍️🤖 This workflow fetches pending content
Streamline management decision-making by automatically evaluating high-priority tenders, generating AI-powered executive summaries, and routing them for approval inside Slack. 🤖📩 This workflow pulls p
Ensure suppliers never miss a follow-up by automating overdue purchase order tracking and scheduling. 📦⏰ This workflow checks Airtable every weekday morning for open POs older than seven days without
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.