{
  "id": "m4oSNHMZeivOzH27",
  "meta": {
    "builderVariant": "mcp",
    "aiBuilderAssisted": true
  },
  "name": "Reusable AI summarise sub-workflow you can call from any workflow",
  "tags": [],
  "nodes": [
    {
      "id": "b97454a0-8f7f-4412-8285-bd8cc37563b3",
      "name": "Called by Another Workflow",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        -16,
        32
      ],
      "parameters": {
        "workflowInputs": {
          "values": [
            {
              "name": "text"
            },
            {
              "name": "language"
            },
            {
              "name": "audience"
            },
            {
              "name": "maxWords",
              "type": "number"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "85afa8c9-0d2c-4d30-8949-40949e8995c6",
      "name": "Apply Defaults",
      "type": "n8n-nodes-base.code",
      "position": [
        208,
        32
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const i = $json;\nconst text = String(i.text || '').trim();\nreturn {\n  text: text,\n  hasText: text.length > 0,\n  charCount: text.length,\n  language: i.language || 'English',\n  audience: i.audience || 'General business audience',\n  maxWords: Number(i.maxWords) > 0 ? Number(i.maxWords) : 80\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "d910e00c-e888-4fc4-b2ad-ee82b77e6bbb",
      "name": "Has Text",
      "type": "n8n-nodes-base.if",
      "position": [
        432,
        32
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.hasText }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "9337b4f4-32dd-4f7c-885c-ce18b767c154",
      "name": "Summarise with Gemini",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "onError": "continueRegularOutput",
      "position": [
        896,
        16
      ],
      "parameters": {
        "text": "=Summarise the text below for a {{ $json.audience }} in {{ $json.language }}, in at most {{ $json.maxWords }} words. Return a plain-language summary, 3-5 key bullet points, the overall tone of the original (positive, neutral or negative), and your confidence (high, medium or low) in whether the text was clear enough to summarise faithfully. Never add facts that are not present.\n\nText:\n{{ $json.text }}",
        "batching": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "c26618ea-ced0-4105-bd52-c66eb6c42225",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        896,
        256
      ],
      "parameters": {
        "options": {
          "temperature": 0.3
        },
        "modelName": "models/gemini-3.1-flash-lite"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "099d0d26-7eeb-42ce-abf2-ac17da6ba269",
      "name": "Summary Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1072,
        256
      ],
      "parameters": {
        "jsonSchemaExample": "{\"summary\":\"A short plain-language summary\",\"bullets\":[\"First key point\",\"Second key point\"],\"tone\":\"neutral\",\"confidence\":\"high\"}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "42726b2d-dc64-4bb4-ae70-5222c1c36722",
      "name": "Return Summary",
      "type": "n8n-nodes-base.code",
      "position": [
        1424,
        16
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const src = $json.output || {};\nconst meta = $('Apply Defaults').item.json;\nconst bullets = Array.isArray(src.bullets) ? src.bullets : [];\nreturn {\n  ok: true,\n  summary: src.summary || '',\n  bullets: bullets,\n  bulletText: bullets.map(function (b) { return '- ' + b; }).join('\\n'),\n  tone: String(src.tone || 'neutral').toLowerCase(),\n  confidence: String(src.confidence || 'medium').toLowerCase(),\n  language: meta.language,\n  sourceChars: meta.charCount,\n  error: ''\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "9dc57aa7-e97f-4bdc-a4fd-7f260f143560",
      "name": "Return Empty Error",
      "type": "n8n-nodes-base.code",
      "position": [
        688,
        256
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "return { ok: false, summary: '', bullets: [], bulletText: '', tone: '', confidence: '', language: $json.language, sourceChars: 0, error: 'No text was supplied to summarise.' };"
      },
      "typeVersion": 2
    },
    {
      "id": "988f726f-5433-4bbf-9522-572fd6f88c2d",
      "name": "Overview Sticky",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -816,
        -144
      ],
      "parameters": {
        "width": 724,
        "height": 732,
        "content": "## Reusable AI summarise sub-workflow you can call from any workflow\n\n### How it works\nMost teams end up pasting the same summarising prompt into a dozen workflows, then have to fix them all when the wording changes. This template is the opposite: one shared building block that other workflows call, like an internal API.\n\nIt starts with an Execute Sub-workflow Trigger that declares a clear contract - text, language, audience and maxWords - so any calling workflow sees exactly what to pass. Defaults are applied for anything omitted, empty input is rejected up front with a structured error rather than a crash, and a Basic LLM Chain with Google Gemini returns a summary, key bullets, the tone of the original and a confidence rating so the caller can decide whether to trust it.\n\nEvery path returns the same shape - ok, summary, bullets, bulletText, tone, confidence, error - so callers can branch on ok without guessing. Change the prompt once here and every workflow that calls it improves.\n\n### Setup\n1. Connect the Google Gemini (PaLM) API credential.\n2. Save and activate this workflow.\n3. In any other workflow, add an Execute Sub-workflow node, select this workflow, and map text (plus optional language, audience and maxWords).\n\n### Customization tips\nAdd a style parameter for formal or casual output, or a second chain that translates the summary."
      },
      "typeVersion": 1
    },
    {
      "id": "385fe129-8d40-4007-87f7-8e0179a36b88",
      "name": "S1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 652,
        "height": 620,
        "content": "## 1. The contract\nThe Execute Sub-workflow Trigger declares the inputs callers must pass: text, language, audience and maxWords. Defaults fill in anything omitted, and empty text is rejected before any AI call is made."
      },
      "typeVersion": 1
    },
    {
      "id": "04a16c4b-53e6-491b-8d5a-574d7ef16cd7",
      "name": "S2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        592,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 608,
        "height": 620,
        "content": "## 2. Summarise (Basic LLM Chain)\nGemini returns the summary, key bullets, the tone of the original and a confidence rating, so the caller can judge whether to use it."
      },
      "typeVersion": 1
    },
    {
      "id": "312f74ea-48bd-4a42-94ac-d698ec8609b4",
      "name": "S3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1232,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 620,
        "content": "## 3. One consistent response shape\nSuccess and failure both return ok, summary, bullets, bulletText, tone, confidence and error - so calling workflows can simply branch on ok."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": true,
    "executionOrder": "v1"
  },
  "versionId": "02c02739-da0e-4974-bb41-dee714fe4313",
  "nodeGroups": [],
  "connections": {
    "Has Text": {
      "main": [
        [
          {
            "node": "Summarise with Gemini",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Return Empty Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Apply Defaults": {
      "main": [
        [
          {
            "node": "Has Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Summary Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Summarise with Gemini",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Summarise with Gemini": {
      "main": [
        [
          {
            "node": "Return Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Summarise with Gemini",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Called by Another Workflow": {
      "main": [
        [
          {
            "node": "Apply Defaults",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}