Extracteur de CV Intelligent : Google Drive vers Sheet + Mise à jour Slack pour les recruteurs
Ceci est unHR, AI Summarizationworkflow d'automatisation du domainecontenant 19 nœuds.Utilise principalement des nœuds comme Code, Slack, Filter, GoogleDrive, GoogleSheets. Extracteur de CV piloté par l'IA : GPT-4 traite les CVs de Google Drive vers Sheet, avec notification Slack aux recruteurs
- •Token Bot Slack ou URL Webhook
- •Informations d'identification Google Drive API
- •Informations d'identification Google Sheets API
- •Clé API OpenAI
Nœuds utilisés (19)
Catégorie
{
"id": "l2jNtECwrtbXGgzk",
"meta": {
"instanceId": "4a2e6764ba7a6bc9890d9225f4b21d570ce88fc9bd57549c89057fcee58fed0f",
"templateId": "5453",
"templateCredsSetupCompleted": true
},
"name": "Smart CV Extractor: Google Drive to Sheet + Slack Update for Recruiters",
"tags": [
{
"id": "OcQfoQT2ejtrpKfF",
"name": "HR Workflow",
"createdAt": "2025-07-30T05:57:04.113Z",
"updatedAt": "2025-07-30T05:57:04.113Z"
}
],
"nodes": [
{
"id": "2adb6bb1-927a-41f3-ab79-8fb4a5e7e348",
"name": "Note adhésive1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1136,
1680
],
"parameters": {
"width": 604,
"height": 528,
"content": "## 1. Trigger workflow when new profile upload/edit (every 5 mins)\n- Workflow auto trigger when new profile uploaded to Google Drive folder\n- Workflow auto trigger when existing profile upaded in Google Drive folder"
},
"typeVersion": 1
},
{
"id": "b11ef3a7-c2d9-4fb0-b50d-cdf94430de7b",
"name": "Analyseur json",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
240,
2096
],
"parameters": {
"jsonSchemaExample": "{\n \"full_name\": \"\",\n \"job_title\": \"\",\n \"summary\": \"\",\n \"contact\": {\n \"email\": \"\",\n \"phone\": \"\",\n \"address\": \"\",\n \"linkedin\": \"\",\n \"website\": \"\"\n },\n \"education\": [\n {\n \"degree\": \"\",\n \"field_of_study\": \"\",\n \"institution\": \"\",\n \"location\": \"\",\n \"start_year\": \"\",\n \"end_year\": \"\"\n }\n ],\n \"certifications\": [\n {\n \"name\": \"\",\n \"issuer\": \"\",\n \"date_obtained\": \"\",\n \"expiration_date\": \"\"\n }\n ],\n \"work_experience\": [\n {\n \"company\": \"\",\n \"position\": \"\",\n \"location\": \"\",\n \"start_date\": \"\",\n \"end_date\": \"\",\n \"responsibilities\": [\n \"\"\n ],\n \"achievements\": [\n \"\"\n ]\n }\n ],\n \"skills\": {\n \"technical_skills\": [\n \"\"\n ],\n \"soft_skills\": [\n \"\"\n ],\n \"languages\": [\n {\n \"language\": \"\",\n \"proficiency\": \"\"\n }\n ],\n \"tools_and_technologies\": [\n \"\"\n ]\n },\n \"projects\": [\n {\n \"name\": \"\",\n \"description\": \"\",\n \"technologies_used\": [\n \"\"\n ],\n \"role\": \"\",\n \"duration\": \"\"\n }\n ],\n \"awards\": [\n {\n \"title\": \"\",\n \"issuer\": \"\",\n \"date\": \"\",\n \"description\": \"\"\n }\n ],\n \"volunteer_experience\": [\n {\n \"organization\": \"\",\n \"role\": \"\",\n \"description\": \"\",\n \"start_date\": \"\",\n \"end_date\": \"\"\n }\n ],\n \"additional_information\": {\n \"availability\": \"\",\n \"preferred_location\": \"\",\n \"salary_expectation\": \"\",\n \"work_authorization\": \"\",\n \"other_notes\": \"\"\n }\n}"
},
"typeVersion": 1.3
},
{
"id": "ab8a9c8d-02a9-4ea2-875d-e797398c1f18",
"name": "Modèle gpt4-1",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
96,
2096
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "PPSwAKeLQYgAPobT",
"name": "OpenAi account"
}
},
"typeVersion": 1.2
},
{
"id": "71ea426d-de83-47ec-9a91-8203197f0767",
"name": "Agent Analyseur de Profil",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
80,
1904
],
"parameters": {
"text": "=Please extract all relevant information from this candiadte:\nCV Content:\n===\n{{ $json[\"text\"] }}\n===",
"options": {
"systemMessage": ""
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 2.1
},
{
"id": "ee3f6000-fece-4c7c-9793-f11087feb23f",
"name": "Note adhésive7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2528,
1392
],
"parameters": {
"width": 1312,
"height": 1568,
"content": "# CV Extractor: Google Drive to Sheet + Slack Update for Recruiters\nThis workflow automatically processes resumes (PDFs) uploaded or updated in a Google Drive folder. It extracts and structures the candidate’s information using AI, then updates or inserts the data into a Google Sheet, acting as a central talent database. Finally, it notifies the hiring team via Slack with a summary. Perfect for HR and TA teams, this automation eliminates the repetitive task of manually copying candidate details from CVs into spreadsheets, saving hours of admin work every week and keeping your hiring pipeline clean, fast, and up to date.\n## 👤 Who’s it for\nThis workflow is designed for:\n- **Recruiters** and **HR coordinators** who manage candidate profiles via Google Drive.\n- **Talent Acquisition teams** who want to automate CV parsing, enrichment, and database updating.\n- **Companies or hiring agencies** using spreadsheets for candidate tracking and CRM-like HR ops.\n## ⚙️ How it works / What it does\nThis smart and fully automated workflow:\n1. **Monitors a Google Drive folder** for any uploaded or updated resumes (PDFs).\n2. **Downloads and extracts** resume content using PDF parsing.\n3. **Sends the raw text to GPT-4**, which returns a structured profile (name, title, experience, skills, etc.).\n4. **Verifies the profile** and transforms it into a clean, row-based format.\n5. **Upserts the candidate profile** into a Google Sheet (insert or update by email).\n6. **Notifies the hiring team** in Slack or email that a profile was added or updated.\n\nThis is a no-touch pipeline to keep your candidate data clean, current, and centralized.\n## 🛠️ How to set up\n### Step 1: Prepare your Google Drive folder\n- Create a folder like `/SmartHR/cv/`\n- Upload sample resumes in `.pdf` format\n\n### Step 2: Create your Google Sheet\n- Columns to include: `Email`, `FullName`, `JobTitle`, `Phone`, `Location`, `Experience`, `Education`, `Skills`, etc.\n- Optional: Add conditional formatting to highlight updates\n\n### Step 3: Connect the n8n workflow\n- Use the **Google Drive Trigger**:\n - `fileCreated` → new profile uploaded\n - `fileUpdated` → existing profile modified\n- Use **Google Drive (Download file)** to fetch the resume\n- Use **Extract From PDF** to get raw content\n\n### Step 4: Configure GPT-4 node\n- Use the structured system prompt to extract profile information\n- Use `json parser` node to ensure safe formatting for next steps\n\n### Step 5: Transform & Save\n- Use a Function node to map fields to Google Sheet columns\n- Use `Append or update row` (based on email as unique key)\n- Optionally send Slack or email message to notify hiring team\n\n## ✅ Requirements\n\n- 🔑 OpenAI GPT-4 API key\n- 🟩 n8n Cloud or Self-hosted with:\n - Google Drive integration\n - Google Sheets integration\n - Email/Slack credentials (optional)\n- 📄 Resume files in readable PDF format\n- 📊 Google Sheet prepared with relevant headers\n\n## ✏️ How to customize the workflow\n\n| Part | Customization Options |\n|----------------------------|----------------------------------------------------------------------------------------|\n| **GPT Prompt** | Tune for different job levels or fields (e.g., engineers vs marketers) |\n| **Field Mapping** | Update transform node to include other profile fields (LinkedIn, portfolio, etc.) |\n| **Notification** | Switch to Microsoft Teams, Telegram, or email alerts instead of Slack |\n| **Data Store** | Replace Google Sheet with Airtable, Notion, or database system |\n| **Trigger Source** | Trigger from email attachments or webhook instead of Google Drive if needed |\n| **Output Format** | Generate PDF profile cards or summary documents using HTML → PDF node |"
},
"typeVersion": 1
},
{
"id": "7fd3ae9f-c844-49c7-8e06-62361a6b38ed",
"name": "Note adhésive3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1136,
2240
],
"parameters": {
"width": 1020,
"height": 340,
"content": "\n"
},
"typeVersion": 1
},
{
"id": "2cb3c62f-109a-4f60-a2eb-e1511fa403c5",
"name": "Transformer la sortie",
"type": "n8n-nodes-base.code",
"position": [
848,
1920
],
"parameters": {
"jsCode": "const profile = $input.first().json.output\n\n// Get most recent job\nconst work = profile.work_experience || [];\nconst latest = work.length > 0 ? work[0] : {};\n\nfunction formatDate(dateStr) {\n const date = new Date(dateStr);\n return isNaN(date) ? dateStr : `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}`;\n}\n\nfunction getExperienceYears(experiences) {\n if (experiences.length === 0) return '';\n const startDates = experiences.map(e => new Date(e.start_date)).filter(d => !isNaN(d));\n const endDates = experiences.map(e => new Date(e.end_date === 'Present' ? new Date() : e.end_date)).filter(d => !isNaN(d));\n if (startDates.length === 0 || endDates.length === 0) return '';\n const start = new Date(Math.min(...startDates));\n const end = new Date(Math.max(...endDates));\n const diffYears = (end - start) / (1000 * 60 * 60 * 24 * 365);\n return `${Math.floor(diffYears)} years`;\n}\n\nfunction formatEducation(edus) {\n if (!edus || edus.length === 0) return '';\n return edus.map(e => {\n const start = new Date(e.start_year);\n const end = new Date(e.end_year);\n const startYear = isNaN(start) ? '' : start.getFullYear();\n const endYear = isNaN(end) ? '' : end.getFullYear();\n const duration = (startYear && endYear) ? `(${startYear}–${endYear})` : '';\n return `${e.degree} of ${e.field_of_study} at ${e.institution} ${duration}`;\n }).join(' | ');\n}\n\nreturn [\n {\n json: {\n FullName: profile.full_name,\n JobTitle: profile.job_title,\n Email: profile.contact.email.toLowerCase(),\n Phone: profile.contact.phone,\n Location: profile.contact.address,\n LinkedIn: profile.contact.linkedin,\n Education: formatEducation(profile.education),\n Summary: profile.summary,\n MostRecentCompany: latest.company || '',\n MostRecentPosition: latest.position || '',\n StartDate: formatDate(latest.start_date || ''),\n EndDate: formatDate(latest.end_date || ''),\n Skills: (profile.skills?.technical_skills || []).slice(0, 3).join(', '),\n Experience: getExperienceYears(work), \n ProfileUrl: $('Get profile detail').first().json.webContentLink\n }\n }\n];"
},
"typeVersion": 2
},
{
"id": "5936caac-99d3-4f0f-8a12-c37986512879",
"name": "Note adhésive2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-480,
1696
],
"parameters": {
"width": 364,
"height": 512,
"content": "## 2. Extract profile information\n- Download profile form Google Drive\n- Extract profile information from PDF"
},
"typeVersion": 1
},
{
"id": "5279248a-4781-4886-bc50-d8ec4f7cd643",
"name": "Note adhésive5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-48,
1696
],
"parameters": {
"width": 652,
"height": 512,
"content": "## 3. Profile Analyzer\n- Smart agent extract all the information from candidate profile and transform to expected output"
},
"typeVersion": 1
},
{
"id": "a7a8ec4a-dbd9-4c35-ab95-867f62e59605",
"name": "Nouveau profil téléchargé dans le dossier Drive",
"type": "n8n-nodes-base.googleDriveTrigger",
"position": [
-960,
1808
],
"parameters": {
"event": "fileCreated",
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyX",
"unit": "minutes",
"value": 5
}
]
},
"triggerOn": "specificFolder",
"folderToWatch": {
"__rl": true,
"mode": "list",
"value": "1J9GnGlJ70ppf88eZGrhLIo3jxIaqT1u7",
"cachedResultUrl": "https://drive.google.com/drive/folders/1J9GnGlJ70ppf88eZGrhLIo3jxIaqT1u7",
"cachedResultName": "cv"
}
},
"credentials": {
"googleDriveOAuth2Api": {
"id": "fC471es5gk5Mm900",
"name": "Google Drive account"
}
},
"typeVersion": 1
},
{
"id": "b1fa9e0b-0316-4406-bf61-90b7708a6844",
"name": "Obtenir les détails du profil",
"type": "n8n-nodes-base.googleDrive",
"position": [
-464,
1904
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "url",
"value": "={{ $json.webViewLink }}"
},
"options": {},
"operation": "download"
},
"credentials": {
"googleDriveOAuth2Api": {
"id": "fC471es5gk5Mm900",
"name": "Google Drive account"
}
},
"typeVersion": 3
},
{
"id": "406d30ab-65c9-4146-b0f0-b08e37bd448c",
"name": "Ajouter ou mettre à jour une ligne dans la feuille",
"type": "n8n-nodes-base.googleSheets",
"position": [
1072,
1824
],
"parameters": {
"columns": {
"value": {},
"schema": [
{
"id": "FullName",
"type": "string",
"display": true,
"required": false,
"displayName": "FullName",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "JobTitle",
"type": "string",
"display": true,
"required": false,
"displayName": "JobTitle",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Phone",
"type": "string",
"display": true,
"required": false,
"displayName": "Phone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Location",
"type": "string",
"display": true,
"required": false,
"displayName": "Location",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "LinkedIn",
"type": "string",
"display": true,
"required": false,
"displayName": "LinkedIn",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Education",
"type": "string",
"display": true,
"required": false,
"displayName": "Education",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Summary",
"type": "string",
"display": true,
"required": false,
"displayName": "Summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "MostRecentCompany",
"type": "string",
"display": true,
"required": false,
"displayName": "MostRecentCompany",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "MostRecentPosition",
"type": "string",
"display": true,
"required": false,
"displayName": "MostRecentPosition",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "StartDate",
"type": "string",
"display": true,
"required": false,
"displayName": "StartDate",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "EndDate",
"type": "string",
"display": true,
"required": false,
"displayName": "EndDate",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Skills",
"type": "string",
"display": true,
"required": false,
"displayName": "Skills",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Experience",
"type": "string",
"display": true,
"required": false,
"displayName": "Experience",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ProfileUrl",
"type": "string",
"display": true,
"required": false,
"displayName": "ProfileUrl",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "autoMapInputData",
"matchingColumns": [
"Email"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1snHIaidALBJbA_bAxm_SQQLG8vyZ9ZkWFaEOOo3PL6o/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1snHIaidALBJbA_bAxm_SQQLG8vyZ9ZkWFaEOOo3PL6o",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1snHIaidALBJbA_bAxm_SQQLG8vyZ9ZkWFaEOOo3PL6o/edit?usp=drivesdk",
"cachedResultName": "Processed Candidates"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "L670Nly6gZGo71br",
"name": "Google Sheets account 2"
}
},
"typeVersion": 4.6
},
{
"id": "9764a794-6d8b-4252-bc11-03fc0a046f4e",
"name": "Profil existant mis à jour",
"type": "n8n-nodes-base.googleDriveTrigger",
"position": [
-960,
2032
],
"parameters": {
"event": "fileUpdated",
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyX",
"unit": "minutes",
"value": 5
}
]
},
"triggerOn": "specificFolder",
"folderToWatch": {
"__rl": true,
"mode": "list",
"value": "1J9GnGlJ70ppf88eZGrhLIo3jxIaqT1u7",
"cachedResultUrl": "https://drive.google.com/drive/folders/1J9GnGlJ70ppf88eZGrhLIo3jxIaqT1u7",
"cachedResultName": "cv"
}
},
"credentials": {
"googleDriveOAuth2Api": {
"id": "fC471es5gk5Mm900",
"name": "Google Drive account"
}
},
"typeVersion": 1
},
{
"id": "2b27dcdd-d680-4fa7-957b-88f4962633bd",
"name": "Vérifier l'email du profil",
"type": "n8n-nodes-base.filter",
"position": [
464,
1904
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "d03f5a71-8e0c-4196-a6e1-5d5ec7a86894",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.output.contact.email }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "6d0c5fdc-39ec-4258-9532-b0d046288689",
"name": "Extraire les informations du profil",
"type": "n8n-nodes-base.extractFromFile",
"position": [
-240,
1904
],
"parameters": {
"options": {},
"operation": "pdf"
},
"typeVersion": 1
},
{
"id": "b23cfccb-2b21-4a27-9f22-5153ddc533a5",
"name": "Note adhésive",
"type": "n8n-nodes-base.stickyNote",
"position": [
672,
1696
],
"parameters": {
"width": 620,
"height": 512,
"content": "## 4. Upsert record to google sheet\n- Candidate profile has been extract, analyze and transofrm to be able to save in a well-structured format in google sheet for later use"
},
"typeVersion": 1
},
{
"id": "33016c65-9f8d-4bda-9c33-3e71d47873c5",
"name": "Informer l'équipe de recrutement",
"type": "n8n-nodes-base.slack",
"position": [
1072,
2016
],
"webhookId": "3e16b79d-e39e-461f-8718-510eab00b7ea",
"parameters": {
"text": "={{ $json.FullName }} profile has been processed and recorded in Google Drive!",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C098LDNAG1E",
"cachedResultName": "hiring-channel"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"id": "fDHHxMgQm69z0h5T",
"name": "Slack account"
}
},
"typeVersion": 2.3
},
{
"id": "6967ec7b-270b-4902-ac58-ff1512a377a7",
"name": "Note adhésive4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1312,
2016
],
"parameters": {
"width": 1020,
"height": 228,
"content": ""
},
"typeVersion": 1
},
{
"id": "6a1b49d5-3c95-4e20-9b39-404d4cbba960",
"name": "Note adhésive6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1312,
1632
],
"parameters": {
"width": 1020,
"height": 340,
"content": ""
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "e3fa9819-0d17-4a7f-a5b8-59a016d9f6a2",
"connections": {
"b11ef3a7-c2d9-4fb0-b50d-cdf94430de7b": {
"ai_outputParser": [
[
{
"node": "71ea426d-de83-47ec-9a91-8203197f0767",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"ab8a9c8d-02a9-4ea2-875d-e797398c1f18": {
"ai_languageModel": [
[
{
"node": "71ea426d-de83-47ec-9a91-8203197f0767",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"2cb3c62f-109a-4f60-a2eb-e1511fa403c5": {
"main": [
[
{
"node": "406d30ab-65c9-4146-b0f0-b08e37bd448c",
"type": "main",
"index": 0
},
{
"node": "33016c65-9f8d-4bda-9c33-3e71d47873c5",
"type": "main",
"index": 0
}
]
]
},
"b1fa9e0b-0316-4406-bf61-90b7708a6844": {
"main": [
[
{
"node": "6d0c5fdc-39ec-4258-9532-b0d046288689",
"type": "main",
"index": 0
}
]
]
},
"2b27dcdd-d680-4fa7-957b-88f4962633bd": {
"main": [
[
{
"node": "2cb3c62f-109a-4f60-a2eb-e1511fa403c5",
"type": "main",
"index": 0
}
]
]
},
"71ea426d-de83-47ec-9a91-8203197f0767": {
"main": [
[
{
"node": "2b27dcdd-d680-4fa7-957b-88f4962633bd",
"type": "main",
"index": 0
}
]
]
},
"9764a794-6d8b-4252-bc11-03fc0a046f4e": {
"main": [
[
{
"node": "b1fa9e0b-0316-4406-bf61-90b7708a6844",
"type": "main",
"index": 0
}
]
]
},
"6d0c5fdc-39ec-4258-9532-b0d046288689": {
"main": [
[
{
"node": "71ea426d-de83-47ec-9a91-8203197f0767",
"type": "main",
"index": 0
}
]
]
},
"a7a8ec4a-dbd9-4c35-ab95-867f62e59605": {
"main": [
[
{
"node": "b1fa9e0b-0316-4406-bf61-90b7708a6844",
"type": "main",
"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é - Ressources Humaines, 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
Trung Tran
@trungtranHelps small and medium businesses grow with intelligent automation and practical AI tools, no heavy tech team needed.
Partager ce workflow