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": "Tutorial - Coordinator Agent (Simplified)",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "invoice-agent",
"responseMode": "responseNode",
"options": {}
},
"id": "webhook-trigger",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
240,
300
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "requestId",
"name": "requestId",
"value": "={{ $runId }}",
"type": "string"
},
{
"id": "action",
"name": "action",
"value": "={{ $json.body.action ?? 'unknown' }}",
"type": "string"
},
{
"id": "data",
"name": "data",
"value": "={{ $json.body.data ?? {} }}",
"type": "object"
},
{
"id": "options",
"name": "options",
"value": "={{ $json.body.options ?? {} }}",
"type": "object"
},
{
"id": "timestamp",
"name": "timestamp",
"value": "={{ $now.toISO() }}",
"type": "string"
}
]
},
"options": {}
},
"id": "extract-request",
"name": "Extract Request",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
440,
300
]
},
{
"parameters": {
"rules": {
"rules": [
{
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "generate",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
},
"renameOutput": true,
"outputKey": "generate"
},
{
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "parse",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
},
"renameOutput": true,
"outputKey": "parse"
},
{
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "validate",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
},
"renameOutput": true,
"outputKey": "validate"
},
{
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "parseAutoDetect",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
},
"renameOutput": true,
"outputKey": "parseAutoDetect"
}
],
"fallbackOutput": {
"fallbackOutput": "extra"
}
},
"options": {}
},
"id": "route-action",
"name": "Route by Action",
"type": "n8n-nodes-base.switch",
"typeVersion": 3.2,
"position": [
640,
300
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "success",
"name": "success",
"value": true,
"type": "boolean"
},
{
"id": "action",
"name": "action",
"value": "generate",
"type": "string"
},
{
"id": "message",
"name": "message",
"value": "Generation agent would be called here. In production, use Execute Workflow node to call the Generation Agent workflow.",
"type": "string"
},
{
"id": "data",
"name": "data",
"value": "={{ $('Extract Request').item.json.data }}",
"type": "object"
}
]
},
"options": {}
},
"id": "placeholder-generation",
"name": "Generation Agent (Placeholder)",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
880,
120
],
"notesInFlow": true,
"notes": "In production: Replace with Execute Workflow node pointing to 03-generation-agent.json"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "success",
"name": "success",
"value": true,
"type": "boolean"
},
{
"id": "action",
"name": "action",
"value": "parse",
"type": "string"
},
{
"id": "message",
"name": "message",
"value": "Parsing agent would be called here. In production, use Execute Workflow node to call the Parsing Agent workflow.",
"type": "string"
},
{
"id": "data",
"name": "data",
"value": "={{ $('Extract Request').item.json.data }}",
"type": "object"
}
]
},
"options": {}
},
"id": "placeholder-parsing",
"name": "Parsing Agent (Placeholder)",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
880,
240
],
"notesInFlow": true,
"notes": "In production: Replace with Execute Workflow node pointing to 04-parsing-agent.json"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "success",
"name": "success",
"value": true,
"type": "boolean"
},
{
"id": "action",
"name": "action",
"value": "parseAutoDetect",
"type": "string"
},
{
"id": "message",
"name": "message",
"value": "Parse Auto-Detect agent would be called here. Automatically detects country and format. In production, use Execute Workflow node with parseAutoDetect operation.",
"type": "string"
},
{
"id": "data",
"name": "data",
"value": "={{ $('Extract Request').item.json.data }}",
"type": "object"
}
]
},
"options": {}
},
"id": "placeholder-parse-autodetect",
"name": "Parse Auto-Detect Agent (Placeholder)",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
880,
360
],
"notesInFlow": true,
"notes": "In production: Replace with Execute Workflow node using parseAutoDetect operation"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "success",
"name": "success",
"value": true,
"type": "boolean"
},
{
"id": "action",
"name": "action",
"value": "validate",
"type": "string"
},
{
"id": "message",
"name": "message",
"value": "Validation agent would be called here. In production, use Execute Workflow node to call the Validation Agent workflow.",
"type": "string"
},
{
"id": "data",
"name": "data",
"value": "={{ $('Extract Request').item.json.data }}",
"type": "object"
}
]
},
"options": {}
},
"id": "placeholder-validation",
"name": "Validation Agent (Placeholder)",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
880,
480
],
"notesInFlow": true,
"notes": "In production: Replace with Execute Workflow node pointing to 02-validation-agent.json"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "success",
"name": "success",
"value": false,
"type": "boolean"
},
{
"id": "error",
"name": "error",
"value": "Unknown action. Supported actions: generate, parse, parseAutoDetect, validate",
"type": "string"
},
{
"id": "action",
"name": "action",
"value": "={{ $('Extract Request').item.json.action }}",
"type": "string"
},
{
"id": "errorCode",
"name": "errorCode",
"value": 400,
"type": "number"
}
]
},
"options": {}
},
"id": "unknown-action",
"name": "Unknown Action Error",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
880,
620
]
},
{
"parameters": {},
"id": "merge-results",
"name": "Merge Results",
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [
1120,
300
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.success }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
]
},
"options": {}
},
"id": "check-success",
"name": "Check Success",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1320,
300
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: true, requestId: $('Extract Request').item.json.requestId, action: $json.action, result: { message: $json.message, data: $json.data }, timestamp: $now.toISO() }) }}",
"options": {
"responseCode": 200,
"responseHeaders": {
"entries": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
}
},
"id": "respond-success",
"name": "Respond Success",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
1560,
200
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: false, requestId: $('Extract Request').item.json.requestId, error: $json.error ?? 'Processing failed', action: $json.action, timestamp: $now.toISO() }) }}",
"options": {
"responseCode": "={{ $json.errorCode ?? 500 }}",
"responseHeaders": {
"entries": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
}
},
"id": "respond-error",
"name": "Respond Error",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
1560,
400
]
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Extract Request",
"type": "main",
"index": 0
}
]
]
},
"Extract Request": {
"main": [
[
{
"node": "Route by Action",
"type": "main",
"index": 0
}
]
]
},
"Route by Action": {
"main": [
[
{
"node": "Generation Agent (Placeholder)",
"type": "main",
"index": 0
}
],
[
{
"node": "Parsing Agent (Placeholder)",
"type": "main",
"index": 0
}
],
[
{
"node": "Validation Agent (Placeholder)",
"type": "main",
"index": 0
}
],
[
{
"node": "Parse Auto-Detect Agent (Placeholder)",
"type": "main",
"index": 0
}
],
[
{
"node": "Unknown Action Error",
"type": "main",
"index": 0
}
]
]
},
"Generation Agent (Placeholder)": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 0
}
]
]
},
"Parsing Agent (Placeholder)": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 0
}
]
]
},
"Parse Auto-Detect Agent (Placeholder)": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 0
}
]
]
},
"Validation Agent (Placeholder)": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 0
}
]
]
},
"Unknown Action Error": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 0
}
]
]
},
"Merge Results": {
"main": [
[
{
"node": "Check Success",
"type": "main",
"index": 0
}
]
]
},
"Check Success": {
"main": [
[
{
"node": "Respond Success",
"type": "main",
"index": 0
}
],
[
{
"node": "Respond Error",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [
{
"name": "tutorial",
"id": "tutorial-3"
},
{
"name": "coordinator",
"id": "coordinator-1"
},
{
"name": "multi-agent",
"id": "multi-agent-1"
}
]
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Tutorial - Coordinator Agent (Simplified). Webhook trigger; 12 nodes.
Source: https://github.com/xhubio/n8n-nodes-invoice-api-xhub/blob/main/docs/tutorials/workflows/tutorial-03-coordinator.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.