This workflow corresponds to n8n.io template #18120 — we link there as the canonical source.
This workflow follows the Chainllm → 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 →
{
"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
}
]
]
}
}
}
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.
googlePalmApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This reusable sub-workflow is called from other n8n workflows to summarise provided text using Google Gemini, returning a consistent JSON response with a plain-language summary, key bullet points, tone, confidence, and error handling. Receives input from another workflow with…
Source: https://n8n.io/workflows/18120/ — 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.
Content - Newsletter Agent. Uses formTrigger, chainLlm, outputParserStructured, httpRequest. Event-driven trigger; 91 nodes.
Host Your Own AI Deep Research Agent with n8n, Apify and OpenAI. Uses outputParserStructured, lmChatOpenAi, formTrigger, chainLlm. Event-driven trigger; 87 nodes.
This template attempts to replicate OpenAI's DeepResearch feature which, at time of writing, is only available to their pro subscribers.
Any-File2Json-Converter. Uses chainLlm, lmChatGroq, outputParserStructured, executeWorkflowTrigger. Event-driven trigger; 30 nodes.
A friendly, practical tool that makes working with AppSheet data simpler and more efficient. This workflow is your go-to helper for building precise queries without getting lost in a sea of different