AutomationFlowsAI & RAG › Automated Job Hunt with Tavily

Automated Job Hunt with Tavily

ByMay Ramati Kroitero @may-kroitero on n8n.io

Automatically searches for recent job postings (example: “Software Engineering Intern”), extracts structured details from each posting using an AI agent + Tavily, bundles results, and emails a single weekly digest.

Cron / scheduled trigger★★★★☆ complexityAI-powered17 nodesAgentOpenAI Chat@Tavily/N8N Nodes TavilyGmailMemory Buffer WindowOpenAI
AI & RAG Trigger: Cron / scheduled Nodes: 17 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #8616 — 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": "sre2RfUnMtFx3bXB",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Job Postings with Tavily",
  "tags": [],
  "nodes": [
    {
      "id": "374469c4-e958-4be3-977d-b0227a86caa5",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        280,
        0
      ],
      "parameters": {
        "text": "You are an autonomous research agent tasked with monitoring job postings with Tavily API tool.\nYou will interact with the workflow in three stages:\n",
        "options": {
          "systemMessage": "You are an information extraction and formatting specialist.\n\nYou have received job postings retrieved via the Tavily API tool. Your job is to:\n\nCount how many individual job postings are included in the input. Each posting is a separate object with its own title, URL, company, location, description, and other metadata.\n\nThen, for each job posting, extract and format:\n\nJob Title\n\nURL\n\nPosting date (use ISO format: YYYY-MM-DD, if available)\n\nA 2\u20133 sentence summary of the job description\n\n1\u20132 key requirements or highlights\n\nCompany name\n\nCompany description (if provided)\n\nCompany website (if available)\n\nLocation (if provided)\n\nDo not include any hallucinated or assumed data. Only format what's explicitly in the input.\n\nFormat each job posting like this:\n\nJob Posting <number>\nJob Title: <Job Title>\nURL: <URL>\nPosting date: <YYYY-MM-DD>\nJob Description: <Brief description in 2\u20133 sentences>\nKey Requirements:\n<Point 1>\n<Point 2>\nCompany: <Company Name>\nCompany Description: <Short description>\nCompany Website: <URL>\nLocation: <Location>\n--- END JOB POSTING ---\n\nOutput only structured job postings in this format.\n\nYou must process all available job postings in the input. Do not stop early, do not skip entries, and do not truncate the output.\n\nUse only the input below. Do not perform any web searches or add external information.\n"
        },
        "promptType": "define"
      },
      "typeVersion": 2
    },
    {
      "id": "6b53c752-134e-4835-a23a-5426f84cd3fa",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        220,
        220
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {
          "responseFormat": "text"
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "5adcd1ef-64f4-4734-9023-60bbd0d8aede",
      "name": "Search in Tavily",
      "type": "@tavily/n8n-nodes-tavily.tavilyTool",
      "position": [
        520,
        220
      ],
      "parameters": {
        "query": "Roles posted this week for Software Engineering",
        "options": {
          "time_range": "week",
          "max_results": 15,
          "search_depth": "advanced",
          "include_domains": [
            "indeed.com",
            "glassdoor.com",
            "linkedin.com"
          ],
          "include_raw_content": true
        }
      },
      "credentials": {
        "tavilyApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b34a8697-2b7f-4263-b2a9-7234e65c6eb4",
      "name": "Send a message",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1720,
        0
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "={{ \n  $json.data.map(post => {\n    return `Job Posting ${post.posting_number} - ${post.job_title}\n\n\ud83d\udd17 URL: ${post.url}\n\n\ud83d\uddd3\ufe0f Posting Date: ${post.posting_date}\n\n\ud83d\udcdd Job Description:\n${post.job_description}\n\n\ud83d\udccc Requirements:\n${post.requirements && post.requirements.length > 0 \n  ? post.requirements.map((point, i) => `${i + 1}. ${point}`).join('\\n') \n  : 'No requirements available.'}\n\n\ud83c\udfe2 Company Name: ${post.company_name}\n\n\ud83d\udcdd Company Description: ${post.company_description}\n\n\ud83d\udd17 Company Website: ${post.company_website}\n\n\ud83d\udccd Location: ${post.location}\n---`;\n  }).join('\\n\\n')\n}}\n",
        "options": {},
        "subject": "New Jobs for this week!",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "e9b4dfe7-1a60-44e9-a445-f991352b5f9f",
      "name": "Edit Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        680,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "97eac08d-b72e-442b-a537-b092434789e7",
              "name": "Response",
              "type": "string",
              "value": "={{ $json.output }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f2543a75-2680-4cad-a475-fcfdd5d7cb73",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        0,
        0
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtHour": 8
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "cfbddace-b185-47b0-b7d4-85f3961e1d36",
      "name": "Simple Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        380,
        220
      ],
      "parameters": {
        "sessionKey": "1234",
        "sessionIdType": "customKey"
      },
      "typeVersion": 1.3
    },
    {
      "id": "2173e130-cb1b-409b-a8d6-05a16b7864f0",
      "name": "Message a model",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        920,
        0
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=You will receive a block of content containing multiple job postings from the last week. Each post includes a job title, URL, posting date, job description, requirements, company name, company description, compamy website, and location.\n\nYour only task is to structure each job posting into its own block using the exact content provided \u2014 do not rewrite, paraphrase, or shorten anything except for the following exception:\n\nIf company, posting date, company description, or company Website are missing or not specified, you may not use your own knowledge to fill in these four fields only.\n\nUse the following exact format for each mention:\n\nJob Posting <number>\n1. Job Title: <Exact title>\n2. URL: <Exact URL>\n3. Posting Date: <Exact posting date or \"Not specified\">\n4. Job Description: <Exact description as written>\n5. Requirements:\n<Point 1>\n<Point 2>\n(and so on\u2026)\n6. Company Name: <company name>\n7. Company Description: <Company Description>\n8. Company Website: <Company website exactly as written or use your knowledge if not specified>\n9. Location: <location>\n\n10. End each job posting with the line:\n--- END JOB POSTING ---\n\nOnly structure the content \u2014 do not rewrite or shorten any summaries or key points. If a field is not present and not listed as allowed for lookup, write \"Not specified\".\n\nHere is the content to format:\n{{ $json.Response }}"
            }
          ]
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "aa6fd23f-7a66-490d-94b0-5c80e96367c1",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "position": [
        1280,
        0
      ],
      "parameters": {
        "jsCode": "// Collect all inputs\nconst allInputs = $input.all();\n\n// Flatten all job contents into a single string\nconst raw = allInputs\n  .map(item => item.json.message?.content || \"\")\n  .join(\"\\n\\n\");\n\n// If nothing found, stop\nif (!raw.trim()) {\n  return [];\n}\n\n// Split the raw content by job postings\nconst postings = raw\n  .split('--- END JOB POSTING ---')\n  .filter(p => p.trim() !== '');\n\nconst structuredPostings = postings.map((post, index) => {\n  const jobTitle = post.match(/Job Title:\\s*(.+)/)?.[1]?.trim() || \"Not specified\";\n  const url = post.match(/URL:\\s*(.+)/)?.[1]?.trim() || \"Not specified\";\n  const postingDate = post.match(/Posted|Posting Date:\\s*(.+)/)?.[1]?.trim() || \"Not specified\";\n\n  const descriptionMatch = post.match(/Job Description:\\s*([\\s\\S]*?)(?:\\nRequirements:|\\n6\\.)/) ||\n                           post.match(/Job Description:\\s*([\\s\\S]*)/);\n  const jobDescription = descriptionMatch?.[1]?.trim() || \"Not specified\";\n\n  const requirementsMatch = post.match(/Requirements:\\s*([\\s\\S]*?)(?:\\n6\\.|$)/);\n  const requirements = requirementsMatch\n    ? requirementsMatch[1]\n        .split('\\n')\n        .map(r => r.replace(/^-?\\s*/, '').trim())\n        .filter(Boolean)\n    : [];\n\n  const companyName = post.match(/Company Name:\\s*(.+)/)?.[1]?.trim() || \"Not specified\";\n  const companyDescription = post.match(/Company Description:\\s*(.+)/)?.[1]?.trim() || \"Not specified\";\n  const companyWebsite = post.match(/Company Website:\\s*(.+)/)?.[1]?.trim() || \"Not specified\";\n  const location = post.match(/Location:\\s*(.+)/)?.[1]?.trim() || \"Not specified\";\n\n  return {\n    json: {\n      posting_number: index + 1,\n      job_title: jobTitle,\n      url,\n      posting_date: postingDate,\n      job_description: jobDescription,\n      requirements,\n      company_name: companyName,\n      company_description: companyDescription,\n      company_website: companyWebsite,\n      location\n    }\n  };\n});\n\nreturn structuredPostings;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "d19fcd6c-2d59-4023-883a-c9502790eb8f",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1500,
        0
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "d639bcdf-af55-40c5-a536-e37ea241e597",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        -120
      ],
      "parameters": {
        "color": 3,
        "width": 200,
        "height": 100,
        "content": "Runs this workflow automatically at your chosen interval (daily or weekly)"
      },
      "typeVersion": 1
    },
    {
      "id": "d045adcb-fb7d-4605-9701-ffa1e0360c05",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        280,
        -220
      ],
      "parameters": {
        "color": 5,
        "height": 200,
        "content": "Performs a web search for job postings based on your query. You can customize the search for specific job titles or keywords by changing the query, and limit results to a specific time range. Filters results by trusted domains and optional search depth"
      },
      "typeVersion": 1
    },
    {
      "id": "b921a830-831e-4902-83a7-bf7114871286",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        660,
        -140
      ],
      "parameters": {
        "width": 150,
        "height": 120,
        "content": "Collects all search results into a single structured bundle for processing"
      },
      "typeVersion": 1
    },
    {
      "id": "79361797-a2fa-4f76-aae7-1b43256ba2d2",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        920,
        -140
      ],
      "parameters": {
        "color": 3,
        "width": 260,
        "height": 120,
        "content": "Restructures raw job postings into a clean, readable format. Extracts Job Title, Description, Requirements, Company info, and Location"
      },
      "typeVersion": 1
    },
    {
      "id": "04b65e37-b208-4579-b83d-8e17ad6a02dc",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1240,
        -140
      ],
      "parameters": {
        "color": 5,
        "width": 180,
        "height": 120,
        "content": "Splits multiple job postings into individual objects and extracts each field for easy aggregation"
      },
      "typeVersion": 1
    },
    {
      "id": "8ce0186f-cc76-4a90-be4a-11c8e8c1f729",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1480,
        -140
      ],
      "parameters": {
        "width": 150,
        "height": 120,
        "content": "Combines all processed postings into one array for sending in a single email"
      },
      "typeVersion": 1
    },
    {
      "id": "376937ef-599e-4700-a409-0e82df315b5e",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1700,
        -140
      ],
      "parameters": {
        "color": 3,
        "width": 160,
        "height": 120,
        "content": "Sends one consolidated email with all job postings formatted for readability"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "dc38f1d1-760c-47dc-a7f1-ae3fa061618f",
  "connections": {
    "Code": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Message a model",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Message a model": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search in Tavily": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "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

Automatically searches for recent job postings (example: “Software Engineering Intern”), extracts structured details from each posting using an AI agent + Tavily, bundles results, and emails a single weekly digest.

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

Whatsapp Lead Agent. Uses httpRequest, hunter, @tavily/n8n-nodes-tavily, @mendable/n8n-nodes-firecrawl. Webhook trigger; 35 nodes.

HTTP Request, Hunter, @Tavily/N8N Nodes Tavily +11
AI & RAG

This n8n workflow template uses community nodes and is only compatible with the self-hosted version of n8n.

Agent, OpenAI Chat, Memory Buffer Window +2
AI & RAG

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

Mailgun, OpenAI, OpenAI Chat +8
AI & RAG

⚠️ DISCLAIMER: This workflow uses the AnySite LinkedIn community node, which is only available on self-hosted n8n instances. It will not work on n8n.cloud.

OpenAI Chat, Output Parser Structured, Google Sheets +6
AI & RAG

This workflow is for beauty salons who want consistent, high‑quality social media content without writing every post manually. It also suits agencies and automation builders who manage multiple beauty

Telegram, Google Sheets Trigger, Agent +26