Publication d'offres d'emploi avec Tavily
Ceci est unMiscellaneous, AI Summarizationworkflow d'automatisation du domainecontenant 17 nœuds.Utilise principalement des nœuds comme Set, Code, Gmail, Aggregate, Agent. Recherche automatisée d'emplois avec Tavily
- •Compte Google et informations d'identification Gmail API
- •Clé API OpenAI
Nœuds utilisés (17)
{
"id": "sre2RfUnMtFx3bXB",
"meta": {
"instanceId": "2ca4984385c3b4ae87442f36287f909e6c3da21289fc19cfc9b0d35c9fbde67e",
"templateCredsSetupCompleted": true
},
"name": "Job Postings with Tavily",
"tags": [],
"nodes": [
{
"id": "374469c4-e958-4be3-977d-b0227a86caa5",
"name": "Agent IA",
"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–3 sentence summary of the job description\n\n1–2 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–3 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": {
"id": "qlYYPSkolNpxulIN",
"name": "OpenAi account 5"
}
},
"typeVersion": 1.2
},
{
"id": "5adcd1ef-64f4-4734-9023-60bbd0d8aede",
"name": "Recherche dans 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": {
"id": "o9UztDdPrsUey15i",
"name": "Tavily account 4"
}
},
"typeVersion": 1
},
{
"id": "b34a8697-2b7f-4263-b2a9-7234e65c6eb4",
"name": "Envoyer un message",
"type": "n8n-nodes-base.gmail",
"position": [
1720,
0
],
"webhookId": "d3d1135b-2633-4826-b54c-7311445b94e6",
"parameters": {
"sendTo": "may@tavily.com",
"message": "={{ \n $json.data.map(post => {\n return `Job Posting ${post.posting_number} - ${post.job_title}\n\n🔗 URL: ${post.url}\n\n🗓️ Posting Date: ${post.posting_date}\n\n📝 Job Description:\n${post.job_description}\n\n📌 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🏢 Company Name: ${post.company_name}\n\n📝 Company Description: ${post.company_description}\n\n🔗 Company Website: ${post.company_website}\n\n📍 Location: ${post.location}\n---`;\n }).join('\\n\\n')\n}}\n",
"options": {},
"subject": "New Jobs for this week!",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"id": "tJbWRxNBB3mNW43v",
"name": "Gmail account 3"
}
},
"typeVersion": 2.1
},
{
"id": "e9b4dfe7-1a60-44e9-a445-f991352b5f9f",
"name": "Modifier les champs",
"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": "Déclencheur programmé",
"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": "Mémoire simple",
"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 à un modèle",
"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 — 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…)\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 — 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": {
"id": "qlYYPSkolNpxulIN",
"name": "OpenAi account 5"
}
},
"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": "Agrégation",
"type": "n8n-nodes-base.aggregate",
"position": [
1500,
0
],
"parameters": {
"options": {},
"aggregate": "aggregateAllItemData"
},
"typeVersion": 1
},
{
"id": "d639bcdf-af55-40c5-a536-e37ea241e597",
"name": "Note adhésive",
"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": "Note adhésive1",
"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": "Note adhésive2",
"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": "Note adhésive3",
"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": "Note adhésive4",
"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": "Note adhésive5",
"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": "Note adhésive6",
"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,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "dc38f1d1-760c-47dc-a7f1-ae3fa061618f",
"connections": {
"aa6fd23f-7a66-490d-94b0-5c80e96367c1": {
"main": [
[
{
"node": "d19fcd6c-2d59-4023-883a-c9502790eb8f",
"type": "main",
"index": 0
}
]
]
},
"374469c4-e958-4be3-977d-b0227a86caa5": {
"main": [
[
{
"node": "e9b4dfe7-1a60-44e9-a445-f991352b5f9f",
"type": "main",
"index": 0
}
]
]
},
"d19fcd6c-2d59-4023-883a-c9502790eb8f": {
"main": [
[
{
"node": "b34a8697-2b7f-4263-b2a9-7234e65c6eb4",
"type": "main",
"index": 0
}
]
]
},
"e9b4dfe7-1a60-44e9-a445-f991352b5f9f": {
"main": [
[
{
"node": "2173e130-cb1b-409b-a8d6-05a16b7864f0",
"type": "main",
"index": 0
}
]
]
},
"cfbddace-b185-47b0-b7d4-85f3961e1d36": {
"ai_memory": [
[
{
"node": "374469c4-e958-4be3-977d-b0227a86caa5",
"type": "ai_memory",
"index": 0
}
]
]
},
"2173e130-cb1b-409b-a8d6-05a16b7864f0": {
"main": [
[
{
"node": "aa6fd23f-7a66-490d-94b0-5c80e96367c1",
"type": "main",
"index": 0
}
]
]
},
"f2543a75-2680-4cad-a475-fcfdd5d7cb73": {
"main": [
[
{
"node": "374469c4-e958-4be3-977d-b0227a86caa5",
"type": "main",
"index": 0
}
]
]
},
"5adcd1ef-64f4-4734-9023-60bbd0d8aede": {
"ai_tool": [
[
{
"node": "374469c4-e958-4be3-977d-b0227a86caa5",
"type": "ai_tool",
"index": 0
}
]
]
},
"6b53c752-134e-4835-a23a-5426f84cd3fa": {
"ai_languageModel": [
[
{
"node": "374469c4-e958-4be3-977d-b0227a86caa5",
"type": "ai_languageModel",
"index": 0
}
]
]
}
}
}Comment utiliser ce workflow ?
Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.
Dans quelles scénarios ce workflow est-il adapté ?
Avancé - Divers, Résumé IA
Est-ce payant ?
Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.
Workflows recommandés
May Ramati Kroitero
@may-kroiteroI am an AI Engineer at Tavily, where I focus on building AI solutions that integrate real-time web data to power intelligent applications.
Partager ce workflow