This workflow corresponds to n8n.io template #11215 — we link there as the canonical source.
This workflow follows the Gmail → Google Docs 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 →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "4359d0c4-5b9c-4119-8f19-747d9ff3a38a",
"name": "When clicking \u2018Execute workflow\u2019",
"type": "n8n-nodes-base.manualTrigger",
"position": [
1712,
1040
],
"parameters": {},
"typeVersion": 1
},
{
"id": "d7744474-582c-42a1-9b20-f0dec9a9d777",
"name": "Get a document",
"type": "n8n-nodes-base.googleDocs",
"position": [
1920,
1040
],
"parameters": {
"operation": "get",
"documentURL": "[PASTE_YOUR_GOOGLE_DOC_ID_HERE]"
},
"typeVersion": 2
},
{
"id": "470aaf71-c1ec-417d-9604-c1d7ce5f69ab",
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"position": [
2144,
1040
],
"parameters": {
"url": "https://api.apify.com/v2/acts/hKByXkMQaC5Qt9UMN/run-sync-get-dataset-items",
"method": "POST",
"options": {
"redirect": {
"redirect": {}
}
},
"jsonBody": "{\n\u00a0 \u00a0 \"count\": 100,\n\u00a0 \u00a0 \"scrapeCompany\": true,\n\u00a0 \u00a0 \"urls\": [\n\u00a0 \u00a0 \u00a0 \u00a0 \"https://www.linkedin.com/jobs/search/?currentJobId=4250801865&geoId=103644278&keywords=ai%20automation&origin=JOB_COLLECTION_PAGE_LOCATION_AUTOCOMPLETE&refresh=true\"\n\u00a0 \u00a0 ]\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Accept",
"value": "application/json"
},
{
"name": "Authorization",
"value": "Bearer [YOUR_APIFY_API_KEY]"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "4677c9a2-d9c9-487f-962b-3f5eefac6f62",
"name": "Message a model",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
2608,
1040
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini",
"cachedResultName": "GPT-4.1-MINI"
},
"options": {
"temperature": 0.7
},
"messages": {
"values": [
{
"role": "system",
"content": "You're a helpful, intelligent job filtering assistant."
},
{
"content": "=I'm looking for jobs. Your task is to filter the based on a list of attributes and skills that I have. Some jobs may not be relevant, which is why I want you to go through each of them and then let me know whether or not I'm an OK fit.\n\nBelow is a block of context about me and my skills:\n\n[INSERT YOUR RESUME SUMMARY AND SKILLS HERE]\n- Skill 1\n- Skill 2\n- Experience Level\n- Location Preferences\n\n--\n\nHere is the job description.\n\n{{ $json.toJsonString() }}\n\n--\n\nRespond in this JSON format:\n\n{\"verdict\":\"true or false\"}\n\nIf I'm a fit, return true. If I'm not a fit, return false (both strings)."
}
]
},
"jsonOutput": true
},
"typeVersion": 1.8
},
{
"id": "d92f445e-5b6b-4bf0-8078-96a1b2a55b04",
"name": "Limit",
"type": "n8n-nodes-base.limit",
"position": [
2336,
1040
],
"parameters": {
"maxItems": 10
},
"typeVersion": 1
},
{
"id": "f803f8f1-db0d-47af-9725-286e22450448",
"name": "Filter",
"type": "n8n-nodes-base.filter",
"position": [
2960,
1040
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "6528ca5e-a675-47a3-b2d5-e8ad4b379e02",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.message.content.verdict }}",
"rightValue": "true"
},
{
"id": "82c07c68-6255-42b9-ab66-68366bff3165",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $('Limit').item.json.companyWebsite }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "1d58798c-e985-4a2f-83c9-4322e1e3568f",
"name": "Message a model1",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
3424,
1040
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1",
"cachedResultName": "GPT-4.1"
},
"options": {
"temperature": 0.7
},
"messages": {
"values": [
{
"role": "system",
"content": "You're a helpful, intelligent resume customization assistant."
},
{
"content": "=\u00a0 I'm looking for jobs. Your task is to customize a provided resume using provided job description.\n\nBelow is a block of context about me and my skills:\n\n[INSERT YOUR RESUME SUMMARY AND SKILLS HERE]\n- Skill 1\n- Skill 2\n- Experience Level\n- Location Preferences\n\n--\n\nHere is the job description.\n\n{{ $('Limit').item.json.toJsonString() }}\n\n--\n\nHere is my resume:\n{{ $('Get a document').item.json.content }}\n\nRespond with inly the customized, updated resume-nothing else.\n\nWrite it in Markdown (atx) format. Do not output any backticks(no ```)"
}
]
}
},
"typeVersion": 1.8
},
{
"id": "f2a1f4b5-e4ca-4a6c-bb6b-95dad446be8b",
"name": "Limit1",
"type": "n8n-nodes-base.limit",
"position": [
3168,
1040
],
"parameters": {
"maxItems": 4
},
"typeVersion": 1
},
{
"id": "2b6d41ec-b727-4339-b5c2-7963f8969fe4",
"name": "Markdown",
"type": "n8n-nodes-base.markdown",
"position": [
1728,
1264
],
"parameters": {
"mode": "markdownToHtml",
"options": {},
"markdown": "={{ $json.message.content }}"
},
"typeVersion": 1
},
{
"id": "0632cffb-4f30-4086-9c97-71528acfaa8e",
"name": "HTTP Request1",
"type": "n8n-nodes-base.httpRequest",
"position": [
2464,
1264
],
"parameters": {
"url": "=[https://www.googleapis.com/upload/drive/v3/files/](https://www.googleapis.com/upload/drive/v3/files/){{ $('Create a document').item.json.id }}?uploadType=media",
"body": "={{ $('Markdown').item.json.data }}",
"method": "PATCH",
"options": {},
"sendBody": true,
"contentType": "raw",
"jsonHeaders": "{\n\u00a0 \"Content-Type\": \"text/html\"\n}",
"sendHeaders": true,
"authentication": "predefinedCredentialType",
"rawContentType": "text/html",
"specifyHeaders": "json",
"nodeCredentialType": "googleDocsOAuth2Api"
},
"typeVersion": 4.2
},
{
"id": "b5195bea-c0a0-48ff-969e-f9dfc836ba43",
"name": "Create a document",
"type": "n8n-nodes-base.googleDocs",
"position": [
1936,
1264
],
"parameters": {
"title": "Tailored Resume - [Candidate Name]",
"folderId": "default"
},
"typeVersion": 2
},
{
"id": "3fac3e8d-f12a-4a95-a22a-65e802a49e38",
"name": "HTTP Request2",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"position": [
2672,
1264
],
"parameters": {
"url": "[https://api.anymailfinder.com/v5.1/find-email/decision-maker](https://api.anymailfinder.com/v5.1/find-email/decision-maker)",
"method": "POST",
"options": {},
"sendBody": true,
"sendHeaders": true,
"bodyParameters": {
"parameters": [
{
"name": "domain",
"value": "={{ $('Limit').item.json.companyWebsite }}"
},
{
"name": "decision_maker_category",
"value": "ceo"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "[YOUR_ANYMAIL_FINDER_API_KEY]"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "357e3231-edcb-4831-884f-e8f8f22dd63a",
"name": "Filter1",
"type": "n8n-nodes-base.filter",
"position": [
2992,
1248
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "4ba14283-df7a-49f5-90d2-8d827b48f7e4",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.email }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "1caa4534-d2ae-4857-a7a1-35cf77855446",
"name": "Create a draft",
"type": "n8n-nodes-base.gmail",
"position": [
3264,
1248
],
"parameters": {
"message": "=Hey {{ $json.person_full_name.split(\" \").first()}}\n\nI know you're hiring right now-Just wanted to tell you i am the right fit for the job.To be upfront: I actually used AI to scrape this job, customize my resume, and ten automatically get your contact details. \n\nI know showing is better then telling, so would be happy to run you/any hiring managers here through the system. If picked, I'd going far above and beyond the job description (and implement system similar to this in {{ $('Limit').item.json.companyName }})\n\nResume below. Let me know what you'd like to do next.\n\n[https://docs.google.com/document/d/](https://docs.google.com/document/d/){{ $('Get a document').item.json.documentId }}\n\nThanks\n",
"options": {},
"subject": "=Re :\u00a0 {{ $('Limit').item.json.title }}",
"resource": "draft"
},
"typeVersion": 2.1
},
{
"id": "7d9e3a95-c940-495a-b73b-4d54770ea557",
"name": "Share file",
"type": "n8n-nodes-base.googleDrive",
"position": [
2144,
1264
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.id }}"
},
"options": {},
"operation": "share",
"permissionsUi": {
"permissionsValues": {
"role": "writer",
"type": "anyone"
}
}
},
"typeVersion": 3
},
{
"id": "ce17ce1c-918c-431c-8d78-8c03a61fd759",
"name": "Main Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
1040,
672
],
"parameters": {
"width": 544,
"height": 992,
"content": "# AI Job Application Agent\n---\n### **Overview**\nThis workflow acts as your personal AI recruiter. It automates the end-to-end process of finding high-quality jobs, tailoring your resume, and drafting personalized outreach emails.\n\n---\n### **How it Works:**\n\n**1. Scrape & Search**\n* Fetches your **\"Master Resume\"** from Google Docs.\n* Uses **Apify** to scrape real-time LinkedIn job postings based on keywords (e.g., \"AI Automation\").\n\n**2. Intelligent Filtering**\n* **AI Screener:** Uses **GPT-4o-mini** to analyze job descriptions against your skills.\n* **Verdict:** Automatically discards jobs if you aren't a fit or company data is missing.\n\n**3. Hyper-Personalization**\n* **Tailoring:** Uses **GPT-4o** to rewrite your resume specifically for the role.\n* **Formatting:** Converts AI output into clean HTML for the document.\n\n**4. Document Generation**\n* Creates a unique **Google Doc** for each application.\n* Uploads the customized resume and sets sharing permissions.\n\n**5. Enrichment & Outreach**\n* **Headhunting:** Uses **Anymail Finder** to locate the CEO/Hiring Manager's email.\n* **Drafting:** Creates a **Gmail** draft with your pitch and resume link.\n\n---\n### **Setup Requirements**\n* **Google Drive/Docs:** Storage & creation.\n* **Apify Account:** LinkedIn Job Scraper.\n* **OpenAI API:** Analysis (GPT-4o).\n* **Anymail Finder:** Email enrichment.\n* **Gmail:** Sending drafts."
},
"typeVersion": 1
},
{
"id": "4e0553e7-cf43-420c-a3b2-b3e2e8d05a9b",
"name": "STICKY 1 \u2013 Input & Scraping",
"type": "n8n-nodes-base.stickyNote",
"position": [
1920,
864
],
"parameters": {
"color": 6,
"width": 250,
"height": 100,
"content": "Fetches your master resume, scrapes LinkedIn job postings, and prepares raw data for further AI-based filtering."
},
"typeVersion": 1
},
{
"id": "8494c30e-e11e-4977-9e38-f95d6d2ed6ef",
"name": "STICKY 2 \u2013 AI Filtering",
"type": "n8n-nodes-base.stickyNote",
"position": [
2720,
864
],
"parameters": {
"color": 6,
"width": 250,
"height": 100,
"content": "GPT analyzes each job description, removes irrelevant leads, and limits results to the top matches."
},
"typeVersion": 1
},
{
"id": "8072f0a9-181b-4d44-ba07-b379f222be25",
"name": "STICKY 3 \u2013 Resume Writer",
"type": "n8n-nodes-base.stickyNote",
"position": [
3424,
864
],
"parameters": {
"color": 6,
"width": 250,
"height": 100,
"content": "GPT rewrites your resume based on the selected job description and converts the final output into HTML."
},
"typeVersion": 1
},
{
"id": "2839f919-d981-4613-b628-276152b91217",
"name": "STICKY 4 \u2013 Google Docs",
"type": "n8n-nodes-base.stickyNote",
"position": [
2112,
1440
],
"parameters": {
"color": 6,
"width": 250,
"height": 100,
"content": "Creates a Google Doc, uploads the rewritten resume, and adjusts sharing settings."
},
"typeVersion": 1
},
{
"id": "416df9bd-40e2-4161-85b3-3b652a32803f",
"name": "STICKY 5 \u2013 Email Outreach",
"type": "n8n-nodes-base.stickyNote",
"position": [
2912,
1440
],
"parameters": {
"color": 6,
"width": 250,
"height": 100,
"content": "Finds the CEO\u2019s verified email via Anymail, validates it, and creates a cold email draft in Gmail."
},
"typeVersion": 1
}
],
"connections": {
"Limit": {
"main": [
[
{
"node": "Message a model",
"type": "main",
"index": 0
}
]
]
},
"Filter": {
"main": [
[
{
"node": "Limit1",
"type": "main",
"index": 0
}
]
]
},
"Limit1": {
"main": [
[
{
"node": "Message a model1",
"type": "main",
"index": 0
}
]
]
},
"Filter1": {
"main": [
[
{
"node": "Create a draft",
"type": "main",
"index": 0
}
]
]
},
"Markdown": {
"main": [
[
{
"node": "Create a document",
"type": "main",
"index": 0
}
]
]
},
"Share file": {
"main": [
[
{
"node": "HTTP Request1",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Limit",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request1": {
"main": [
[
{
"node": "HTTP Request2",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request2": {
"main": [
[
{
"node": "Filter1",
"type": "main",
"index": 0
}
]
]
},
"Get a document": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"Message a model": {
"main": [
[
{
"node": "Filter",
"type": "main",
"index": 0
}
]
]
},
"Message a model1": {
"main": [
[
{
"node": "Markdown",
"type": "main",
"index": 0
}
]
]
},
"Create a document": {
"main": [
[
{
"node": "Share file",
"type": "main",
"index": 0
}
]
]
},
"When clicking \u2018Execute workflow\u2019": {
"main": [
[
{
"node": "Get a document",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Stop applying manually. This workflow acts as your personal AI recruiter, automating the end-to-end process of finding high-quality jobs, tailoring your resume, and preparing personalized outreach emails to decision-makers.
Source: https://n8n.io/workflows/11215/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
What it is An automated LinkedIn content system that takes a simple form (idea + optional file), generates LinkedIn posts with OpenAI, stores them in Notion, builds Google Slides carousels, and auto-p
Listens for completed Fireflies transcripts, qualifies whether a proposal is needed using OpenAI, drafts structured proposal content, populates a Google Doc template, converts to PDF, and sends it to
Streamlit Logibot. Uses notion, ollamaChatModel, lmChatOllama, googleDrive. Event-driven trigger; 29 nodes.
Overview
💥 Automate YouTube thumbnail creation from video links -vide. Uses telegramTrigger, httpRequest, googleDrive, gmail. Event-driven trigger; 25 nodes.