{
  "name": "Barton Creek Mechanical Dual-Agent Dispatch",
  "active": false,
  "isArchived": false,
  "versionId": "gauntlet-lab-2026-09-05",
  "id": "apex-dual-agent-dispatch",
  "meta": {
    "instanceId": "gauntlet-voice-lab",
    "templateCredsSetupCompleted": false
  },
  "settings": {
    "executionOrder": "v1",
    "callerPolicy": "workflowsFromSameOwner"
  },
  "pinData": {},
  "tags": [
    {
      "name": "retell"
    },
    {
      "name": "hvac"
    },
    {
      "name": "gauntlet"
    }
  ],
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "retell-events",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "a1f0c0de-1111-4000-8000-apexwebhook01",
      "name": "Retell Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [0, 300],
      "webhookId": "apex-retell-events"
    },
    {
      "parameters": {
        "jsCode": "const body = $input.first().json;\nconst event = body.event;\nconst call = body.call ?? {};\nconst callId = call.call_id;\nif (!event || !callId) {\n  throw new Error('Invalid Retell webhook: event + call.call_id required');\n}\nconst key = `${event}:${callId}`;\nconst staticData = $getWorkflowStaticData('global');\nstaticData.seen = staticData.seen || {};\nconst duplicate = Boolean(staticData.seen[key]);\nif (!duplicate) staticData.seen[key] = Date.now();\nconst metadata = call.metadata ?? {};\nreturn [{\n  json: {\n    source: 'retell',\n    event,\n    call_id: callId,\n    idempotency_key: key,\n    duplicate,\n    direction: call.direction ?? 'inbound',\n    agent_id: call.agent_id ?? 'apex-inbound',\n    from_number: call.from_number,\n    to_number: call.to_number,\n    job_id: metadata.jobId ?? null,\n    emergency: metadata.emergency === true,\n    payload: body,\n  },\n}];"
      },
      "id": "b2e1d1ef-2222-4000-8000-apexidempot02",
      "name": "Idempotency Guard",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [240, 300]
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.duplicate }}",
              "value2": true
            }
          ]
        }
      },
      "id": "c3d2e2f0-3333-4000-8000-apexdupes03",
      "name": "Already Seen?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [480, 300]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { received: true, duplicate: true, idempotency_key: $json.idempotency_key, event: $json.event, call_id: $json.call_id } }}"
      },
      "id": "d4c3f301-4444-4000-8000-apexdupack04",
      "name": "Ack Duplicate",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [720, 160]
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "string": [
                  {
                    "value1": "={{ $json.event }}",
                    "value2": "call_ended"
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "call_ended"
            },
            {
              "conditions": {
                "string": [
                  {
                    "value1": "={{ $json.event }}",
                    "value2": "call_analyzed"
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "call_analyzed"
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "id": "e5b40412-5555-4000-8000-apexswitch05",
      "name": "Event Switch",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3,
      "position": [720, 400]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "ended-note",
              "name": "note",
              "value": "Call ended. Waiting for call_analyzed before SMS/email fan-out.",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "f6a51523-6666-4000-8000-apexended06",
      "name": "Log Call Ended",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [980, 280]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { received: true, duplicate: false, idempotency_key: $json.idempotency_key, event: $json.event, call_id: $json.call_id, side_effects: [] } }}"
      },
      "id": "07b62634-7777-4000-8000-apexendack07",
      "name": "Ack call_ended",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [1220, 280]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "sms-body",
              "name": "sms_body",
              "value": "=Barton Creek Mechanical: we logged your call ({{ $json.call_id }}). A tech will follow up.",
              "type": "string"
            },
            {
              "id": "email-body",
              "name": "email_body",
              "value": "=Call {{ $json.call_id }} analyzed. Job {{ $json.job_id || 'none' }}.",
              "type": "string"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "id": "18c73745-8888-4000-8000-apexset08",
      "name": "Build Fan-out",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [980, 520]
    },
    {
      "parameters": {
        "from": "+15125550100",
        "to": "={{ $json.from_number }}",
        "message": "={{ $json.sms_body }}"
      },
      "id": "29d84856-9999-4000-8000-apextwilio09",
      "name": "Confirmation SMS",
      "type": "n8n-nodes-base.twilio",
      "typeVersion": 1,
      "position": [1220, 420],
      "credentials": {
        "twilioApi": {
          "id": "REPLACE_ME",
          "name": "Twilio account"
        }
      }
    },
    {
      "parameters": {
        "sendTo": "ops@bartoncreek.example",
        "subject": "=Barton Creek dispatch · {{ $json.event }} · {{ $json.call_id }}",
        "message": "={{ $json.email_body }}",
        "options": {}
      },
      "id": "3ae95967-aaaa-4000-8000-apexgmail10",
      "name": "Ops Email",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [1220, 560],
      "credentials": {
        "gmailOAuth2": {
          "id": "REPLACE_ME",
          "name": "Gmail account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.emergency }}",
              "value2": true
            }
          ]
        }
      },
      "id": "4bfa6a78-bbbb-4000-8000-apexemerg11",
      "name": "Emergency?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [1460, 520]
    },
    {
      "parameters": {
        "from": "+15125550100",
        "to": "+15125550100",
        "message": "=Emergency page: call {{ $json.call_id }} / job {{ $json.job_id || 'unassigned' }}."
      },
      "id": "5c0b7b89-cccc-4000-8000-apexpage12",
      "name": "Owner Alert SMS",
      "type": "n8n-nodes-base.twilio",
      "typeVersion": 1,
      "position": [1700, 400],
      "credentials": {
        "twilioApi": {
          "id": "REPLACE_ME",
          "name": "Twilio account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.job_id }}",
              "operation": "isNotEmpty"
            }
          ]
        }
      },
      "id": "6d1c8c9a-dddd-4000-8000-apexjob13",
      "name": "Job Booked?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [1700, 620]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.retellai.com/v2/create-phone-call",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"from_number\": \"+15125550109\",\n  \"to_number\": \"+15125550101\",\n  \"override_agent_id\": \"apex-outbound\",\n  \"metadata\": {\n    \"jobId\": \"{{ $json.job_id }}\",\n    \"emergency\": {{ $json.emergency }}\n  }\n}",
        "options": {}
      },
      "id": "7e2d9dab-eeee-4000-8000-apexout14",
      "name": "Start Outbound Tech Call",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1940, 540],
      "credentials": {
        "httpHeaderAuth": {
          "id": "REPLACE_ME",
          "name": "Retell API"
        }
      }
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { received: true, duplicate: false, idempotency_key: $json.idempotency_key, event: $json.event, call_id: $json.call_id, side_effects: ['sms', 'email', $json.emergency ? 'owner_alert' : null, $json.job_id ? 'outbound_tech_call' : null].filter(Boolean) } }}"
      },
      "id": "8f3eaebc-ffff-4000-8000-apexack15",
      "name": "Ack call_analyzed",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [2180, 520]
    }
  ],
  "connections": {
    "Retell Webhook": {
      "main": [
        [
          {
            "node": "Idempotency Guard",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Idempotency Guard": {
      "main": [
        [
          {
            "node": "Already Seen?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Already Seen?": {
      "main": [
        [
          {
            "node": "Ack Duplicate",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Event Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Event Switch": {
      "main": [
        [
          {
            "node": "Log Call Ended",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Build Fan-out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Call Ended": {
      "main": [
        [
          {
            "node": "Ack call_ended",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Fan-out": {
      "main": [
        [
          {
            "node": "Confirmation SMS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Confirmation SMS": {
      "main": [
        [
          {
            "node": "Ops Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ops Email": {
      "main": [
        [
          {
            "node": "Emergency?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Emergency?": {
      "main": [
        [
          {
            "node": "Owner Alert SMS",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Job Booked?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Owner Alert SMS": {
      "main": [
        [
          {
            "node": "Job Booked?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Job Booked?": {
      "main": [
        [
          {
            "node": "Start Outbound Tech Call",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Ack call_analyzed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start Outbound Tech Call": {
      "main": [
        [
          {
            "node": "Ack call_analyzed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
