AutomationFlowsAI & RAG › Upwork Job Aggregator with AI Summaries

Upwork Job Aggregator with AI Summaries

Original n8n title: Automated Job Hunter: Upwork Opportunity Aggregator & Ai-powered Notifier

ByYaron Been @yaron-nofluff on n8n.io

This cutting-edge n8n automation is a sophisticated job discovery and notification tool designed to transform freelance job hunting into a seamless, intelligent process. By intelligently connecting Apify, OpenAI, Google Sheets, and Gmail, this workflow: Discovers Job…

Cron / scheduled trigger★★★★☆ complexityAI-powered13 nodesHTTP RequestGoogle SheetsAgentGmailOpenAI ChatOutput Parser Structured
AI & RAG Trigger: Cron / scheduled Nodes: 13 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #4733 — we link there as the canonical source.

This workflow follows the Agent → Gmail 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
{
  "id": "Q4LhFRDraaQuorBs",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Upwork Job Aggregator & Notifier",
  "tags": [],
  "nodes": [
    {
      "id": "834d0a42-1398-4cd4-aaf3-b1164e00b4a8",
      "name": "Daily Upwork Job Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        0,
        0
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a0d54dfe-fc68-4020-b2ed-d191a57d5897",
      "name": "Fetch Upwork Jobs (Apify)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        220,
        0
      ],
      "parameters": {
        "url": "https://api.apify.com/v2/actor-tasks/<YOUR_TASK_ID>/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>",
        "method": "POST",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "a9812fc7-0fa5-492a-91aa-392d0c8ee43b",
      "name": "Format Job Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        440,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "24bd782a-a34f-4b98-8d8f-21763181677b",
              "name": "title",
              "type": "string",
              "value": "={{ $json.title }}"
            },
            {
              "id": "ee879b3d-339a-44c2-9e11-f653edab2e7f",
              "name": "url",
              "type": "string",
              "value": "={{ $json.url }}"
            },
            {
              "id": "b5ff7975-667b-4997-ac8f-acbe9a3b3b85",
              "name": "description",
              "type": "string",
              "value": "={{ $json.description }}"
            },
            {
              "id": "29051fc3-e4f8-4e39-a024-d7b943271acc",
              "name": "budget",
              "type": "string",
              "value": "={{ $json.budget }}"
            },
            {
              "id": "a6492128-a58a-4735-b427-12265f81da3a",
              "name": "datePosted",
              "type": "string",
              "value": "={{ $json.datePosted }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "a996aa35-8f0d-4e1a-997b-4aadd402f65c",
      "name": "Log Jobs to Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        740,
        0
      ],
      "parameters": {
        "columns": {
          "value": {
            "url": "={{ $json.url }}",
            "title": "={{ $json.title }}",
            "budget": "={{ $json.budget }}",
            "datePosted": "={{ $json.datePosted }}",
            "description": "={{ $json.description }}"
          },
          "schema": [
            {
              "id": "title",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "description",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "budget",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "budget",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "datePosted",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "datePosted",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1dEU6uMB4ehiGXjIExjtFQHvUjANRODawKMBGKDaTcEc/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1dEU6uMB4ehiGXjIExjtFQHvUjANRODawKMBGKDaTcEc",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1dEU6uMB4ehiGXjIExjtFQHvUjANRODawKMBGKDaTcEc/edit?usp=drivesdk",
          "cachedResultName": "Upwork Scraper"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "e0cd68e5-4d6d-479a-8a48-1faccc9f3ff7",
      "name": "Summarize Job Listings",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        960,
        0
      ],
      "parameters": {
        "text": "=Provide a summary of the upwork jobs. It should be in email format\n\nTitle: {{ $json.title }}\nURL: {{ $json.url }}\nDescription:{{ $json.description }}\nBudget:{{ $json.budget }}\nDate posted: {{ $json.datePosted }}",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "30002e32-6046-4e5c-a27f-a0d58f380ae9",
      "name": "Send Job Summary Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1500,
        0
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "={{ $json.output.Summary }}",
        "options": {},
        "subject": "={{ $json.output.subject }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "a1fb5d66-b780-4b6b-96be-3391b6196301",
      "name": "OpenAI Job Summarizer",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        900,
        260
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "f79a7336-80fc-4832-862b-51d0d737d5a3",
      "name": "Parse Summary Output",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1160,
        260
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"subject\": \"Upwork Job Opportunity: Webflow Expert Needed for Portfolio Website\",\n  \"Summary\": \"The client is seeking a designer with strong experience in Webflow to create a responsive and elegant portfolio site.\"\n}\n"
      },
      "typeVersion": 1.2
    },
    {
      "id": "85465ead-0a06-455c-9308-866c092d8ef5",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -60,
        -560
      ],
      "parameters": {
        "color": 3,
        "width": 640,
        "height": 760,
        "content": "### \ud83d\udd01 **Section 1: Job Fetch & Preparation**\n\n\ud83d\udce6 **Group Name**: `\ud83d\udce5 Fetch & Prepare Upwork Jobs`\n\n#### \u2705 **Included Nodes:**\n\n1. `\ud83d\udd52 Daily Upwork Job Trigger`\n2. `\ud83c\udf10 Fetch Upwork Jobs (Apify)`\n3. `\ud83d\udee0\ufe0f Format Job Fields`\n\n#### \ud83d\udccb **What this group does:**\n\nThis group is responsible for automatically triggering the job search, pulling fresh job data from Upwork (via Apify), and formatting that data into a clean, structured format.\n\n#### \ud83d\udccc **Highlights:**\n\n* Uses Apify\u2019s `run-sync-get-dataset-items` to ensure you get fresh job results in one go.\n* Ensures only the required fields (like title, URL, budget) are passed forward.\n* Keeps your data clean and minimal for logging and summarization.\n\n---"
      },
      "typeVersion": 1
    },
    {
      "id": "3699ba73-75ee-4bf2-91eb-8d0d05143321",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        680,
        -620
      ],
      "parameters": {
        "color": 5,
        "width": 620,
        "height": 1040,
        "content": "### \ud83d\udcca **Section 2: Data Logging & Summary Generation**\n\n\ud83d\udce6 **Group Name**: `\ud83e\uddfe Log & Summarize Jobs`\n\n#### \u2705 **Included Nodes:**\n\n1. `\ud83d\udcc8 Log Jobs to Google Sheet`\n2. `\ud83e\udd16 Summarize Job Listings`\n\n   * `\ud83e\udde0 OpenAI Job Summarizer`\n   * `\ud83d\udcc4 Parse Summary Output`\n\n#### \ud83d\udccb **What this group does:**\n\nThis group handles the dual responsibility of:\n\n* Persistently logging all job entries to a **Google Sheet**\n* Generating a human-friendly **natural language summary** of the fetched jobs using the OpenAI model and parsing the result into clean output\n\n#### \ud83d\udca1 **Why this matters:**\n\n* Keeps historical records in Sheets \u2705\n* Makes email digest more meaningful and less overwhelming for the reader \ud83e\udde0\n\n---\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "2289feb5-9ab1-4dbb-a77e-f4742f0f341d",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1400,
        -420
      ],
      "parameters": {
        "color": 6,
        "width": 340,
        "height": 600,
        "content": "## \ud83d\udce4 **Section 3: Job Summary Notification**\n\n\ud83d\udce6 **Group Name**: `\u2709\ufe0f Notify via Email`\n\n#### \u2705 **Included Node:**\n\n1. `\ud83d\udce7 Send Job Summary Email`\n\n#### \ud83d\udccb **What this group does:**\n\nSends a **summary email** to the desired recipient(s) with the content generated by the AI agent.\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "95727922-4856-4481-acff-519638ac5d23",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1520,
        -560
      ],
      "parameters": {
        "color": 4,
        "width": 1300,
        "height": 320,
        "content": "=======================================\n            WORKFLOW ASSISTANCE\n=======================================\nFor any questions or support, please contact:\n    Yaron@nofluff.online\n\nExplore more tips and tutorials here:\n   - YouTube: https://www.youtube.com/@YaronBeen/videos\n   - LinkedIn: https://www.linkedin.com/in/yaronbeen/\n=======================================\n"
      },
      "typeVersion": 1
    },
    {
      "id": "c161b105-70a6-431a-91e2-9031ccba8fe4",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1520,
        -220
      ],
      "parameters": {
        "color": 4,
        "width": 1289,
        "height": 3058,
        "content": "# \u2705 n8n Automation: \"Upwork Job Aggregator & Notifier\"\n\n> **Purpose**: Automatically fetch job postings from Upwork with specific keywords, save them in Google Sheets, summarize them using AI, and email the results daily (or at any interval you want).\n\n---\n\n## \ud83e\uddf1 HIGH-LEVEL OVERVIEW\n\n| Feature         | Description                                          |\n| --------------- | ---------------------------------------------------- |\n| \ud83d\udd50 Trigger      | Scheduled (e.g., every 6 hours)                      |\n| \ud83c\udf10 Source       | [Apify](https://apify.com) actor for Upwork scraping |\n| \ud83d\udcc4 Storage      | Google Sheets                                        |\n| \ud83e\udde0 Summary      | OpenAI model with structured output                  |\n| \ud83d\udcec Notification | Gmail with formatted job summary                     |\n\n---\n\n## \ud83e\udde0 GROUP 1: \ud83d\udce5 Fetch & Prepare Upwork Jobs\n\n### \ud83d\udfe2 Nodes:\n\n1. `\ud83d\udd52 Daily Upwork Job Trigger`\n\n   * **Type**: Cron Trigger\n   * **Purpose**: Runs the flow automatically at your set interval (e.g., every 6 hours or daily)\n\n2. `\ud83c\udf10 Fetch Upwork Jobs (Apify)`\n\n   * **Type**: HTTP Request\n   * **Method**: POST\n   * **URL**: `https://api.apify.com/v2/actor-tasks/<TASK_ID>/run-sync-get-dataset-items?token=<API_TOKEN>`\n   * **Purpose**: Calls your Apify Upwork Scraper task to get the latest job listings\n   * **Output**: JSON array of job objects\n\n3. `\ud83d\udee0\ufe0f Format Job Fields`\n\n   * **Type**: Edit Fields (Set or Function Node)\n   * **Purpose**: Extracts needed job fields like `title`, `url`, `description`, `budget`, and `datePosted`\n   * **Reason**: Makes data uniform for Sheet storage and AI summary\n\n---\n\n## \ud83d\udcca GROUP 2: \ud83e\uddfe Log & Summarize Jobs\n\n### \ud83d\udfe2 Nodes:\n\n4. `\ud83d\udcc8 Log Jobs to Google Sheet`\n\n   * **Type**: Google Sheets \u2192 Append Sheet\n   * **Sheet Setup**: Must have headers like `Title`, `URL`, `Description`, `Budget`, `Date`\n   * **Purpose**: Appends each new job as a row in the sheet for historical tracking\n\n5. `\ud83e\udd16 Summarize Job Listings` (AI Agent node group)\n\n   * **Type**: Tools Agent (LangChain / OpenAI Integration)\n   * **Connected Sub-Nodes**:\n\n     * `\ud83e\udde0 OpenAI Job Summarizer` (OpenAI Chat Model)\n\n       * **Prompt** example:\n\n         ```\n         You are an assistant summarizing freelance job postings. Summarize each job in 1-2 lines. Include title, budget, and a short description.\n         ```\n     * `\ud83d\udcc4 Parse Summary Output` (Structured Output Parser)\n\n       * **Purpose**: Converts the AI response into structured n8n items\n   * **Input**: Job data from Google Sheets\n   * **Output**: A clear, natural language summary of all jobs\n\n---\n\n## \ud83d\udce4 GROUP 3: \u2709\ufe0f Notify via Email\n\n### \ud83d\udfe2 Node:\n\n6. `\ud83d\udce7 Send Job Summary Email`\n\n   * **Type**: Gmail \u2192 Send Message\n\n   * **Authentication**: Google OAuth2\n\n   * **To**: Yourself or your team\n\n   * **Subject**: `\"\ud83d\ude80 New Upwork Jobs Found!\"`\n\n   * **Body**:\n\n     ```\n     Hello,\n\n     Here\u2019s a summary of the latest Upwork jobs matching your criteria:\n\n     {{summary from AI}}\n\n     \u2795 View full job list here: [Google Sheet Link]\n\n     Best,  \n     Your Automation Bot \ud83e\udd16\n     ```\n\n   * **Error Handling**: Add an IF node to prevent email if no jobs were returned (optional)\n\n---\n\n## \ud83d\uddc2 Suggested Color-Coded Groups in n8n:\n\n| Group                          | Nodes                                | Color     | Description                     |\n| ------------------------------ | ------------------------------------ | --------- | ------------------------------- |\n| \ud83d\udce5 Fetch & Prepare Upwork Jobs | Trigger, HTTP Request, Format Fields | \ud83d\udfe2 Green  | Gets data and prepares it       |\n| \ud83e\uddfe Log & Summarize Jobs        | Google Sheets, AI Agent, Parser      | \ud83d\udfe1 Yellow | Logs + creates smart summaries  |\n| \u2709\ufe0f Notify via Email            | Gmail                                | \ud83d\udd34 Red    | Notifies you with clean summary |\n\n---\n\n## \ud83d\ude80 ADVANTAGES\n\n\u2705 Completely automated\n\u2705 Saves all job history\n\u2705 AI-enhanced summaries\n\u2705 Instant email alerts\n\u2705 Easy to expand or customize\n\n---\n\n## \ud83e\udde9 Bonus Enhancements (Optional)\n\n| Idea                      | Description                                                   |\n| ------------------------- | ------------------------------------------------------------- |\n| \ud83d\udd0d Add keyword filters    | Add filters before saving to Sheets (e.g., only \u201cReact\u201d jobs) |\n| \ud83d\udd75\ufe0f\u200d\u2642\ufe0f Prevent duplicates | Store job IDs and check before saving                         |\n| \ud83d\udce3 Add Slack alerts       | Add Slack node for team notification                          |\n| \ud83d\udcca Dashboard              | Build Google Data Studio report over the Sheet                |\n\n---\n\n\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "8c929fc6-2198-4adf-89c3-ff0a2b296fdd",
  "connections": {
    "Format Job Fields": {
      "main": [
        [
          {
            "node": "Log Jobs to Google Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Summary Output": {
      "ai_outputParser": [
        [
          {
            "node": "Summarize Job Listings",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Job Summarizer": {
      "ai_languageModel": [
        [
          {
            "node": "Summarize Job Listings",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Summarize Job Listings": {
      "main": [
        [
          {
            "node": "Send Job Summary Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily Upwork Job Trigger": {
      "main": [
        [
          {
            "node": "Fetch Upwork Jobs (Apify)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Jobs to Google Sheet": {
      "main": [
        [
          {
            "node": "Summarize Job Listings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Upwork Jobs (Apify)": {
      "main": [
        [
          {
            "node": "Format Job Fields",
            "type": "main",
            "index": 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

This cutting-edge n8n automation is a sophisticated job discovery and notification tool designed to transform freelance job hunting into a seamless, intelligent process. By intelligently connecting Apify, OpenAI, Google Sheets, and Gmail, this workflow: Discovers Job…

Source: https://n8n.io/workflows/4733/ — 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

This n8n automation workflow automates the creation, scripting, production, and posting of YouTube videos. It leverages AI (OpenAI), image generation (PIAPI), video rendering (Shotstack), and platform

Agent, OpenAI Chat, Airtable Tool +7
AI & RAG

Created by: Peyton Leveillee Last updated: October 2025

OpenAI Chat, Google Sheets, HTTP Request +5
AI & RAG

SEO Blog Article Generation Workflow. Uses outputParserStructured, httpRequest, agent, lmChatOpenAi. Scheduled trigger; 56 nodes.

Output Parser Structured, HTTP Request, Agent +4
AI & RAG

This workflow was born out of a very real problem.

Output Parser Structured, OpenAI Chat, Memory Buffer Window +11
AI & RAG

This workflow automates end-to-end ESG (Environmental, Social, and Governance) sustainability reporting for enterprise sustainability teams, compliance officers, and green governance leads. It solves

Agent, OpenAI Chat, Output Parser Structured +12