N
n8n Store
Workflow Market
Weekly OKR Alignment Report with Gmail, Google Calendar, Notion, and GPT-4.1

Weekly OKR Alignment Report with Gmail, Google Calendar, Notion, and GPT-4.1

by mark106670 views

Description

Categories

📊 Productivity🤖 AI & Machine Learning

Nodes Used

n8n-nodes-base.setn8n-nodes-base.setn8n-nodes-base.coden8n-nodes-base.coden8n-nodes-base.coden8n-nodes-base.coden8n-nodes-base.coden8n-nodes-base.gmailn8n-nodes-base.gmailn8n-nodes-base.merge
PriceGratis
Views0
Last Updated11/28/2025
workflow.json
{
  "nodes": [
    {
      "id": "c47729f7-33d0-4276-ac6f-ca67edd179ac",
      "name": "Get many messages",
      "type": "n8n-nodes-base.gmail",
      "position": [
        0,
        0
      ],
      "webhookId": "c32d957e-e332-40f9-946f-b84e148a397c",
      "parameters": {
        "filters": {
          "receivedAfter": "={{ $now.minus({ week: 1 }) }}"
        },
        "operation": "getAll",
        "returnAll": true
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "fOhvOhzbmfvT5cZo",
          "name": "Gmail account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "ae728d35-ccd1-4f09-8efc-f52ff442e236",
      "name": "Edit Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        400,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "56ac22c4-56a7-467f-898b-fafa7e233b07",
              "name": "from_display",
              "type": "string",
              "value": "={{$json.From.name || $json.From.email || $json.From}}"
            },
            {
              "id": "04fbfc22-d358-4a2c-aeee-483a1e5372ba",
              "name": "subject",
              "type": "string",
              "value": "={{$json.Subject}}"
            },
            {
              "id": "cad79f7c-cf47-4eb8-a2bd-36b62e70a9ec",
              "name": "date",
              "type": "string",
              "value": "={{$json.internalDate}}"
            },
            {
              "id": "612403fd-8e26-43fa-b49e-fc510d0596f6",
              "name": "body",
              "type": "string",
              "value": "={{$json.textPlain || $json.snippet}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f7ebfc4a-16dd-44ed-b796-17173bc53fec",
      "name": "Get many events",
      "type": "n8n-nodes-base.googleCalendar",
      "position": [
        0,
        240
      ],
      "parameters": {
        "options": {},
        "timeMax": "={{ $now.plus({ month: 1 }) }}",
        "timeMin": "={{ $now.minus({ week: 1 }) }}",
        "calendar": {
          "__rl": true,
          "mode": "list",
          "value": "[email protected]",
          "cachedResultName": "[email protected]"
        },
        "operation": "getAll"
      },
      "credentials": {
        "googleCalendarOAuth2Api": {
          "id": "pC0SIvrNY21dVpIQ",
          "name": "Google Calendar account"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "8a6fa5f2-9d9a-4f2d-a1f8-092bd218fbcc",
      "name": "Edit Fields1",
      "type": "n8n-nodes-base.set",
      "position": [
        192,
        240
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "8da8d232-f2f8-4a22-8ead-5c56f2c12fcb",
              "name": "summary",
              "type": "string",
              "value": "={{ $json.summary }}"
            },
            {
              "id": "b03fb05b-b857-409c-8811-f8b44718bc40",
              "name": "time",
              "type": "string",
              "value": "={{ $json.start.dateTime }}{{ $json.end.dateTime }}"
            },
            {
              "id": "ddc969da-e0d3-45fd-9281-5c0fa213742c",
              "name": "attendees",
              "type": "string",
              "value": "={{ $json.attendees[0].email }}"
            },
            {
              "id": "22760046-2864-4ec1-bab1-fcec17ef370b",
              "name": "description",
              "type": "string",
              "value": "={{ $json.description }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "3ed4818e-2693-492d-b9e0-1898ca470635",
      "name": "Analyze image",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        624,
        512
      ],
      "parameters": {
        "text": "Prompt for Analyze Image\n\nYou are analyzing a weekly plan written in a notebook.\n\nThe page is divided into quadrants: Urgent / Not Urgent (columns) and Important / Not Important (rows).\n\nEach bullet or phrase is an action item.\n\nIf an item is crossed out, mark it as finished = true. Otherwise, finished = false.\n\nReturn all items in structured JSON.\n\nOutput format:\n\n{\n  \"quadrants\": {\n    \"urgent_important\": [\n      {\"task\": \"string\", \"finished\": true|false},\n      {\"task\": \"string\", \"finished\": true|false}\n    ],\n    \"not_urgent_important\": [\n      {\"task\": \"string\", \"finished\": true|false}\n    ],\n    \"urgent_not_important\": [\n      {\"task\": \"string\", \"finished\": true|false}\n    ],\n    \"not_urgent_not_important\": [\n      {\"task\": \"string\", \"finished\": true|false}\n    ]\n  }\n}\n\n\nRules:\n\nPreserve original wording as much as possible.\n\nIf the quadrant placement is unclear, make your best guess.\n\nDo not add commentary — output only the JSON.",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {},
        "resource": "image",
        "inputType": "base64",
        "operation": "analyze"
      },
      "credentials": {
        "openAiApi": {
          "id": "zKPOyC2wICv7flD9",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "abfe489e-2195-4e87-bcc2-1005afdc884a",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        400,
        512
      ],
      "parameters": {
        "url": "={{ $json.property_files_media[0] }}",
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "b7f5ca68-8a77-4def-9659-b8beb7a57b73",
      "name": "Filter1",
      "type": "n8n-nodes-base.filter",
      "notes": "On the last day of each week, the system grabs the weekly plan of that week. \n\n{{ $now.setZone('Asia/Hong_Kong').toISODate() }}",
      "position": [
        192,
        512
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4839778a-17c1-47de-a193-9d3c866138d2",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.property_date.end }}",
              "rightValue": "={{ $now.setZone('Asia/Hong_Kong').toISODate() }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "4f6ba339-8b85-4e39-894c-91342f797c56",
      "name": "Filter2",
      "type": "n8n-nodes-base.filter",
      "position": [
        192,
        768
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "f74dc194-a313-4c15-8814-731eb73804cf",
              "operator": {
                "type": "dateTime",
                "operation": "after"
              },
              "leftValue": "={{ $now.setZone('Asia/Hong_Kong').toISODate() }}",
              "rightValue": "={{ $json.property_date.start }}"
            },
            {
              "id": "1271a486-4845-4ec4-992a-bb1f761c503a",
              "operator": {
                "type": "dateTime",
                "operation": "beforeOrEquals"
              },
              "leftValue": "={{ $now.setZone('Asia/Hong_Kong').toISODate() }}",
              "rightValue": "={{ $json.property_date.end }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c76c7867-e8e3-45c0-9b07-6b3a66958eb7",
      "name": "Gmail Code",
      "type": "n8n-nodes-base.code",
      "position": [
        624,
        0
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\n\nconst MAX_CHARS = 2000;\n\nconst blocks = items.map(i => {\n  const j = i.json;\n  const body = (j.body || '')\n    .replace(/\\s+\\n/g, '\\n')\n    .slice(0, MAX_CHARS);\n\n  return [\n    '=== EMAIL ===',\n    `Date: ${j.date}`,\n    `From: ${j.from_display}`,\n    `Subject: ${j.subject}`,\n    '',\n    body\n  ].join('\\n');\n});\n\nreturn [{ json: { emails_joined: blocks.join('\\n\\n') } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "165a03f8-cb2f-495c-a0b1-cb5477572310",
      "name": "Calendar Code",
      "type": "n8n-nodes-base.code",
      "position": [
        400,
        240
      ],
      "parameters": {
        "jsCode": "// Build a compact, LLM-friendly string from Calendar events\nconst MAX_DESC = 600; // trim long descriptions\n\nfunction splitTimeField(t) {\n  if (!t) return [null, null];\n  // Prefer regex for two ISO datetimes with timezone offsets\n  const m = t.match(/\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}[+-]\\d{2}:\\d{2}/g);\n  if (m && m.length >= 2) return [m[0], m[1]];\n  // Fallback: ISO with offset is 25 chars; split in half\n  if (t.length >= 50) return [t.slice(0, 25), t.slice(25)];\n  return [t, null];\n}\n\nconst blocks = items.map(i => {\n  const j = i.json || {};\n  const [start, end] = splitTimeField(j.time);\n\n  const attendees =\n    j.attendees == null\n      ? []\n      : Array.isArray(j.attendees)\n        ? j.attendees\n        : String(j.attendees).split(',').map(s => s.trim()).filter(Boolean);\n\n  const notes = (j.description || '')\n    .replace(/\\s+\\n/g, '\\n')\n    .trim()\n    .slice(0, MAX_DESC);\n\n  const lines = [\n    '=== EVENT ===',\n    `When: ${start || 'TBD'} → ${end || 'TBD'}`,\n    `Title: ${j.summary || '(no title)'}`,\n    `Attendees: ${attendees.length ? attendees.join(', ') : '-'}`\n  ];\n  if (notes) {\n    lines.push('', notes);\n  }\n  return lines.join('\\n');\n});\n\nreturn [{ json: { calendar_joined: blocks.join('\\n\\n') } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "c7855bfa-8906-41a9-aefb-d2f13a049e96",
      "name": "Weekly Code",
      "type": "n8n-nodes-base.code",
      "notes": "\n\n\n\n// Parse the JSON from content (sometimes it's stringified with markdown formatting)\nlet parsed;\ntry {\n  const raw = $json.content.trim();\n  const jsonText = raw.startsWith('```') ? raw.replace(/```(json)?/g, '').trim() : raw;\n  parsed = JSON.parse(jsonText);\n} catch (err) {\n  throw new Error(\"Failed to parse 'content' as JSON\");\n}\n\nconst quadrants = parsed.quadrants || {};\n\nfunction formatTasks(title, tasks) {\n  if (!tasks || !tasks.length) return '';\n  const lines = tasks.map(t =>\n    `- [${t.finished ? 'x' : ' '}] ${t.task}`\n  );\n  return [`=== ${title} ===`, ...lines].join('\\n');\n}\n\nconst blocks = [\n  formatTasks('Urgent & Important', quadrants.urgent_important),\n  formatTasks('Not Urgent but Important', quadrants.not_urgent_important),\n  formatTasks('Urgent but Not Important', quadrants.urgent_not_important),\n  formatTasks('Not Urgent & Not Important', quadrants.not_urgent_not_important),\n].filter(Boolean); // remove empty sections\n\nreturn [{ json: { weeklyplan_joined: blocks.join('\\n\\n') } }];\n\n",
      "position": [
        832,
        512
      ],
      "parameters": {
        "jsCode": "// Run Once for All Items\n// Purpose: Safely parse the \"content\" field coming from the LLM (or other nodes),\n// which may be in multiple inconsistent formats:\n//   - Already a JSON object\n//   - A JSON string (valid)\n//   - A JSON string wrapped in ```json ... ``` code fences\n//   - A JSON string prefixed with \"json\\n\"\n//   - A JSON string that's double-encoded (JSON string inside a string)\n//   - Or even invalid, in which case we want to fail gracefully\n\nfunction toObj(val) {\n  if (val == null) return {};                 // Case 1: if content is null/undefined → return empty object\n  if (typeof val === 'object') return val;    // Case 2: if it's already parsed into an object → just return it\n\n  // Otherwise, assume it's a string\n  let txt = String(val).trim();               // Convert to string & trim whitespace\n\n  // Remove markdown code fences ```json ... ```\n  txt = txt.replace(/^```(?:json)?\\s*/i, '')  // Remove opening ``` or ```json\n           .replace(/```$/,'')                // Remove closing ```\n           .trim();\n\n  // Some models add \"json\\n{...}\" before the object → remove the leading \"json\"\n  txt = txt.replace(/^json\\s*/i, '');\n\n  // --- Attempt parsing in several ways ---\n\n  // Attempt #1: Normal JSON.parse\n  try { \n    return JSON.parse(txt); \n  } catch {}\n\n  // Attempt #2: Double-encoded JSON\n  // Example: \"\\\"{ \\\\\\\"key\\\\\\\":123 }\\\"\" → needs two parses\n  try { \n    return JSON.parse(JSON.parse(txt)); \n  } catch {}\n\n  // Attempt #3: Extract first {...} block and try parsing that\n  // Useful if there’s extra text around the JSON\n  const m = txt.match(/\\{[\\s\\S]*\\}$/);   // greedy match from first { to last }\n  if (m) { \n    try { return JSON.parse(m[0]); } catch {} \n  }\n\n  // If all parsing attempts fail, return a fallback object\n  return { \n    _raw: txt,                         // Keep the raw string so we don't lose information\n    _error: 'could_not_parse_json'     // Add a flag for debugging\n  };\n}\n\n// --- Main execution starts here ---\n// $json is the current item in n8n\n// We check for the field \"content\" (or sometimes LLM outputs live under message.content)\nconst content = $json.content ?? $json.message?.content ?? '';\n\n// Apply the parser to try to normalize content into an object\nconst obj = toObj(content);\n\n// Return the result as n8n output\n// - weeklyplan_joined: always a string version (good for downstream LLM prompts)\n// - parsed_weekly: the actual parsed object (good for structured handling)\nreturn [{\n  json: {\n    weeklyplan_joined: typeof obj === 'string' ? obj : JSON.stringify(obj),\n    parsed_weekly: obj\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "63fc8f6b-5f4a-4ced-9b3a-c202490fa224",
      "name": "Quarterly Code",
      "type": "n8n-nodes-base.code",
      "position": [
        400,
        768
      ],
      "parameters": {
        "jsCode": "const blocks = $items('Filter2').map((i, idx) => {\n  const j = i.json;\n  return [\n    `=== OKR ${idx + 1} ===`,\n    `Objective: ${j.property_objective || '(missing)'}`,\n    `Key Result: ${j.property_key_result || '(missing)'}`,\n    `Status: ${j.property_status || 'Unknown'}`\n  ].join('\\n');\n});\n\nreturn [{ json: { okrs_joined: blocks.join('\\n\\n') } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "e129ca79-4521-47ed-9ac1-c6665b8ee026",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        1152,
        160
      ],
      "parameters": {
        "mode": "chooseBranch",
        "output": "empty"
      },
      "typeVersion": 3.2
    },
    {
      "id": "ab0b5344-c5ba-49ed-88a1-2006be862d11",
      "name": "Merge1",
      "type": "n8n-nodes-base.merge",
      "position": [
        1152,
        592
      ],
      "parameters": {
        "mode": "chooseBranch",
        "output": "empty"
      },
      "typeVersion": 3.2
    },
    {
      "id": "a8ca2567-3d89-40a9-9103-0f904fa0f1d6",
      "name": "Merge2",
      "type": "n8n-nodes-base.merge",
      "position": [
        1408,
        384
      ],
      "parameters": {
        "mode": "chooseBranch",
        "output": "empty"
      },
      "typeVersion": 3.2
    },
    {
      "id": "2e23de28-730f-446e-aa18-9710891d1142",
      "name": "Send a message",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2080,
        384
      ],
      "webhookId": "fc15b8e1-78d7-4411-a320-2e5f1355dadc",
      "parameters": {
        "sendTo": "[email protected]",
        "message": "={{$json[\"message\"][\"content\"]}}",
        "options": {},
        "subject": "Weekly OKR Report"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "fOhvOhzbmfvT5cZo",
          "name": "Gmail account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "18ef3024-0679-42cc-9a73-a62a547fdd38",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "notes": "0 */1 * * * *\n\n0 14 10 * * 6",
      "position": [
        -336,
        416
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 30 20 * * 6"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "3ea6bd19-c77b-4285-8732-5ddbb1f3d702",
      "name": "Gmail Filter",
      "type": "n8n-nodes-base.code",
      "position": [
        192,
        0
      ],
      "parameters": {
        "jsCode": "const isNoise = (item) => {\n  const labels = item.json.labels?.map(l => l.name.toUpperCase()) || [];\n  const subject = (item.json.Subject || '').toLowerCase();\n\n  // Exclude by labels\n  const hasBadLabel = labels.some(l =>\n    ['CATEGORY_PROMOTIONS', 'CATEGORY_SOCIAL', 'SPAM', 'n8n', 'TRASH'].includes(l)\n  );\n\n  // Exclude by subject (receipts)\n  const isReceipt = subject.includes('receipt') || subject.includes('receipts');\n\n  return hasBadLabel || isReceipt;\n};\n\n// Filter\nconst filtered = items.filter(item => !isNoise(item));\n\n// Fallback: if empty, return dummy\nif (filtered.length === 0) {\n  return [{\n    json: {\n      Subject: '',\n      From: '',\n      body: 'No human-relevant emails this week.',\n    }\n  }];\n}\n\nreturn filtered;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "23a5c0bd-7d15-48ee-8ec6-0115e85b720c",
      "name": "Get quarterly okr database",
      "type": "n8n-nodes-base.notion",
      "position": [
        0,
        768
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "operation": "getAll",
        "returnAll": true,
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "260741de-415a-80a8-bdc9-d7bb7cf4b66e",
          "cachedResultUrl": "[REDACTED_NOTION_URL]",
          "cachedResultName": "QuarterlyPlan"
        }
      },
      "credentials": {
        "notionApi": {
          "id": "35TsQmfyObapPFkk",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "882db05a-6f91-4554-8196-1fd41e3e1ac2",
      "name": "Get weekly plan database",
      "type": "n8n-nodes-base.notion",
      "position": [
        0,
        512
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "operation": "getAll",
        "returnAll": true,
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "261741de-415a-8011-9ec5-e9988d4f414e",
          "cachedResultUrl": "[REDACTED_NOTION_URL]",
          "cachedResultName": "WeeklyPlan"
        }
      },
      "credentials": {
        "notionApi": {
          "id": "35TsQmfyObapPFkk",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "207b11e3-0b9b-4df4-92c2-7e9a68b49046",
      "name": "Message a model1",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1680,
        384
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini",
          "cachedResultName": "GPT-4.1-MINI"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=# Inputs\n\n## OKRs\n{{ $node[\"Quarterly Code\"].json[\"okrs_joined\"] }}\n\n## Calendar\n{{ $node[\"Calendar Code\"].json[\"calendar_joined\"] }}\n\n## Weekly Plan\n{{ $node[\"Weekly Code\"].json[\"weeklyplan_joined\"] }}\n\n## Emails\n{{ $node[\"Gmail Code\"].json[\"emails_joined\"] }}\n\n\n# Tasks\n1. Check alignment across OKRs, emails, calendar, and weekly plan.\n    * Treat OKRs as the North Star.\n    * Use emails, calendar events, and weekly plan tasks as evidence of actual work.\n    * Look for alignment (e.g., a weekly task reflected in an email thread).\n    * Also recognize complementary items (e.g., a short task that appears only on weekly plan but not blocked on calendar).\n    * Goal: form a comprehensive view of progress.\n2. Assess execution realism for the week.\n    * Highlight over- or under-scheduling, conflicts, missing preparation, and dependencies.\n    * Identify what advances each OKR, and flag any OKRs falling behind due to lack of attention or communication.\n    * Call out gaps and risks (e.g., a key result with no calendar time or email activity, or a due date approaching).\n3. Extract time-sensitive asks and commitments from emails.\n    * Note replies that are delayed or missing.\n    * Highlight urgent follow-ups to avoid overlooking important threads.\n4. Suggest concrete next steps.\n    * Recommend actions that keep execution realistic and OKRs on track.\n\n\n# Output format\nReturn the entire output as valid HTML (no Markdown). Follow this structure:\n\n<h3>Summary</h3>\n<ul>\n  <li>4–6 key themes of the week.</li>\n</ul>\n\n<h3>Alignment Check</h3>\n<table border=\"1\" cellpadding=\"6\" cellspacing=\"0\" style=\"border-collapse:collapse; width:100%;\">\n  <tr>\n    <th>OKR</th>\n    <th>Weekly Plan Tasks</th>\n    <th>Calendar Events</th>\n    <th>Related Emails / Notes</th>\n  </tr>\n  <!-- Add one <tr> row per OKR -->\n</table>\n\n<h3>Email Follow-ups</h3>\n<ul>\n  <li>List urgent or overdue responses</li>\n</ul>\n\n<h3>Next Steps</h3>\n<ol>\n  <li>3–5 clear actions for the coming week</li>\n</ol>\n"
            },
            {
              "role": "system",
              "content": "You are an assistant that checks alignment across OKRs, emails, calendar, and weekly plans. \nAlways return valid HTML (no Markdown). \nTreat OKRs as the North Star for evaluation.\nMaintain realistic scope.\n    * Remember you are an assistant tool with limited background context.\n    * Avoid making unsupported assumptions or inventing details.\n    * High-level or abstract insights are still valuable."
            }
          ]
        }
      },
      "credentials": {
        "openAiApi": {
          "id": "zKPOyC2wICv7flD9",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.8
    }
  ],
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Merge2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge1": {
      "main": [
        [
          {
            "node": "Merge2",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge2": {
      "main": [
        [
          {
            "node": "Message a model1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter1": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter2": {
      "main": [
        [
          {
            "node": "Quarterly Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail Code": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Gmail Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Weekly Code": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields1": {
      "main": [
        [
          {
            "node": "Calendar Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail Filter": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Analyze image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze image": {
      "main": [
        [
          {
            "node": "Weekly Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calendar Code": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Quarterly Code": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Get many events": {
      "main": [
        [
          {
            "node": "Edit Fields1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Message a model1": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get many messages",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get many events",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get weekly plan database",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get quarterly okr database",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get many messages": {
      "main": [
        [
          {
            "node": "Gmail Filter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get weekly plan database": {
      "main": [
        [
          {
            "node": "Filter1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get quarterly okr database": {
      "main": [
        [
          {
            "node": "Filter2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

相关工作流