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 →
{
"name": "Agent Swarm - Main Orchestrator",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "agent-swarm",
"responseMode": "responseNode",
"options": {}
},
"id": "webhook-node",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
250,
300
]
},
{
"parameters": {
"jsCode": "// Extract and structure input from webhook\nconst body = $input.item.json.body || $input.item.json;\n\nreturn {\n json: {\n task: body.task || '',\n context: body.context || {},\n preferences: body.preferences || {},\n user_id: body.context?.user_id || 'anonymous',\n timestamp: new Date().toISOString()\n }\n};"
},
"id": "set-input",
"name": "Set Input",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
450,
300
]
},
{
"parameters": {
"url": "=https://api.openai.com/v1/chat/completions",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": []
},
"specifyBody": "json",
"jsonBody": "={\n \"model\": \"gpt-4o\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"Du bist der ORCHESTRATOR im Agent-Swarm-System f\u00fcr KI-Automatisierung.\\n\\nROLLE:\\nDu steuerst die Arbeit der anderen Agenten (Builder, Reviewer, Documenter).\\nDu zerlegst komplexe Aufgaben in klare Teilaufgaben und weist sie den richtigen Agenten zu.\\n\\nAUFGABEN:\\n1. Verstehe das Ziel oder Problem des Nutzers\\n2. Zerlege komplexe Aufgaben in klare Teilaufgaben\\n3. Entscheide, welcher Agent welche Teilaufgabe \u00fcbernimmt:\\n - BUILDER: Technische Umsetzung (Code, Skripte, Workflows)\\n - REVIEWER: Qualit\u00e4tskontrolle (Pr\u00fcfung, Fehlererkennung)\\n - DOCUMENTER: Dokumentation (Zusammenfassung, Strukturierung)\\n4. Priorisiere die Aufgaben\\n5. Erstelle eine klare Zusammenfassung\\n\\nOUTPUT-FORMAT (JSON, zwingend einhalten):\\n{\\n \\\"task_breakdown\\\": [\\n {\\n \\\"subtask_id\\\": 1,\\n \\\"subtask\\\": \\\"Kurze Beschreibung\\\",\\n \\\"agent\\\": \\\"builder|reviewer|documenter\\\",\\n \\\"priority\\\": 1,\\n \\\"description\\\": \\\"Detaillierte Beschreibung\\\"\\n }\\n ],\\n \\\"summary\\\": \\\"Zusammenfassung\\\",\\n \\\"estimated_time\\\": \\\"X Minuten\\\",\\n \\\"requires_parallel\\\": true\\n}\\n\\nAntworte NUR mit validem JSON, keine zus\u00e4tzlichen Erkl\u00e4rungen.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"=Task: {{ $json.task }}\\nContext: {{ JSON.stringify($json.context) }}\"\n }\n ],\n \"temperature\": 0.3,\n \"response_format\": { \"type\": \"json_object\" }\n}",
"options": {}
},
"id": "orchestrator-llm",
"name": "Orchestrator LLM",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
650,
300
],
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// Parse LLM Response and extract task breakdown\nconst response = $input.item.json;\nlet content;\n\ntry {\n // Handle OpenAI API response format\n if (response.choices && response.choices[0]) {\n content = JSON.parse(response.choices[0].message.content);\n } else if (response.content) {\n content = typeof response.content === 'string' ? JSON.parse(response.content) : response.content;\n } else {\n content = response;\n }\n} catch (e) {\n throw new Error(`Failed to parse LLM response: ${e.message}`);\n}\n\n// Validate structure\nif (!content.task_breakdown || !Array.isArray(content.task_breakdown)) {\n throw new Error('Invalid response format: missing task_breakdown array');\n}\n\nreturn {\n json: {\n task_breakdown: content.task_breakdown,\n summary: content.summary || '',\n estimated_time: content.estimated_time || 'unknown',\n requires_parallel: content.requires_parallel || false,\n original_task: $('Set Input').item.json.task,\n context: $('Set Input').item.json.context\n }\n};"
},
"id": "parse-orchestrator",
"name": "Parse Orchestrator",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
850,
300
]
},
{
"parameters": {
"mode": "splitInBatches",
"batchSize": 1,
"options": {}
},
"id": "split-tasks",
"name": "Split Tasks",
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
1050,
300
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "current-subtask",
"name": "current_subtask",
"value": "={{ $json.task_breakdown[$json.item] }}",
"type": "object"
},
{
"id": "agent-type",
"name": "agent_type",
"value": "={{ $json.task_breakdown[$json.item].agent }}",
"type": "string"
}
]
},
"options": {}
},
"id": "set-current-task",
"name": "Set Current Task",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1250,
300
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "builder-case",
"leftValue": "={{ $json.agent_type }}",
"rightValue": "builder",
"operator": {
"type": "string",
"operation": "equals"
}
},
{
"id": "reviewer-case",
"leftValue": "={{ $json.agent_type }}",
"rightValue": "reviewer",
"operator": {
"type": "string",
"operation": "equals"
}
},
{
"id": "documenter-case",
"leftValue": "={{ $json.agent_type }}",
"rightValue": "documenter",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "or"
},
"options": {}
},
"id": "route-agent",
"name": "Route to Agent",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [
1450,
300
]
},
{
"parameters": {
"workflowId": "agent-builder",
"source": "database",
"options": {}
},
"id": "call-builder",
"name": "Call Builder Agent",
"type": "n8n-nodes-base.executeWorkflow",
"typeVersion": 1.1,
"position": [
1650,
200
],
"notes": "Sub-Workflow: agent-builder"
},
{
"parameters": {
"workflowId": "agent-reviewer",
"source": "database",
"options": {}
},
"id": "call-reviewer",
"name": "Call Reviewer Agent",
"type": "n8n-nodes-base.executeWorkflow",
"typeVersion": 1.1,
"position": [
1650,
300
],
"notes": "Sub-Workflow: agent-reviewer"
},
{
"parameters": {
"workflowId": "agent-documenter",
"source": "database",
"options": {}
},
"id": "call-documenter",
"name": "Call Documenter Agent",
"type": "n8n-nodes-base.executeWorkflow",
"typeVersion": 1.1,
"position": [
1650,
400
],
"notes": "Sub-Workflow: agent-documenter"
},
{
"parameters": {
"mode": "combine",
"combinationMode": "mergeByPosition",
"options": {}
},
"id": "merge-results",
"name": "Merge Results",
"type": "n8n-nodes-base.merge",
"typeVersion": 2.1,
"position": [
1850,
300
]
},
{
"parameters": {
"jsCode": "// Aggregate all agent results\nconst items = $input.all();\nconst taskBreakdown = $('Parse Orchestrator').item.json.task_breakdown;\n\nconst results = {\n status: 'success',\n task_id: `task_${Date.now()}`,\n original_task: $('Parse Orchestrator').item.json.original_task,\n summary: $('Parse Orchestrator').item.json.summary,\n estimated_time: $('Parse Orchestrator').item.json.estimated_time,\n agents: {},\n execution_time: new Date().toISOString()\n};\n\n// Organize results by agent type\nitems.forEach((item, index) => {\n const agentType = taskBreakdown[index]?.agent || 'unknown';\n results.agents[agentType] = {\n output: item.json.output || item.json,\n status: item.json.status || 'completed',\n subtask: taskBreakdown[index]?.subtask || ''\n };\n});\n\nreturn { json: results };"
},
"id": "aggregate-results",
"name": "Aggregate Results",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2050,
300
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ $json }}",
"options": {}
},
"id": "respond-webhook",
"name": "Respond to Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
2250,
300
]
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Set Input",
"type": "main",
"index": 0
}
]
]
},
"Set Input": {
"main": [
[
{
"node": "Orchestrator LLM",
"type": "main",
"index": 0
}
]
]
},
"Orchestrator LLM": {
"main": [
[
{
"node": "Parse Orchestrator",
"type": "main",
"index": 0
}
]
]
},
"Parse Orchestrator": {
"main": [
[
{
"node": "Split Tasks",
"type": "main",
"index": 0
}
]
]
},
"Split Tasks": {
"main": [
[
{
"node": "Set Current Task",
"type": "main",
"index": 0
}
]
]
},
"Set Current Task": {
"main": [
[
{
"node": "Route to Agent",
"type": "main",
"index": 0
}
]
]
},
"Route to Agent": {
"main": [
[
{
"node": "Call Builder Agent",
"type": "main",
"index": 0
}
],
[
{
"node": "Call Reviewer Agent",
"type": "main",
"index": 0
}
],
[
{
"node": "Call Documenter Agent",
"type": "main",
"index": 0
}
]
]
},
"Call Builder Agent": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 0
}
]
]
},
"Call Reviewer Agent": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 0
}
]
]
},
"Call Documenter Agent": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 0
}
]
]
},
"Merge Results": {
"main": [
[
{
"node": "Aggregate Results",
"type": "main",
"index": 0
}
]
]
},
"Aggregate Results": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [],
"triggerCount": 0,
"updatedAt": "2025-12-19T12:00:00.000Z",
"versionId": "1"
}
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.
httpHeaderAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Agent Swarm - Main Orchestrator. Uses httpRequest. Webhook trigger; 13 nodes.
Source: https://github.com/timo-goetz-ai/apki-infra-hetzner/blob/133589ea8bc73203bd0b1e7a93f1df5c0a71941c/workflows/agent_swarm_01_main-orchestrator.json — 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.
Jigsaw API key for image processing, I use this as a gatekeeper/second pair of eyes. LINK to their website https://jigsawstack.com/ SECOND A postgress DATABASE (I use Supabase) LlamaCloud for the pars
Onsite Photos to Jobs (SMS Agent). Uses dataTable, twilio, httpRequest, airtable. Webhook trigger; 62 nodes.
W1 - IN WhatsApp Adapter (Secure + Fast ACK). Uses postgres, redis, httpRequest. Webhook trigger; 50 nodes.
W1 - IN WhatsApp Adapter (Secure + Fast ACK). Uses postgres, redis, httpRequest. Webhook trigger; 48 nodes.