AutomationFlowsEmail & Gmail › Synthesize and Compare Multiple LLM Responses with Openrouter Council

Synthesize and Compare Multiple LLM Responses with Openrouter Council

ByUlf Morys @syrom on n8n.io

This template adapts Andrej Karpathy’s LLM Council concept for use in n8n, creating a workflow that collects, evaluates, and synthesizes multiple large language model (LLM) responses to reduce individual model bias and improve answer quality.

Chat trigger trigger★★★★☆ complexityAI-powered26 nodesChat TriggerHTTP RequestEmail Send
Email & Gmail Trigger: Chat trigger Nodes: 26 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Chat Trigger → HTTP Request 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": "sYEXpXSAAF75tWKC",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "LLM Council",
  "tags": [],
  "nodes": [
    {
      "id": "9e8c8e51-b1e8-431b-b104-675d4bb2cc57",
      "name": "Initialize Variables",
      "type": "n8n-nodes-base.set",
      "position": [
        224,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "user-query",
              "name": "userQuery",
              "type": "string",
              "value": "={{ $json.chatInput }}"
            },
            {
              "id": "council-models",
              "name": "councilModels",
              "type": "array",
              "value": "=[\"openai/gpt-4o\", \"google/gemini-2.5-flash\", \"anthropic/claude-sonnet-4.5\",\"perplexity/sonar-pro-search\"]"
            },
            {
              "id": "chairman-model",
              "name": "chairmanModel",
              "type": "string",
              "value": "google/gemini-2.5-flash"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "11432589-2dd5-42c5-9a05-d85b7908fd23",
      "name": "Split by Model",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        368,
        0
      ],
      "parameters": {
        "include": "={{ $json.userQuery }}",
        "options": {},
        "fieldToSplitOut": "councilModels"
      },
      "typeVersion": 1
    },
    {
      "id": "f304d235-b1a1-41b2-88ef-15a3fa53123c",
      "name": "When chat message received",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        64,
        0
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.4
    },
    {
      "id": "234da11b-e5f3-49a2-a5f7-502a9d713b9e",
      "name": "Stage 1: Query Model Answers",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        544,
        0
      ],
      "parameters": {
        "url": "https://openrouter.ai/api/v1/chat/completions",
        "body": "={{   JSON.stringify({     model: $json.councilModels,     messages: [       {         role: \"user\",         content: $('Initialize Variables').item.json.userQuery       }     ]   }) }}",
        "method": "POST",
        "options": {
          "timeout": 120000
        },
        "sendBody": true,
        "contentType": "raw",
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "rawContentType": "application/json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "openRouterApi"
      },
      "typeVersion": 4.2
    },
    {
      "id": "c00798aa-8e82-453e-9030-3e875a5d1ec6",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        -304
      ],
      "parameters": {
        "color": 7,
        "width": 496,
        "height": 624,
        "content": "## INPUT and INITIALIZATION\n- Ask the question\n- Initialize the models"
      },
      "typeVersion": 1
    },
    {
      "id": "19faade7-71a3-493c-8d77-7bcc3b7ddfe4",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        496,
        -304
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 624,
        "content": "## Stage 1: Individual Model Responses\n- Feed user query to **all** Council Member Models\n- Collect the Model responses  from **all** Council Member Models"
      },
      "typeVersion": 1
    },
    {
      "id": "f78c2ed3-b1a7-42e0-8a9d-4ed0c2e4df36",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        976,
        -304
      ],
      "parameters": {
        "color": 7,
        "width": 1328,
        "height": 624,
        "content": "## Stage 2: Response Evaluation and Ranking\n- **Anonymize model responses**\n- Ask models to evaluate and rank the answers"
      },
      "typeVersion": 1
    },
    {
      "id": "e61dbdc2-87d9-438e-a732-dbe74fd63467",
      "name": "Stage 2: Query Model Answer Rankings",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1776,
        0
      ],
      "parameters": {
        "url": "https://openrouter.ai/api/v1/chat/completions",
        "body": "={{   JSON.stringify({     model: $json.councilModels,     messages: [       {         role: \"user\",         content: $json.rankingPrompt       }     ]   }) }}",
        "method": "POST",
        "options": {
          "timeout": 120000
        },
        "sendBody": true,
        "contentType": "raw",
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "rawContentType": "application/json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "openRouterApi"
      },
      "typeVersion": 4.2
    },
    {
      "id": "dd5219c2-c4a0-4f46-aa12-21114a02a92a",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1040,
        368
      ],
      "parameters": {
        "color": 7,
        "width": 736,
        "height": 624,
        "content": "## Stage 3: The Chairman's verdict\n- The Chairman model synthesizes the Council's result\n"
      },
      "typeVersion": 1
    },
    {
      "id": "33fdeb1d-bfed-4d24-aa7f-e5bc604c3369",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1744,
        368
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 624,
        "content": "## Output\n- Build a result report (as mail body) with:\n-- the initial query\n-- the Chairman verdict \n-- the Ranking\n-- the individual model answers"
      },
      "typeVersion": 1
    },
    {
      "id": "8e66ab1a-49c6-4f06-a344-5982824b6125",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        368
      ],
      "parameters": {
        "width": 992,
        "height": 624,
        "content": "## How it works:\nThis workflow is inspired by a vibe coding project of Andrej Karpathy: https://github.com/karpathy/llm-council .\nThe LLM Council serves as a moderation board to synthesize different LLM responses to the same prompt.\n- Stage 1: The same question / user query is answered by different LLMs, the \"Council Members\".\n- Stage 2: The answers are anonymized and then the same models must judge and rank all responses.\n- Stage 3: All this (the individual answers and the judgments and rankings of the models on their answers) is forwarded to a \"Council Chairman\" who synthesizes an overall answer (the Verdict) out of this input.\n- Besides this \"Chairman Verdict\", all other essential information is integrated in the output:\n\t- The original query\n\t- The Chairman Verdict\n\t- The ranking of each model for all responses\n\t- The original query responses of each model\n\n\n\n## Setup steps:\n1. Set up openRouter Credential:\n**Configure it in each of the HTTP Request nodes of Stage 1, 2 and 3.**\n2. Initialize the model variables in the node of the same name:\n**Use any model from https://openrouter.ai/models.**\n2a) councilModels -> Council Member LLMs:\n**All models that are asked to respond to the input query and subsequently evaluate and rank all responses.**\n2b) chairmanModel -> the Council Chairman LLM:\n**The model to summarize and issue the Council's verdict.**\n3. Define your mail output node:\n**You must have access to an SMTP mailbox and know the mail address you want to send the output to.**\n4. Start the chatTrigger to send your query to the LLM council.\n5. Check the workflow result in the configured mailbox.\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "9ed93ba9-221e-40e0-8c03-5a6b33051eee",
      "name": "Stage 3: Chairman Synthesis",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1616,
        672
      ],
      "parameters": {
        "url": "https://openrouter.ai/api/v1/chat/completions",
        "body": "={{   JSON.stringify({     model: $json.chairmanModel,     messages: [       {         role: \"user\",         content: $json.chairmanPrompt       }     ]   }) }}",
        "method": "POST",
        "options": {
          "timeout": 120000
        },
        "sendBody": true,
        "contentType": "raw",
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "rawContentType": "application/json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "openRouterApi"
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "91f0f387-f9d5-4e46-a70b-202f9c17df0e",
      "name": "Stage 1: Extract Responses",
      "type": "n8n-nodes-base.set",
      "position": [
        704,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "extract-response",
              "name": "model",
              "type": "string",
              "value": "={{ $json.model }}"
            },
            {
              "id": "extract-content",
              "name": "response",
              "type": "string",
              "value": "={{ $json.choices[0].message.content }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "2e37b91f-b4da-4976-842c-e8e223242b36",
      "name": "Stage 1: Aggregate Responses",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        848,
        0
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "39f7355c-db9c-437a-8037-a8700515aa37",
      "name": "Stage 2: Create Anonymized Responses",
      "type": "n8n-nodes-base.set",
      "position": [
        1040,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "create-labels",
              "name": "labeledResponses",
              "type": "array",
              "value": "={{ JSON.stringify(   $json.data.map((item, index) => ({     label: String.fromCharCode(65 + index),     model: item.model,     response: item.response,   })) ) }}"
            },
            {
              "id": "anonymized-text",
              "name": "anonymizedText",
              "type": "string",
              "value": "={{ $json.data\n  .map((item, index) => `Response ${String.fromCharCode(65 + index)}:\\n${item.response}`)\n  .join('\\n\\n') }}\n"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "06fd85e8-2ff1-4bb6-9110-8666d1568fb5",
      "name": "Stage 2: Build Ranking Prompt",
      "type": "n8n-nodes-base.set",
      "position": [
        1232,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ranking-prompt",
              "name": "=rankingPrompt",
              "type": "string",
              "value": "={{\n`You are evaluating different responses to the following question:\n\nQuestion:\n${$('Initialize Variables').first().json.userQuery}\n\nHere are the responses from different models (anonymized):\n\n${$json.anonymizedText}\nYour task:\n1. First, evaluate each response individually. For each response, explain what it does well and what it does poorly.\n2. Then, at the very end of your response, provide a final ranking. \n\nIMPORTANT: Your final ranking MUST be formatted EXACTLY as follows:\n- Start with the line \"FINAL RANKING:\" (all caps, with colon)\n- Then list the responses from best to worst as a numbered list \n- Each line should be: number, period, space, then ONLY the response label (e.g., \"1. Response A\") \n- Do not add any other text or explanations in the ranking section \n\nExample of the correct format for your ENTIRE response: \nResponse A provides good detail on X but misses Y... \nResponse B is accurate but lacks depth on Z... \nResponse C offers the most comprehensive answer...  \n\nFINAL RANKING:\n1. Response C \n2. Response A \n3. Response B  \n\nNow provide your evaluation and ranking:`\n}}\n"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "28fd25b9-b44f-4617-99aa-4947d449cc0b",
      "name": "Stage 2: Re-Add councilModels",
      "type": "n8n-nodes-base.set",
      "position": [
        1408,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "545b8760-cb12-4118-9632-fdeac63a457e",
              "name": "rankingPrompt",
              "type": "string",
              "value": "={{ $json.rankingPrompt }}"
            },
            {
              "id": "cff5bee4-58ef-4925-b23c-9d3fc81e3edf",
              "name": "councilModels",
              "type": "array",
              "value": "={{ $('Initialize Variables').item.json.councilModels }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "99a510c0-64b2-49b2-93ac-a28a3836ddfb",
      "name": "Stage 2: rankingPrompt per LLM",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1584,
        0
      ],
      "parameters": {
        "include": "allOtherFields",
        "options": {},
        "fieldToSplitOut": "councilModels"
      },
      "typeVersion": 1
    },
    {
      "id": "ba8e9264-c6a3-474d-af2b-73e10db73a4e",
      "name": "Stage 2: Extract Rankings",
      "type": "n8n-nodes-base.set",
      "position": [
        1936,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ranking-model",
              "name": "model",
              "type": "string",
              "value": "={{ $json.model }}"
            },
            {
              "id": "ranking-content",
              "name": "ranking",
              "type": "string",
              "value": "={{ $json.choices[0].message.content }}"
            },
            {
              "id": "parse-ranking",
              "name": "parsedRanking",
              "type": "array",
              "value": "={{ $json.choices[0].message.content.split('FINAL RANKING:')[1]?.match(/Response [A-Z]/g) || [] }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f7abd792-9809-4b5a-bc53-4186f63b28be",
      "name": "Stage 3: Build ChairmanPrompt Part 1",
      "type": "n8n-nodes-base.set",
      "position": [
        1264,
        672
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "stage1-text",
              "name": "stage1Text",
              "type": "string",
              "value": "={{ ($('Stage 1: Aggregate Responses').item.json.data || $('Stage 1: Aggregate Responses').item.json[0].data).map(r => `Model: ${r.model}\\nResponse: ${r.response}`).join('\\n\\n') }}"
            },
            {
              "id": "stage2-text",
              "name": "stage2Text",
              "type": "string",
              "value": "={{ $json.stage2Results[0].data.map(r => `Model: ${r.model}\\nRanking: ${r.ranking}`).join('\\n\\n') }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "0566f6cf-1c1a-41ff-9dee-27387305c98c",
      "name": "Stage 3: Build Chairman Prompt Part 2",
      "type": "n8n-nodes-base.set",
      "position": [
        1440,
        672
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "chairman-prompt",
              "name": "=chairmanPrompt",
              "type": "string",
              "value": "=You are the Chairman of an LLM Council. Multiple AI models have provided responses to a user's question, and then ranked each other's responses.\n\n# Original Question: {{ $('Initialize Variables').item.json.userQuery }}\n\n# STAGE 1 - Individual Responses from each model:\n{{ $json.stage1Text }}\n\n# STAGE 2 - Peer Rankings from each model\n{{ $json.stage2Text }}\n\n# Your TASK\nAs the Chairman of the LLM council, you must synthesize all of this information into a single, comprehensive, accurate answer to the user's original question. Consider:\n- The individual responses and their insights\n- The peer rankings and what they reveal about response quality\n- Any patterns of agreement or disagreement\n\nProvide a clear, well-reasoned final answer that represents the council's collective wisdom:"
            },
            {
              "id": "c9e0da1c-18c6-42ac-9f9a-cee2c35146bf",
              "name": "chairmanModel",
              "type": "string",
              "value": "={{ $('Initialize Variables').item.json.chairmanModel }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "cdaa1b7e-2d8d-4610-9d4e-0f366286401a",
      "name": "Stage 4: Format Output Part 1",
      "type": "n8n-nodes-base.set",
      "position": [
        1792,
        672
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "chairman-model-used",
              "name": "chairmanModel",
              "type": "string",
              "value": "={{ $('Initialize Variables').item.json.chairmanModel }}"
            },
            {
              "id": "final-response",
              "name": "finalResponse",
              "type": "string",
              "value": "={{ $json.choices[0].message.content }}"
            },
            {
              "id": "aggregate-rankings",
              "name": "aggregateRankings",
              "type": "string",
              "value": "={{ $('Stage 3: Calculate Aggregate Rankings').item.json.aggregateRankings }}"
            },
            {
              "id": "stage1-responses",
              "name": "stage1Responses",
              "type": "string",
              "value": "={{ $('Stage 1: Aggregate Responses').item.json }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8891adea-9665-4813-8068-564b873c8138",
      "name": "Stage 4: Format Output Part 2",
      "type": "n8n-nodes-base.set",
      "position": [
        1984,
        672
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "90ea0f47-c094-4dcc-8a22-3375b4c3e532",
              "name": "MailBody",
              "type": "string",
              "value": "={{\n`You are evaluating different responses to the following question:\n##############\nQuestion:\n##############\n${$('Initialize Variables').first().json.userQuery}\n---------------------------------------\n##############\nFINAL RESPONSE\n##############\nof the chairman model ( ${$json.chairmanModel} ) is:\n\n${$json.finalResponse}\n\n---------------------------------------\n##############\nRANKINGS\n##############\n\nThis was the aggregated ranking of the models' mutual evaluation that has guided the chairman model (lower ranking is better):\n\n${$('Stage 3: Calculate Aggregate Rankings').first().json.aggregateRankings.map(r => 'Model: ' + r.model + '\\nAverage Rank: ' + r.averageRank + '\\nRankings Count: ' + r.rankingsCount).join('\\n\\n------\\n\\n')}\n\nbased on the following per-model-ranking:\n\n${$('Stage 2: Aggregate').first().json.data.map(r => 'Model: ' + r.model + '\\nRanked:\\n' + r.parsedRanking.map((resp, i) => (i + 1) + '. ' + resp).join('\\n')).join('\\n\\n------\\n\\n')}\n\n\n---------------------------------------\n####################\nINDIV. MODEL ANSWERS\n####################\nFor reference: these were the individual responses from each different models:\n\n${$('Stage 2: Create Anonymized Responses').first().json.labeledResponses.map(r => 'Response ' + r.label + ' (' + r.model + '):\\n' + r.response).join('\\n\\n------------\\n\\n')}\n\n`\n}}\n"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "05670818-5ce9-4f61-8cde-4c2b2e41abf5",
      "name": "Stage 4: Send Result per Email",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        2176,
        672
      ],
      "parameters": {
        "text": "={{ $json.MailBody }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "=LLM-Council-Resultat vom: {{ new Date().toLocaleDateString('en-GB').replace(/\\//g, '-') }}\n",
        "toEmail": "user@example.com",
        "fromEmail": "user@example.com",
        "emailFormat": "text"
      },
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "4d1c1bb1-655f-427e-89fc-dddc7cc19bf6",
      "name": "Stage 2: Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        2112,
        0
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "be8a9bc5-b8d6-4ea2-8470-8f648727bed6",
      "name": "Stage 3: Calculate Aggregate Rankings",
      "type": "n8n-nodes-base.code",
      "position": [
        1088,
        672
      ],
      "parameters": {
        "jsCode": "// Calculate aggregate rankings\nconst stage2Results = $input.all();\nconst labeledResponses = $('Stage 2: Create Anonymized Responses').item.json.labeledResponses;\n\n// Create label to model mapping\nconst labelToModel = {};\nlabeledResponses.forEach(item => {\n  labelToModel[`Response ${item.label}`] = item.model;\n});\n\n// Track positions for each model\nconst modelPositions = {};\n\nstage2Results.forEach(ranking => {\n  // Access the data array first\n  const dataArray = ranking.json.data;\n  \n  // Iterate through each ranking in the data array\n  dataArray.forEach(rankingData => {\n    const parsedRanking = rankingData.parsedRanking;\n    \n    parsedRanking.forEach((label, index) => {\n      const position = index + 1;\n      const modelName = labelToModel[label];\n      \n      if (modelName) {\n        if (!modelPositions[modelName]) {\n          modelPositions[modelName] = [];\n        }\n        modelPositions[modelName].push(position);\n      }\n    });\n  });\n});\n\n// Calculate average rankings\nconst aggregateRankings = Object.entries(modelPositions).map(([model, positions]) => {\n  const avgRank = positions.reduce((a, b) => a + b, 0) / positions.length;\n  return {\n    model: model,\n    averageRank: Math.round(avgRank * 100) / 100,\n    rankingsCount: positions.length\n  };\n});\n\n// Sort by average rank (lower is better)\naggregateRankings.sort((a, b) => a.averageRank - b.averageRank);\n\nreturn {\n  json: {\n    aggregateRankings: aggregateRankings,\n    labelToModel: labelToModel,\n    stage2Results: stage2Results.map(r => r.json)\n  }\n};"
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "a134c2b7-eb0d-4c41-b072-2909c1fcfe7a",
  "connections": {
    "Split by Model": {
      "main": [
        [
          {
            "node": "Stage 1: Query Model Answers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 2: Aggregate": {
      "main": [
        [
          {
            "node": "Stage 3: Calculate Aggregate Rankings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Initialize Variables": {
      "main": [
        [
          {
            "node": "Split by Model",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 2: Extract Rankings": {
      "main": [
        [
          {
            "node": "Stage 2: Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 1: Extract Responses": {
      "main": [
        [
          {
            "node": "Stage 1: Aggregate Responses",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When chat message received": {
      "main": [
        [
          {
            "node": "Initialize Variables",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 3: Chairman Synthesis": {
      "main": [
        [
          {
            "node": "Stage 4: Format Output Part 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 1: Aggregate Responses": {
      "main": [
        [
          {
            "node": "Stage 2: Create Anonymized Responses",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 1: Query Model Answers": {
      "main": [
        [
          {
            "node": "Stage 1: Extract Responses",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 2: Build Ranking Prompt": {
      "main": [
        [
          {
            "node": "Stage 2: Re-Add councilModels",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 2: Re-Add councilModels": {
      "main": [
        [
          {
            "node": "Stage 2: rankingPrompt per LLM",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 4: Format Output Part 1": {
      "main": [
        [
          {
            "node": "Stage 4: Format Output Part 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 4: Format Output Part 2": {
      "main": [
        [
          {
            "node": "Stage 4: Send Result per Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 2: rankingPrompt per LLM": {
      "main": [
        [
          {
            "node": "Stage 2: Query Model Answer Rankings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 2: Create Anonymized Responses": {
      "main": [
        [
          {
            "node": "Stage 2: Build Ranking Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 2: Query Model Answer Rankings": {
      "main": [
        [
          {
            "node": "Stage 2: Extract Rankings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 3: Build ChairmanPrompt Part 1": {
      "main": [
        [
          {
            "node": "Stage 3: Build Chairman Prompt Part 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 3: Build Chairman Prompt Part 2": {
      "main": [
        [
          {
            "node": "Stage 3: Chairman Synthesis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 3: Calculate Aggregate Rankings": {
      "main": [
        [
          {
            "node": "Stage 3: Build ChairmanPrompt Part 1",
            "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

This template adapts Andrej Karpathy’s LLM Council concept for use in n8n, creating a workflow that collects, evaluates, and synthesizes multiple large language model (LLM) responses to reduce individual model bias and improve answer quality.

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

More Email & Gmail workflows → · Browse all categories →

Related workflows

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

Email & Gmail

"I used to spend hours every week just copy-pasting product descriptions to find the right tariff codes for our international shipments. It was tedious and prone to errors." - Accounting specialist.

Chat Trigger, HTTP Request, Google Sheets +1
Email & Gmail

Paste any competitor's YouTube URL in chat — and this n8n workflow does everything automatically. WayinVideo API reads the entire video, extracts the summary, key highlights with timestamps, and hasht

HTTP Request, Gmail, Chat Trigger
Email & Gmail

In this workflow, we augment the original prompt using the InfraNodus GraphRAG system that will extract a reasoning ontology from a graph that you create (or that you can copy from our repository of p

Chat Trigger, HTTP Request
Email & Gmail

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

Chat Trigger, @Telepilotco/N8N Nodes Telepilot, Telegram
Email & Gmail

⚠️ COMMUNITY TEMPLATE DISCLAIMER: This is a community-contributed template that uses ScrapeGraphAI (a community node). Please ensure you have the ScrapeGraphAI community node installed in your n8n ins

N8N Nodes Scrapegraphai, HTTP Request, Email Send +1