{
  "name": "Meeting Scheduling & Follow-ups",
  "nodes": [
    {
      "parameters": {
        "pollTimes": {
          "item": [{ "mode": "everyMinute", "minute": 5 }]
        },
        "calendarId": "primary"
      },
      "id": "calendar-trigger",
      "name": "New Calendar Event",
      "type": "n8n-nodes-base.googleCalendarTrigger",
      "typeVersion": 1,
      "position": [240, 300]
    },
    {
      "parameters": {
        "jsCode": "const event = $input.first().json;\nconst attendees = (event.attendees || []).map(a => ({\n  email: a.email,\n  name: a.displayName || a.email.split('@')[0],\n  organizer: a.organizer || false\n})).filter(a => !a.email.includes('calendar.google.com'));\n\nconst meetingTitle = event.summary || 'Untitled meeting';\nconst description = event.description || 'No description provided';\nconst startTime = event.start?.dateTime || event.start?.date || '';\nconst endTime = event.end?.dateTime || event.end?.date || '';\nconst location = event.location || 'No location set';\n\nconst attendeeNames = attendees.map(a => a.name).join(', ');\nconst attendeeEmails = attendees.filter(a => !a.organizer).map(a => a.email).join(', ');\n\nconst requestBody = {\n  model: 'claude-sonnet-4-20250514',\n  max_tokens: 1500,\n  messages: [\n    {\n      role: 'user',\n      content: `I have a meeting coming up. Generate two things:\\n\\n1. A PRE-MEETING BRIEF with:\\n   - Who is attending and what I should know about them (based on their email domains)\\n   - 3 specific questions I should prepare to ask\\n   - What to have ready (docs, data, context)\\n\\n2. A FOLLOW-UP EMAIL DRAFT that:\\n   - Thanks attendees for their time\\n   - Has placeholder bullets for action items: [ACTION ITEM 1], [ACTION ITEM 2]\\n   - Proposes a next step\\n   - Is warm but professional, under 120 words\\n\\nMeeting details:\\nTitle: ${meetingTitle}\\nDescription: ${description}\\nAttendees: ${attendeeNames}\\nTime: ${startTime}\\nLocation: ${location}\\n\\nRespond with JSON only:\\n{\\n  \"brief\": \"the pre-meeting brief as a formatted text block\",\\n  \"follow_up_subject\": \"email subject line for follow-up\",\\n  \"follow_up_body\": \"the follow-up email draft\"\\n}`\n    }\n  ]\n};\n\nreturn [{\n  json: {\n    requestBody,\n    meetingTitle,\n    attendeeEmails,\n    attendeeNames,\n    startTime,\n    eventId: event.id\n  }\n}];"
      },
      "id": "build-request",
      "name": "Build Claude Request",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [460, 300]
    },
    {
      "parameters": {
        "url": "https://api.anthropic.com/v1/messages",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            { "name": "x-api-key", "value": "={{ $env.ANTHROPIC_API_KEY }}" },
            { "name": "anthropic-version", "value": "2023-06-01" },
            { "name": "content-type", "value": "application/json" }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($json.requestBody) }}",
        "options": {}
      },
      "id": "call-claude",
      "name": "Generate Brief & Follow-up",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [680, 300]
    },
    {
      "parameters": {
        "jsCode": "const response = $input.first().json;\nconst content = response.content[0].text;\nconst prev = $('Build Claude Request').first().json;\n\nlet parsed;\ntry {\n  const jsonMatch = content.match(/\\{[\\s\\S]*\\}/);\n  parsed = JSON.parse(jsonMatch[0]);\n} catch (e) {\n  parsed = {\n    brief: 'Could not generate brief. Review the meeting details manually.',\n    follow_up_subject: 'Following up: ' + prev.meetingTitle,\n    follow_up_body: 'Thanks for meeting today. Here are the action items we discussed:\\n\\n- [ACTION ITEM 1]\\n- [ACTION ITEM 2]\\n\\nLet me know if I missed anything.'\n  };\n}\n\nreturn [{\n  json: {\n    ...parsed,\n    meetingTitle: prev.meetingTitle,\n    attendeeEmails: prev.attendeeEmails,\n    attendeeNames: prev.attendeeNames,\n    startTime: prev.startTime\n  }\n}];"
      },
      "id": "parse-content",
      "name": "Parse Content",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [900, 300]
    },
    {
      "parameters": {
        "jsCode": "const item = $input.first().json;\nreturn [{ json: { text: 'Meeting prep: ' + item.meetingTitle + '\\nTime: ' + item.startTime + '\\nWith: ' + item.attendeeNames + '\\n\\n' + item.brief } }];"
      },
      "id": "build-slack",
      "name": "Build Slack Brief",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [1120, 200]
    },
    {
      "parameters": {
        "url": "={{ $env.SLACK_WEBHOOK_URL }}",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($json) }}",
        "options": {}
      },
      "id": "send-brief",
      "name": "Send Pre-Meeting Brief",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1340, 200]
    },
    {
      "parameters": {
        "operation": "create",
        "resource": "draft",
        "subject": "={{ $json.follow_up_subject }}",
        "message": "={{ $json.follow_up_body }}",
        "toList": "={{ $json.attendeeEmails }}",
        "options": {}
      },
      "id": "draft-followup",
      "name": "Draft Follow-up Email",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2,
      "position": [1120, 400]
    }
  ],
  "connections": {
    "New Calendar Event": { "main": [[{ "node": "Build Claude Request", "type": "main", "index": 0 }]] },
    "Build Claude Request": { "main": [[{ "node": "Generate Brief & Follow-up", "type": "main", "index": 0 }]] },
    "Generate Brief & Follow-up": { "main": [[{ "node": "Parse Content", "type": "main", "index": 0 }]] },
    "Parse Content": {
      "main": [[
        { "node": "Build Slack Brief", "type": "main", "index": 0 },
        { "node": "Draft Follow-up Email", "type": "main", "index": 0 }
      ]]
    },
    "Build Slack Brief": { "main": [[{ "node": "Send Pre-Meeting Brief", "type": "main", "index": 0 }]] }
  },
  "settings": { "executionOrder": "v1" },
  "meta": { "templateCredsSetupCompleted": false, "instanceId": "loomiq-template" },
  "tags": ["loomiq", "scheduling", "ai"]
}
