AutomationFlowsAI & RAG › Enrich Klicktipp Contact Fields Using Openai Gpt-5.5 and Context

Enrich Klicktipp Contact Fields Using Openai Gpt-5.5 and Context

ByKlickTipp @KlickTipp on n8n.io

This workflow receives an email and a context block, uses OpenAI to extract and validate enrichment details against the existing KlickTipp subscriber record, and then updates approved mapped data fields in KlickTipp. Receives an incoming request from another workflow containing…

Event trigger★★★☆☆ complexityAI-powered8 nodesOpenAI ChatN8N Nodes KlicktippAgentExecute Workflow Trigger
AI & RAG Trigger: Event Nodes: 8 Complexity: ★★★☆☆ AI nodes: yes Added:

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

This workflow follows the Agent → Execute Workflow Trigger 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": "ZOuzSahH9RaZw3or",
  "name": "KlickTipp contact data field enrichment via AI agent",
  "tags": [],
  "nodes": [
    {
      "id": "b63e8132-f9c9-4566-b8a7-6a44fcdacf38",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        208,
        224
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5.5",
          "cachedResultName": "gpt-5.5"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {},
      "typeVersion": 1.3
    },
    {
      "id": "19e6f151-eeb3-408e-8216-61defa4f4a1e",
      "name": "Update contact in KlickTipp",
      "type": "n8n-nodes-klicktipp.klicktippTool",
      "position": [
        512,
        224
      ],
      "parameters": {
        "fields": {
          "dataFields": [
            {
              "fieldId": "=fieldFirstName",
              "fieldValue": "={{\n  $fromAI(\n    'firstName',\n    'Return ONLY the first name. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "=fieldLastName",
              "fieldValue": "={{\n  $fromAI(\n    'lastName',\n    'Return ONLY the last name. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "=fieldCompanyName",
              "fieldValue": "={{\n  $fromAI(\n    'companyName',\n    'Return ONLY the company name. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "fieldStreet1",
              "fieldValue": "={{\n  $fromAI(\n    'street1',\n    'Return ONLY the street 1. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "fieldStreet2",
              "fieldValue": "={{\n  $fromAI(\n    'street2',\n    'Return ONLY the street 2. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "=fieldCity",
              "fieldValue": "={{\n  $fromAI(\n    'city',\n    'Return ONLY the city. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "=fieldState",
              "fieldValue": "={{\n  $fromAI(\n    'state',\n    'Return ONLY the state or region. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "fieldZip",
              "fieldValue": "={{\n  $fromAI(\n    'zip',\n    'Return ONLY the zip. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "fieldCountry",
              "fieldValue": "={{\n  $fromAI(\n    'country',\n    'Return ONLY the country. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "fieldPrivatePhone",
              "fieldValue": "={{\n  $fromAI(\n    'privatePhone',\n    'Return ONLY the private phone number. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "fieldMobilePhone",
              "fieldValue": "={{\n  $fromAI(\n    'mobilePhone',\n    'Return ONLY the mobile phone number. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "fieldPhone",
              "fieldValue": "={{\n  $fromAI(\n    'phone',\n    'Return ONLY the phone number. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "fieldFax",
              "fieldValue": "={{\n  $fromAI(\n    'fax',\n    'Return ONLY the fax number. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "fieldWebsite",
              "fieldValue": "={{\n  $fromAI(\n    'website',\n    'Return ONLY the website URL. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "fieldBirthday",
              "fieldValue": "={{\n  $fromAI(\n    'birthday',\n    'Return ONLY the birthday. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "field221930",
              "fieldValue": "={{\n  $fromAI(\n    'linkedinUrl',\n    'Return ONLY the LinkedIn profile URL. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "field223329",
              "fieldValue": "={{\n  $fromAI(\n    'facebookUrl',\n    'Return ONLY the Facebook profile URL. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "field223328",
              "fieldValue": "={{\n  $fromAI(\n    'instagramUrl',\n    'Return ONLY the Instagram profile URL. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            },
            {
              "fieldId": "field226068",
              "fieldValue": "={{\n  $fromAI(\n    'jobTitle',\n    'Return ONLY the job title. If unknown, return empty.',\n    'string',\n    ''\n  )\n}}"
            }
          ]
        },
        "resource": "subscriber",
        "operation": "update",
        "lookupEmail": "={{ $json.email }}"
      },
      "credentials": {},
      "typeVersion": 3
    },
    {
      "id": "3293f3e1-c344-4550-8e21-70584411902e",
      "name": "AI Enrichment Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        288,
        0
      ],
      "parameters": {
        "text": "={{ $json.context }}",
        "options": {
          "systemMessage": "=1. ROLE / CONTEXT\n- Act as an AI Agent that enriches an existing KlickTipp contact from provided context.\n- The scenario already provides the Email directly to the \"Get Contact\" and \"Update Contact\" tools.\n- You receive:\n  - Context\n  - the existing contact data returned by \"Get Contact\"\n- You have access to:\n  - Get Contact\n  - Update Contact\n\n2. TASK / GOAL\n- Using the provided Context and the contact returned by \"Get Contact\", do the following:\n  1. Extract contact enrichment data from the Context.\n  2. Compare extracted values with the existing contact.\n  3. Decide which fields are safe to update.\n  4. For each supported field, determine the FINAL value that should be kept in KlickTipp.\n  5. Call \"Update Contact\" with those final values.\n\n3. RULES\n- Use only the provided Context and the existing contact data.\n- Do not browse externally.\n- Do not invent facts.\n- Only use values explicitly supported by the Context.\n- Never overwrite a non-empty field unless confidenceScore > 70.\n- If the current field is empty, it may be filled when the Context clearly supports the value.\n- If a value cannot be determined confidently, keep the existing KlickTipp value for that field.\n- Never return an empty string for a field if KlickTipp already has a non-empty value for that field.\n\n4. EXTRACTION\n- Extract relevant contact attributes explicitly supported by the Context.\n- Common enrichment fields include, but are not limited to:\n  - firstName\n  - lastName\n  - companyName\n  - jobTitle\n  - department\n  - country\n  - privatePhone\n  - mobilePhone\n  - phone\n  - fax\n  - website\n  - birthday\n  - linkedinUrl\n  - instagramUrl\n  - facebookUrl\n  - city\n  - state\n- Other fields may also be enriched if they are clearly supported by the Context.\n- Normalize values where reasonable:\n  - trim whitespace\n  - normalize URLs to https when possible\n  - remove obvious tracking parameters\n  - avoid duplicates\n- Only extract values that are clearly present in the Context.\n\n5. CUSTOM FIELD MAPPING\n- Use the custom field mappings below to understand the meaning of custom KlickTipp fields.\n- Only fill a custom field when the Context explicitly supports the value.\n- If a custom field is not mapped below, do not guess its meaning.\n\nExample custom field mappings:\n- field221930 = LinkedIn URL\n- field223328 = Instagram URL\n- field223329 = Facebook URL\n- field226068 = Job Title\n\n6. CONFIDENCE LOGIC\n- Assign a confidenceScore from 0 to 100 for each extracted field.\n- Apply this rule:\n  - if current value is empty and the extracted value is clearly supported -> use the extracted value\n  - if current value is not empty and confidenceScore > 70 -> use the extracted value\n  - otherwise -> keep the existing current value\n- Be conservative with confidence scores.\n\n7. OUTPUT / FINAL VALUE RULE\n- For every supported field, return the FINAL value that should remain in KlickTipp after evaluation.\n- This means:\n  - if update is allowed -> return the new enriched value\n  - if update is not allowed -> return the existing KlickTipp value\n- Do not return blank values unless the field is already blank in KlickTipp and no reliable enrichment is available.\n\n8. TOOL BEHAVIOR\n- The Email for contact lookup is already handled by the scenario configuration.\n- Do not change the contact identity.\n- Do not set \"New Email Address\" unless explicitly supported and required.\n- Call \"Update Contact\" with the final values determined by the rules above.\n\n9. PROCESS\n- Read the provided Context.\n- Review the existing contact data from \"Get Contact\".\n- Extract candidate values from the Context.\n- Compare candidate values with existing KlickTipp values.\n- Decide the final value for each field:\n  - approved new value, or\n  - existing value\n- Send those final values to \"Update Contact\"."
        },
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "46dd7aaf-a5ce-4482-9f24-b30c9a36cdf4",
      "name": "Get contact in KlickTipp",
      "type": "n8n-nodes-klicktipp.klicktippTool",
      "position": [
        368,
        224
      ],
      "parameters": {
        "resource": "subscriber",
        "operation": "get",
        "lookupEmail": "={{ $json.email }}"
      },
      "credentials": {},
      "typeVersion": 3
    },
    {
      "id": "a89bbd15-0159-4dd5-a22b-9ff90f76dcdf",
      "name": "1. Input",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 224,
        "height": 548,
        "content": "## 1. Input"
      },
      "typeVersion": 1
    },
    {
      "id": "16536bab-fa82-4e59-9be9-29c059548a29",
      "name": "Input: Email + Context",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        -16,
        0
      ],
      "parameters": {
        "inputSource": "jsonExample",
        "jsonExample": "{\n  \"email\": \"user@example.com\",\n  \"context\": \"LinkedIn profile summary\\n\\nName: Anna Becker\\nCurrent role: Senior Partnerships Manager at Acme Labs\\nDepartment: Business Development\\nLocation: Berlin, Germany\\n\\nAbout:\\nAnna builds strategic technology partnerships across Europe and works closely with SaaS and automation platforms. She focuses on partner growth, channel development, and co-marketing initiatives.\\n\\nContact details found in source:\\nWebsite: acmelabs.io\\nLinkedIn: linkedin.com/in/anna-becker-partnerships\\nInstagram: instagram.com/annab.partners\\nFacebook: facebook.com/anna.becker.business\\n\\nAdditional notes:\\nPreviously listed employer on older public pages: BrightScale\\nA community post also mentioned Acme Labs as her current company.\"\n}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "6542c11d-d315-4503-86c1-a36bb1c4f89a",
      "name": "2. Agent",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 496,
        "height": 548,
        "content": "## 2. Agent"
      },
      "typeVersion": 1
    },
    {
      "id": "2da2f1e6-2d35-43a0-9b28-26a9bf6cc6b3",
      "name": "Documentation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -784,
        -128
      ],
      "parameters": {
        "width": 679,
        "height": 668,
        "content": "Community Node Disclaimer: This workflow uses KlickTipp community nodes.\n\n## Introduction\nThis workflow enriches existing **KlickTipp contacts** using **OpenAI** and saves approved values back into KlickTipp. It takes an **email address** and a **context block** as input, checks the current contact data with **Get Contact**, and updates only the mapped fields you choose in **Update Contact**.\n\nThis automation is useful for marketers, agencies, sales teams, recruiters, coaches, and service-based businesses that want to improve contact records at scale without manually reviewing every source.\n\n## How it works\n1. **Input: Email + Context**\n2. **OpenAI Agent:** reads the context and compares it with the existing KlickTipp contact\n3. **Get Contact in KlickTipp:** loads the current contact record\n4. **Update Contact in KlickTipp:** saves the final approved field values\n\n## Setup Instructions\n1. **KlickTipp preparation**\n   - Create the **custom fields** you want to update\n   - Decide which fields should be mapped in the **Update Contact in KlickTipp** node\n\n2. **Credential Configuration**\n   - Authenticate your KlickTipp connection with **username/password** credentials\n   - Connect your OpenAI account using an **API key**\n\n## Customization\n- **Confidence threshold**: the prompt currently uses **70%** as the threshold for overwriting existing non-empty values\n- **Mapped fields**: add or remove fields depending on your enrichment use case\n- **Prompt behavior**: adjust the AI prompt if you want stricter or more flexible updates"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "2ee1b34c-f8b4-48b6-8d3f-5bd51ad4940c",
  "nodeGroups": [],
  "connections": {
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Enrichment Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "AI Enrichment Agent": {
      "main": [
        []
      ]
    },
    "Input: Email + Context": {
      "main": [
        [
          {
            "node": "AI Enrichment Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get contact in KlickTipp": {
      "ai_tool": [
        [
          {
            "node": "AI Enrichment Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Update contact in KlickTipp": {
      "ai_tool": [
        [
          {
            "node": "AI Enrichment Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow receives an email and a context block, uses OpenAI to extract and validate enrichment details against the existing KlickTipp subscriber record, and then updates approved mapped data fields in KlickTipp. Receives an incoming request from another workflow containing…

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

Enrich Property Inventory Survey With Image Recognition And Ai Agent. Uses manualTrigger, lmChatOpenAi, airtable, executeWorkflowTrigger. Event-driven trigger; 29 nodes.

OpenAI Chat, Airtable, Execute Workflow Trigger +5
AI & RAG

Manual Http. Uses manualTrigger, lmChatOpenAi, airtable, executeWorkflowTrigger. Event-driven trigger; 29 nodes.

OpenAI Chat, Airtable, Execute Workflow Trigger +5
AI & RAG

⚡📽️ Ultimate AI-Powered Chatbot for YouTube Summarization & Analysis. Uses executeWorkflowTrigger, chatTrigger, stickyNote, memoryBufferWindow. Event-driven trigger; 29 nodes.

Execute Workflow Trigger, Chat Trigger, Memory Buffer Window +4
AI & RAG

This n8n workflow template allows you to interact with an AI agent that extracts details and the transcript of a YouTube video using a provided video ID. Once the details and transcript are retrieved,

Execute Workflow Trigger, Chat Trigger, Memory Buffer Window +4
AI & RAG

This n8n workflow assists property managers and surveyors by reducing the time and effort it takes to complete property inventory surveys.

OpenAI Chat, Airtable, Execute Workflow Trigger +5