AutomationFlowsAI & RAG › Create Sprint Goals From Google Sheets with Pega Agile Studio and Google Gemini

Create Sprint Goals From Google Sheets with Pega Agile Studio and Google Gemini

ByRichard Nijsten @rnijsten on n8n.io

Based on the Google Sheet data, the AI will retrieve the userstories ID's, retrieves the userstory data and the corresponding attachments and creates sprint goals according to the defined system prompt.

Event trigger★★★★★ complexityAI-powered33 nodesGoogle Gemini ChatGoogle SheetsHTTP Request ToolGmailAgentExecute Workflow TriggerGoogle DriveHTTP Request
AI & RAG Trigger: Event Nodes: 33 Complexity: ★★★★★ AI nodes: yes Added:

This workflow corresponds to n8n.io template #13602 — we link there as the canonical source.

This workflow follows the Agent → Execute Workflow Trigger 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 →

Download .json
{
  "id": "5HeHcrsztsyUafYZ",
  "name": "Create sprint goals using Pega Agile Studio with AI",
  "tags": [],
  "nodes": [
    {
      "id": "c3d5e4aa-94f7-49f8-b0bb-898f988ad975",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1360,
        544
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "3c0ed479-2a2a-4f70-8268-4d02322d166d",
      "name": "Retrieve_Data_From_Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        720,
        320
      ],
      "parameters": {
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "",
          "cachedResultUrl": "",
          "cachedResultName": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": ""
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "d24f1b08-2cfb-4906-95f7-e517c6d5dfc1",
      "name": "Retrieve Agile Studio US",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        1696,
        544
      ],
      "parameters": {
        "url": "=https://<yoururl>/userstories/{{ $fromAI('Userstory', ``, 'string') }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "oAuth2Api"
      },
      "typeVersion": 4.4
    },
    {
      "id": "5d1f3240-4590-4df1-9db6-e26c457c946f",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        944,
        320
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "Userstory"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4de6ab39-8e70-4e80-9cf2-5350b488edcd",
      "name": "Send a message",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1888,
        320
      ],
      "parameters": {
        "message": "={{ $json.output }}",
        "options": {},
        "subject": "Sprint Goals"
      },
      "typeVersion": 2.2
    },
    {
      "id": "0199b4f9-5f45-4453-b6da-c729c3dd1cb1",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        144
      ],
      "parameters": {
        "width": 336,
        "height": 800,
        "content": "## Create sprint goals using Pega Agile Studio with AI\nBased on the Google Sheet data, the AI will retrieve the userstories ID's, retrieves the userstory data and the corresponding attachments and creates sprint goals according the defined system prompt.\n\n**Who's it for**\n* Product owners/Scrum masters that use Pega Agile Studio\n\n\n**How it works** \n* It retrieves the data from each userstory using the Agile Studio api, and the Google API to gather the attachments in the corresponding documents/sheets/slides.\n* Then the AI processes it according to the system prompt and generates a mail.\n\n\n**How to set up** \n* Create a Google Sheet and add the userstories you want in the Google Sheet in column named \"Userstory\".\n* Set the GoogleSheet ID in the node \"Retrieve_Data_From_Sheet\" \n* Setup other credentials.\n* Publish the subworkflows for attachment handling.\n* Execute the workflow.\n\n**Requirements** \n* Access to Pega Agile Studio OAuth2 Api.\n* AI API.\n* Access to Google Cloud for the Google API's"
      },
      "typeVersion": 1
    },
    {
      "id": "4a284dcc-5185-4e3f-bb87-debaab06a161",
      "name": "Sprint Goal Generator",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1360,
        320
      ],
      "parameters": {
        "text": "=For the {{ $json.Userstory }} in the column \"Userstory\" retrieve the information using the following subworkflows/tools:\n- Retrieve Agile Studio US using only 1 US at a time, so US-1234\n- Call 'Get Attachments - Agile Studio US'\n\nUse the collected information to generate general sprint goals.\n",
        "options": {
          "systemMessage": "**ROLE AND GOAL:**\n\nYou are a Scrum Master/Product Owner. Your task is to formulate one or two overarching, value-driven Sprint Goals based on the Userstories and their attachments. \n\nBeautify the HTML using inline CSS styling for an email. Format it like a modern newsletter. Output only the results without any header elements.\nKeep the formatting and layout each mail the same.\nGenerate a professional HTML email report\nOutput ONLY the raw HTML code. \nDO NOT include introductory text (like 'Here is your report').\nDO NOT include markdown code blocks (no ```html).\nDO NOT include explanations, justifications, or Python code.\nStart your response with <html> and end it with </html>.\""
        },
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "ded0900b-c824-4960-b9d2-4514d2870d4c",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        496,
        320
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "ed5a1c26-7bdf-4107-a015-b6e0851e70da",
      "name": "When Executed by Another Workflow",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        320,
        1904
      ],
      "parameters": {
        "workflowInputs": {
          "values": [
            {
              "name": "Userstory"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "8ec6fb9e-2dcb-48b7-a971-c8f0a24c98e9",
      "name": "Switch",
      "type": "n8n-nodes-base.switch",
      "position": [
        1248,
        1408
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "f29699b0-1917-431c-a1f5-5c238108655d",
                    "operator": {
                      "type": "string",
                      "operation": "notContains"
                    },
                    "leftValue": "={{ $json.url }}",
                    "rightValue": "rtpof=true"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "405163ca-cb47-49d9-aada-734bd5e8f207",
                    "operator": {
                      "type": "string",
                      "operation": "contains"
                    },
                    "leftValue": "={{ $json.url }}",
                    "rightValue": "rtpof=true"
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "1475c17f-fb96-47db-ad2f-343a465465b9",
      "name": "Download file",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1696,
        1504
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.url }}"
        },
        "options": {},
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "ab86e388-ccd2-4413-9eb0-f714872a53d9",
      "name": "Extract from File",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        1920,
        1504
      ],
      "parameters": {
        "options": {},
        "operation": "xlsx"
      },
      "typeVersion": 1.1
    },
    {
      "id": "ced10b8b-594f-4684-b299-aad76d3865e0",
      "name": "Merge the results",
      "type": "n8n-nodes-base.merge",
      "position": [
        2368,
        1408
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "363e8b1a-89ca-40ab-9c18-15172df1ddaf",
      "name": "Convert to sheet data to readable format",
      "type": "n8n-nodes-base.code",
      "position": [
        2144,
        1312
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n    let extractedText = \"\";\n    const sheets = item.json.sheets || [];\n\n    sheets.forEach(sheet => {\n        const sheetTitle = sheet.properties?.title || \"Untitled Sheet\";\n        extractedText += `### Sheet: ${sheetTitle}\\n`;\n        \n        const rowData = sheet.data?.[0]?.rowData || [];\n        \n        rowData.forEach(row => {\n            const rowValues = row.values || [];\n            const rowString = rowValues\n                .map(cell => cell.formattedValue || cell.effectiveValue?.stringValue || \"\")\n                .join(\" | \");\n            \n            if (rowString.trim().replace(/\\|/g, \"\") !== \"\") {\n                extractedText += `| ${rowString} |\\n`;\n            }\n        });\n        extractedText += \"\\n\";\n    });\n\n    results.push({\n        json: {\n            spreadsheetTitle: item.json.properties?.title,\n            cleanText: extractedText.trim()\n        }\n    });\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "665b1a49-3605-449a-9acc-c5dae81e9957",
      "name": "Convert the xlsx data to more readable format",
      "type": "n8n-nodes-base.code",
      "position": [
        2144,
        1504
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nlet extractedText = \"### Sheet: XLSX Data\\n\";\n\nif (items.length > 0) {\n    // Extract headers from the first row's keys\n    const headers = Object.keys(items[0].json);\n    extractedText += `| ${headers.join(\" | \")} |\\n`;\n    \n    // Process rows\n    items.forEach(item => {\n        const rowValues = headers.map(header => {\n            const val = item.json[header];\n            return (val !== null && val !== undefined) ? val : \"\";\n        });\n        const rowString = rowValues.join(\" | \");\n        \n        if (rowString.trim() !== \"\") {\n            extractedText += `| ${rowString} |\\n`;\n        }\n    });\n}\n\nreturn [{\n    json: {\n        spreadsheetTitle: \"XLSX Attachment\",\n        cleanText: extractedText.trim()\n    }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "74cda217-5fbc-4808-a339-c16dabd7ab3c",
      "name": "Keep only the attachment ID of .xlsx",
      "type": "n8n-nodes-base.set",
      "position": [
        1472,
        1504
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "3d299d85-7d56-451f-b86c-9a4bc97cec34",
              "name": "url",
              "type": "string",
              "value": "={{ $json.url.match(/\\/d\\/([a-zA-Z0-9-_]+)/)[1] }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "4e728863-0888-46c0-aa85-1a8cfa7f931d",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1168,
        1136
      ],
      "parameters": {
        "color": 7,
        "height": 432,
        "content": "## Native Sheets or .xlsx\nIf the attachment is a native Google Sheet, directly perform the API call.\n\nIf the file is a .xlsx file, download and extract the data and then return the values as the Google API call does not support it."
      },
      "typeVersion": 1
    },
    {
      "id": "703c715b-e4e6-47e3-a5fa-41023e09f18d",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -16,
        1712
      ],
      "parameters": {
        "width": 272,
        "height": 480,
        "content": "## Subworkflow : \n* Retrieving Google Sheet attachments\nThis Sheets API call will retrieve all attachments that match 'spreadsheets' and get the data.\n\nThe Google API cannot process .xlsx files so a different path will be taken there.\n\n\n* Retrieving Google Docs attachments\nThis API call will retrieve all attachments that match 'document' and get the data.\n\n* Retrieving Google Slides attachments\nThis API call will retrieve all attachments that match 'presentation' and get the data.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "c9dd2256-2021-42a9-9057-8617a4033847",
      "name": "Keep only the attachment ID of the Sheet",
      "type": "n8n-nodes-base.set",
      "position": [
        1696,
        1312
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "3d299d85-7d56-451f-b86c-9a4bc97cec34",
              "name": "url",
              "type": "string",
              "value": "={{ $json.url.match(/\\/d\\/([a-zA-Z0-9-_]+)/)[1] }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "4944021f-7422-4297-a7f5-fed0c08f603e",
      "name": "Only select specific spreadsheets",
      "type": "n8n-nodes-base.filter",
      "position": [
        1024,
        1408
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "41a944b7-6e32-4c01-b459-54d1d8c73f66",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.url }}",
              "rightValue": "spreadsheets"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "7cd22af0-af64-437c-9dca-de7b34803121",
      "name": "Only select specific document",
      "type": "n8n-nodes-base.filter",
      "position": [
        1008,
        1904
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "41a944b7-6e32-4c01-b459-54d1d8c73f66",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.url }}",
              "rightValue": "document"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "cfb16248-ffba-46ad-a08a-723c0845be03",
      "name": "Only select specific presentation",
      "type": "n8n-nodes-base.filter",
      "position": [
        1008,
        2224
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "41a944b7-6e32-4c01-b459-54d1d8c73f66",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.url }}",
              "rightValue": "presentation"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "157e6a8c-ca52-4b1f-86c2-a5eddf06f98c",
      "name": "Get the Userstory data",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        560,
        1904
      ],
      "parameters": {
        "url": "=https://<yoururl>/userstories/{{ $json.Userstory }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "oAuth2Api"
      },
      "typeVersion": 4.2
    },
    {
      "id": "6e167490-498f-4b43-9dd9-25c6dbd9e041",
      "name": "Iterate over the attachments",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        784,
        1904
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "details.attachmentList"
      },
      "typeVersion": 1
    },
    {
      "id": "7d1f2b3e-4425-4929-a7fd-a13a19ae4f4b",
      "name": "Keep only the attachment ID of document",
      "type": "n8n-nodes-base.set",
      "position": [
        1232,
        1904
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "3d299d85-7d56-451f-b86c-9a4bc97cec34",
              "name": "url",
              "type": "string",
              "value": "={{ $json.url.match(/\\/d\\/([a-zA-Z0-9-_]+)/)[1] }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "50b38cca-29cf-43b8-830c-85f701b959d0",
      "name": "Keep only the attachment ID of presentation",
      "type": "n8n-nodes-base.set",
      "position": [
        1232,
        2224
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "3d299d85-7d56-451f-b86c-9a4bc97cec34",
              "name": "url",
              "type": "string",
              "value": "={{ $json.url.match(/\\/d\\/([a-zA-Z0-9-_]+)/)[1] }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "7cf5d996-ad55-4e8e-a338-06b9f65ae772",
      "name": "Perform the API request with the ID of document",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Also slim down the response so only text will be returned, otherwise the response will be to large to handle.",
      "position": [
        1456,
        1904
      ],
      "parameters": {
        "url": "=https://docs.googleapis.com/v1/documents/{{ $json.url }}",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "fields",
              "value": "title,body(content(paragraph(elements(textRun(content))),table(tableRows(tableCells(content(paragraph(elements(textRun(content)))))))))"
            }
          ]
        },
        "nodeCredentialType": "googleDocsOAuth2Api"
      },
      "notesInFlow": true,
      "typeVersion": 4.3
    },
    {
      "id": "6db3a7a5-c5d0-4341-9e94-eb008e8e4c71",
      "name": "Perform the API request with the ID of presentation",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Also slim down the response so only text will be returned, otherwise the response will be to large to handle.",
      "position": [
        1456,
        2224
      ],
      "parameters": {
        "url": "=https://slides.googleapis.com/v1/presentations/{{ $json.url }}",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "fields",
              "value": "slides(pageElements(shape(text(textElements(textRun(content))))))"
            }
          ]
        },
        "nodeCredentialType": "googleSlidesOAuth2Api"
      },
      "notesInFlow": true,
      "typeVersion": 4.3
    },
    {
      "id": "0140946a-9909-4c13-8978-b06d047b5932",
      "name": "Convert the presentation to more readable format",
      "type": "n8n-nodes-base.code",
      "position": [
        1680,
        2224
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n    let outputText = \"\";\n    const slides = item.json.slides || [];\n\n    slides.forEach((slide, index) => {\n        let slideText = `--- Slide ${index + 1} ---\\n`;\n        let hasContent = false;\n        \n        const elements = slide.pageElements || [];\n        elements.forEach(element => {\n            if (element.shape && element.shape.text && element.shape.text.textElements) {\n                element.shape.text.textElements.forEach(te => {\n                    if (te.textRun && te.textRun.content) {\n                        const content = te.textRun.content.trim();\n                        if (content !== \"\") {\n                            slideText += content + \"\\n\";\n                            hasContent = true;\n                        }\n                    }\n                });\n            }\n        });\n        \n        if (hasContent) {\n            outputText += slideText + \"\\n\";\n        }\n    });\n\n    results.push({\n        json: {\n            presentationId: item.json.presentationId || \"unknown\",\n            formattedContent: outputText.trim()\n        }\n    });\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "3d7942ea-4643-4d45-8b2f-82c24320e366",
      "name": "Convert the document to more readable format",
      "type": "n8n-nodes-base.code",
      "position": [
        1680,
        1904
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst results = [];\n\nconst parseElements = (elements) => {\n  return elements\n    .map(el => el.textRun?.content || \"\")\n    .join(\"\");\n};\n\nconst parseContent = (contentArray) => {\n  let text = \"\";\n  for (const item of contentArray) {\n    if (item.paragraph) {\n      text += parseElements(item.paragraph.elements);\n    } else if (item.table) {\n      for (const row of item.table.tableRows) {\n        for (const cell of row.tableCells) {\n          text += parseContent(cell.content || []) + \" | \";\n        }\n        text += \"\\n\";\n      }\n    }\n  }\n  return text;\n};\n\nfor (const item of items) {\n  const bodyContent = item.json.body?.content || [];\n  const cleanText = parseContent(bodyContent);\n\n  results.push({\n    json: {\n      title: item.json.title,\n      documentId: item.json.documentId,\n      text: cleanText.replace(/\\r\\n/g, \"\\n\").trim()\n    }\n  });\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "b951582a-778b-496b-84af-2d610445b8d3",
      "name": "Perform the API request with the ID of sheet",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Also slim down the response so only text will be returned, otherwise the response will be to large to handle.",
      "position": [
        1920,
        1312
      ],
      "parameters": {
        "url": "=https://sheets.googleapis.com/v4/spreadsheets/{{ $json.url }}",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "fields",
              "value": "properties(title),sheets(properties(title),data(rowData(values(effectiveValue,formattedValue))))"
            }
          ]
        },
        "nodeCredentialType": "googleSheetsOAuth2Api"
      },
      "notesInFlow": true,
      "typeVersion": 4.3
    },
    {
      "id": "fdb496cd-3045-4166-851b-ca9b947a8404",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        2592,
        1888
      ],
      "parameters": {
        "numberInputs": 3
      },
      "typeVersion": 3.2
    },
    {
      "id": "c40bf273-0374-4633-b9d7-a9dbd05a404e",
      "name": "Call 'Get Attachments - Agile Studio US'",
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "position": [
        1504,
        544
      ],
      "parameters": {
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "mQ4yQw9JQw2eCmGt",
          "cachedResultUrl": "",
          "cachedResultName": ""
        },
        "workflowInputs": {
          "value": {
            "Userstory": "={{ $fromAI('Userstory', ``, 'string') }}"
          },
          "schema": [
            {
              "id": "Userstory",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Userstory",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Userstory"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "typeVersion": 2.2
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "29931438-4197-4b72-9e7b-5a814beb9921",
  "connections": {
    "Switch": {
      "main": [
        [
          {
            "node": "Keep only the attachment ID of the Sheet",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Keep only the attachment ID of .xlsx",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Sprint Goal Generator",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download file": {
      "main": [
        [
          {
            "node": "Extract from File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract from File": {
      "main": [
        [
          {
            "node": "Convert the xlsx data to more readable format",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge the results": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sprint Goal Generator": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get the Userstory data": {
      "main": [
        [
          {
            "node": "Iterate over the attachments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Sprint Goal Generator",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Retrieve Agile Studio US": {
      "ai_tool": [
        [
          {
            "node": "Sprint Goal Generator",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Retrieve_Data_From_Sheet": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Iterate over the attachments": {
      "main": [
        [
          {
            "node": "Only select specific document",
            "type": "main",
            "index": 0
          },
          {
            "node": "Only select specific spreadsheets",
            "type": "main",
            "index": 0
          },
          {
            "node": "Only select specific presentation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Only select specific document": {
      "main": [
        [
          {
            "node": "Keep only the attachment ID of document",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Only select specific presentation": {
      "main": [
        [
          {
            "node": "Keep only the attachment ID of presentation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Only select specific spreadsheets": {
      "main": [
        [
          {
            "node": "Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Executed by Another Workflow": {
      "main": [
        [
          {
            "node": "Get the Userstory data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Keep only the attachment ID of .xlsx": {
      "main": [
        [
          {
            "node": "Download file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Retrieve_Data_From_Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Keep only the attachment ID of document": {
      "main": [
        [
          {
            "node": "Perform the API request with the ID of document",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Call 'Get Attachments - Agile Studio US'": {
      "ai_tool": [
        [
          {
            "node": "Sprint Goal Generator",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Convert to sheet data to readable format": {
      "main": [
        [
          {
            "node": "Merge the results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Keep only the attachment ID of the Sheet": {
      "main": [
        [
          {
            "node": "Perform the API request with the ID of sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Keep only the attachment ID of presentation": {
      "main": [
        [
          {
            "node": "Perform the API request with the ID of presentation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert the document to more readable format": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Perform the API request with the ID of sheet": {
      "main": [
        [
          {
            "node": "Convert to sheet data to readable format",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert the xlsx data to more readable format": {
      "main": [
        [
          {
            "node": "Merge the results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Perform the API request with the ID of document": {
      "main": [
        [
          {
            "node": "Convert the document to more readable format",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert the presentation to more readable format": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Perform the API request with the ID of presentation": {
      "main": [
        [
          {
            "node": "Convert the presentation to more readable format",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Based on the Google Sheet data, the AI will retrieve the userstories ID's, retrieves the userstory data and the corresponding attachments and creates sprint goals according to the defined system prompt.

Source: https://n8n.io/workflows/13602/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Who is this for? Agencies, consultants, and service providers who conduct discovery calls and need to quickly turn conversations into professional proposals.

Tool Think, Tool Calculator, Agent Tool +18
AI & RAG

This workflow is designed for marketers, content creators, agencies, and solo founders who want to publish long‑form posts with visuals on autopilot using n8n and AI agents. ​

Tool Http Request, Agent, HTTP Request +27
AI & RAG

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

Output Parser Structured, Telegram, N8N Nodes Tesseractjs +14
AI & RAG

This workflow is a fully automated YouTube Shorts production pipeline. It takes the structured output from a video digestion workflow (transcript, key moments, metadata) and produces finished, rendere

HTTP Request, Google Drive, Execute Workflow Trigger +5
AI & RAG

🤖🧑‍💻 AI Agent for Top n8n Creators Leaderboard Reporting. Uses httpRequest, lmChatOpenAi, executeWorkflowTrigger, toolWorkflow. Event-driven trigger; 49 nodes.

HTTP Request, OpenAI Chat, Execute Workflow Trigger +8