AutomationFlowsAI & RAG › Scheduling Assistant - 06 Notify

Scheduling Assistant - 06 Notify

Scheduling Assistant - 06 Notify. Uses executeWorkflowTrigger, emailSend, postgres. Event-driven trigger; 5 nodes.

Event trigger★★★★☆ complexity5 nodesExecute Workflow TriggerEmail SendPostgres
AI & RAG Trigger: Event Nodes: 5 Complexity: ★★★★☆ Added:

This workflow follows the Emailsend → Postgres 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
{
  "name": "Scheduling Assistant - 06 Notify",
  "nodes": [
    {
      "parameters": {},
      "id": "workflow-trigger",
      "name": "When called by another workflow",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Determine notification type and prepare message\nconst items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n  const data = item.json.exportedData || item.json.conflictData || item.json.invalidData || item.json;\n  const notificationType = item.json.notificationType || 'event_created';\n\n  let subject = '';\n  let messageBody = '';\n  let recipients = [];\n\n  // Get requestor email\n  const requestorEmail = data.requestorEmail || data.normalized?.attendees?.[0] || '';\n  if (requestorEmail) {\n    recipients.push(requestorEmail);\n  }\n\n  // Build notification based on type\n  switch (notificationType) {\n    case 'event_created':\n      subject = `[SCHEDULED] Meeting Scheduled: ${data.normalized.title}`;\n      messageBody = `Your meeting has been successfully scheduled.\n\nEvent: ${data.normalized.title}\nTime: ${new Date(data.normalized.startTime).toLocaleString()}\nDuration: ${data.normalized.duration} minutes\nLocation: ${data.normalized.location}\nAttendees: ${data.normalized.attendees.join(', ')}\n\nCalendar Link: ${data.export?.eventUrl || 'Check your calendar'}\nEvent ID: ${data.export?.eventId || data.requestId}\n\nAll attendees have been notified via calendar invitation.`;\n      break;\n\n    case 'conflict_detected':\n      subject = `[CONFLICT] Scheduling Conflict Detected: ${data.normalized.title}`;\n      messageBody = `A conflict was detected with your requested meeting time.\n\nRequested: ${data.normalized.title}\nTime: ${new Date(data.normalized.startTime).toLocaleString()}\nConflicts Found: ${data.conflictScan.conflictCount}\n\nConflicting Events:\n${data.conflictScan.conflicts.map(c => `  - ${c.title} (${new Date(c.start).toLocaleString()} - ${new Date(c.end).toLocaleString()})`).join('\\n')}\n\nSuggested Alternative Times:\n${data.conflictScan.alternatives.map((alt, idx) => `  ${idx + 1}. ${new Date(alt.startTime).toLocaleString()} - ${alt.reason}`).join('\\n')}\n\nPlease reply with your preferred alternative time or suggest a different slot.`;\n      break;\n\n    case 'validation_failed':\n      subject = `[FAILED] Scheduling Request Failed: ${data.normalized?.title || 'Meeting'}`;\n      messageBody = `Your scheduling request could not be processed due to validation errors.\n\nRequested: ${data.normalized?.title || 'Meeting'}\nTime: ${data.normalized?.startTime ? new Date(data.normalized.startTime).toLocaleString() : 'Not specified'}\n\nErrors:\n${data.validation.errors.map(e => `  - ${e}`).join('\\n')}${data.validation.warnings.length > 0 ? `\\n\\nWarnings:\\n${data.validation.warnings.map(w => `  - ${w}`).join('\\n')}` : ''}\n\nPlease review the errors above and submit a corrected request.`;\n      break;\n\n    default:\n      subject = `Meeting Update: ${data.normalized?.title || 'Notification'}`;\n      messageBody = `Your scheduling request has been processed.\n\nRequest ID: ${data.requestId}\nStatus: ${data.status}`;\n  }\n\n  const notificationData = {\n    ...data,\n    notification: {\n      type: notificationType,\n      subject: subject,\n      body: messageBody,\n      recipients: recipients,\n      preparedAt: new Date().toISOString(),\n      confirmationCode: `CONF-${Date.now()}`\n    },\n    stage: 'notification_prepared',\n    processedAt: new Date().toISOString()\n  };\n\n  results.push({ json: notificationData });\n}\n\nreturn results;"
      },
      "id": "code-prepare-notification",
      "name": "Prepare Notification",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        450,
        300
      ]
    },
    {
      "parameters": {
        "fromEmail": "={{$env.NOTIFICATION_EMAIL_FROM || 'noreply@scheduling.com'}}",
        "toEmail": "={{$json.notification.recipients.join(',')}}",
        "subject": "={{$json.notification.subject}}",
        "text": "={{$json.notification.body}}",
        "options": {
          "allowUnauthorizedCerts": false
        }
      },
      "id": "send-notification",
      "name": "Send Notification",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2,
      "position": [
        650,
        300
      ],
      "disabled": true,
      "notes": "Placeholder delivery node, disabled by default. Replace this node with your actual notification channel: Telegram sendMessage, HTTP Request to a webhook, or any messaging integration supported by n8n. The notification payload (subject, body, recipients) is already prepared by the Prepare Notification node above.",
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Log notification delivery\nconst items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n  const data = item.json;\n  \n  const finalResult = {\n    ...data,\n    notification: {\n      ...data.notification,\n      sent: true,\n      sentAt: new Date().toISOString(),\n      deliveryStatus: 'success'\n    },\n    stage: 'completed',\n    completedAt: new Date().toISOString(),\n    summary: {\n      requestId: data.requestId,\n      status: data.status,\n      notificationType: data.notification.type,\n      recipients: data.notification.recipients,\n      processingTime: new Date() - new Date(data.timestamp)\n    }\n  };\n  \n  results.push({ json: finalResult });\n}\n\nreturn results;"
      },
      "id": "code-log-completion",
      "name": "Log Completion",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        850,
        300
      ]
    },
    {
      "parameters": {
        "operation": "insert",
        "table": "scheduling_logs",
        "columns": "request_id, status, notification_type, completed_at, processing_time_ms",
        "options": {}
      },
      "id": "database-log",
      "name": "Store in Database (Optional)",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        1050,
        300
      ],
      "disabled": true,
      "notes": "Enable this node if you want to persist scheduling logs to a database"
    }
  ],
  "connections": {
    "When called by another workflow": {
      "main": [
        [
          {
            "node": "Prepare Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Notification": {
      "main": [
        [
          {
            "node": "Send Email Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Email Notification": {
      "main": [
        [
          {
            "node": "Log Completion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Completion": {
      "main": [
        [
          {
            "node": "Store in Database (Optional)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveExecutionProgress": true,
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "all"
  },
  "staticData": null,
  "tags": [
    {
      "name": "scheduling-assistant",
      "id": "scheduling-tag-001"
    },
    {
      "name": "notification",
      "id": "notification-tag-001"
    }
  ],
  "triggerCount": 0,
  "updatedAt": "2026-01-19T20:02:35.000Z",
  "versionId": "v1.0.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

Scheduling Assistant - 06 Notify. Uses executeWorkflowTrigger, emailSend, postgres. Event-driven trigger; 5 nodes.

Source: https://github.com/jasonv2610/multi-agent-orchestration-architecture/blob/main/examples/scheduling-assistant/workflows/06_notify.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

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

AI & RAG

Memorybufferwindow Workflow. Uses emailSend, httpRequest, executeWorkflowTrigger, formTrigger. Event-driven trigger; 45 nodes.

Email Send, HTTP Request, Execute Workflow Trigger +1
AI & RAG

W4.1 - ROUTER (State + Voice). Uses executeWorkflowTrigger, postgres, redis. Event-driven trigger; 30 nodes.

Execute Workflow Trigger, Postgres, Redis
AI & RAG

SHEETS RAG. Uses googleDriveTrigger, postgres, googleSheets, executeWorkflowTrigger. Event-driven trigger; 24 nodes.

Google Drive Trigger, Postgres, Google Sheets +2
AI & RAG

Gmail-Calendar. Uses executeWorkflowTrigger, postgres, googleCalendar, httpRequest. Event-driven trigger; 12 nodes.

Execute Workflow Trigger, Postgres, Google Calendar +1
AI & RAG

Gmail-Triage. Uses executeWorkflowTrigger, httpRequest, postgres. Event-driven trigger; 10 nodes.

Execute Workflow Trigger, HTTP Request, Postgres