How to Build an AI Influencer Discovery Agent with n8n (Free Template)

How to Build an AI Influencer Discovery Agent with n8n (Free Template)

Finding the right influencers for marketing campaigns wastes hours of manual research. You scroll through profiles, check engagement rates, verify authenticity, and still end up with questionable matches. This n8n AI agent automates the entire discovery process—from campaign brief to ranked CSV of vetted influencers. You'll learn how to build an intelligent filtering system that delivers campaign-ready creator lists in minutes, not days.

The Problem: Manual Influencer Discovery Doesn't Scale

Marketing teams spend 8-15 hours per campaign manually searching for influencers across Instagram and TikTok. The process involves opening dozens of profiles, checking follower counts, calculating engagement rates, and making subjective judgments about brand fit.

Current challenges:

  • No systematic way to filter out fake accounts, bots, or inappropriate content
  • Inconsistent evaluation criteria across team members
  • Missing contact information requires additional research time
  • No documentation of why specific influencers were selected or rejected
  • Impossible to reuse discovery logic across multiple campaigns

Business impact:

  • Time spent: 10-15 hours per campaign on manual research
  • Inconsistent results: Different team members find different creators
  • Missed opportunities: Quality influencers overlooked in manual searches
  • Wasted outreach: Contacting creators who don't fit brand guidelines

The Solution Overview

This n8n AI agent transforms a simple campaign brief into a scored, filtered list of influencer recommendations. The workflow integrates social media discovery APIs, applies multi-layered filtering rules, and uses AI to evaluate brand fit. Each recommended influencer includes contact details, engagement metrics, and a specific explanation of why they match your campaign. The system runs autonomously and can be reused across unlimited campaigns with different briefs.

What You'll Build

This influencer discovery agent delivers a complete vetting and ranking system for Instagram and TikTok creators.

Component Technology Purpose
Input Interface n8n Webhook/Manual Trigger Campaign brief submission
Discovery Engine Social Media APIs (Instagram/TikTok) Find candidate influencers by niche/keywords
Content Filter AI Analysis + Rule Engine Remove explicit, political, fake accounts
Scoring System Custom JavaScript Logic Rank influencers by campaign fit
Contact Enrichment Email Finder APIs Locate creator contact information
Output Generator CSV Builder Structured influencer recommendations
AI Evaluator OpenAI/Claude Integration Explain why each influencer fits the brief

Key capabilities:

  • Processes campaign briefs with niche, geography, and follower requirements
  • Searches Instagram and TikTok using platform APIs or third-party discovery tools
  • Filters out accounts with explicit content, political posts, or bot-like behavior
  • Enforces minimum follower thresholds (configurable, default 1,000+)
  • Calculates engagement rates and audience quality scores
  • Finds creator email addresses for outreach
  • Generates explanations for each recommendation using AI
  • Outputs CSV with handle, platform, profile link, email, followers, engagement, niche tags, score, and fit reason

Prerequisites

Before starting, ensure you have:

  • n8n instance (cloud or self-hosted version 1.0+)
  • Social media discovery API access (RapidAPI Social Media APIs, Apify Instagram/TikTok scrapers, or similar)
  • OpenAI API key (GPT-4 recommended) or Anthropic Claude API access
  • Email finder service account (Hunter.io, Snov.io, or Apollo.io)
  • Basic JavaScript knowledge for custom scoring logic
  • Understanding of API rate limits and quota management

Step 1: Set Up Campaign Brief Input

The workflow begins with a structured input that captures campaign requirements. This determines all downstream filtering and scoring.

Configure the Webhook Trigger

  1. Add a Webhook node as your workflow trigger
  2. Set HTTP Method to POST
  3. Set Path to /influencer-discovery
  4. Enable "Respond Immediately" to confirm receipt

Expected input structure:

{
  "campaign_name": "Summer Fashion Launch",
  "niche": "sustainable fashion, eco-friendly lifestyle",
  "platforms": ["instagram", "tiktok"],
  "geography": "UK",
  "min_followers": 1000,
  "max_followers": 100000,
  "target_count": 20
}

Why this works:
The structured brief ensures consistent agent behavior across campaigns. The niche field drives API search queries. Geography and follower ranges create hard filters. Target count determines how many results to return after scoring.

Step 2: Discover Candidate Influencers

This phase queries social media APIs to build an initial pool of creators matching the campaign niche.

Configure Social Media API Nodes

  1. Add HTTP Request nodes for each platform (Instagram, TikTok)
  2. Use search endpoints with niche keywords from the brief
  3. Set pagination to retrieve 100-200 candidates per platform
  4. Parse responses to extract: username, profile URL, follower count, bio, recent post data

Instagram API configuration example:

// HTTP Request Node Settings
Method: GET
URL: https://instagram-api.p.rapidapi.com/search/users
Headers: {
  "X-RapidAPI-Key": "{{$credentials.rapidapi.apiKey}}",
  "X-RapidAPI-Host": "instagram-api.p.rapidapi.com"
}
Query Parameters: {
  "query": "{{$json.niche}}",
  "country": "{{$json.geography}}"
}

Why this approach:
Casting a wide net initially (100-200 candidates) ensures you don't miss quality creators due to API search limitations. The filtering stages will narrow this down to your target count. Always retrieve recent post data—you'll need it for engagement calculations and content analysis.

Common issues:

  • API rate limits: Implement 2-second delays between requests using Wait nodes
  • Incomplete data: Some APIs don't return email addresses—you'll enrich these later
  • Geography filtering: Not all APIs support location parameters; add a post-processing filter if needed

Step 3: Apply Content and Quality Filters

This critical phase removes influencers who violate brand safety guidelines or show signs of fake engagement.

Configure AI Content Analysis

  1. Add an OpenAI node after data collection
  2. Set Model to gpt-4 for better content understanding
  3. Create a prompt that analyzes profile bio and recent post captions
  4. Return a structured JSON with filter flags

Content filter prompt:

Analyze this influencer profile for brand safety:

Username: {{$json.username}}
Bio: {{$json.bio}}
Recent posts: {{$json.recent_captions}}

Return JSON with these boolean flags:
{
  "has_explicit_content": false,
  "has_political_content": false,
  "appears_fake": false,
  "reason": "Brief explanation if any flag is true"
}

Criteria:
- Explicit: Sexual content, profanity, drug references
- Political: Partisan posts, activism, controversial stances
- Fake: Bio full of emojis, generic comments, follower/engagement ratio < 0.01

Configure Rule-Based Filters

Add an IF node after AI analysis with these conditions:

  • Follower count >= campaign brief minimum (e.g., 1,000)
  • Follower count <= campaign brief maximum (if specified)
  • AI flags: has_explicit_content === false
  • AI flags: has_political_content === false
  • AI flags: appears_fake === false
  • Engagement rate > 1% (calculated as: avg_likes / followers * 100)

Why this works:
AI handles nuanced content analysis that rule-based systems miss. A profile might not contain explicit keywords but still violate brand safety through context. The engagement rate filter catches purchased followers—real audiences engage at 1-5%, fake followers rarely exceed 0.5%.

Variables to customize:

  • min_engagement_rate: Increase to 2% for higher quality, decrease to 0.5% for larger follower counts
  • explicit_content_threshold: Adjust AI sensitivity based on brand tolerance

Step 4: Score and Rank Influencers

This phase assigns numerical scores based on campaign fit, then ranks candidates from best to worst match.

Configure Scoring Logic

Add a Function node with this scoring algorithm:

// Scoring weights (total = 100 points)
const WEIGHTS = {
  follower_fit: 20,      // How close to ideal follower range
  engagement_rate: 30,   // Higher engagement = better
  niche_match: 30,       // Bio/content alignment with brief
  content_quality: 20    // Post consistency and professionalism
};

const item = $input.item.json;
const brief = $('Webhook').item.json;

// Calculate follower fit score (0-20)
const ideal_followers = (brief.min_followers + brief.max_followers) / 2;
const follower_distance = Math.abs(item.followers - ideal_followers) / ideal_followers;
const follower_score = Math.max(0, 20 - (follower_distance * 20));

// Calculate engagement score (0-30)
const engagement_rate = item.engagement_rate; // Already calculated
const engagement_score = Math.min(30, engagement_rate * 6); // 5% = 30 points

// Calculate niche match score (0-30) - from AI analysis
const niche_score = item.ai_niche_relevance * 30; // AI returns 0-1

// Calculate content quality score (0-20)
const quality_score = item.ai_content_quality * 20; // AI returns 0-1

// Total score
const total_score = follower_score + engagement_score + niche_score + quality_score;

return {
  ...item,
  score: Math.round(total_score),
  score_breakdown: {
    follower_fit: Math.round(follower_score),
    engagement: Math.round(engagement_score),
    niche_match: Math.round(niche_score),
    content_quality: Math.round(quality_score)
  }
};

Add AI Niche Relevance Analysis

Before the scoring node, add another OpenAI node:

Campaign niche: {{$('Webhook').item.json.niche}}
Influencer bio: {{$json.bio}}
Recent post topics: {{$json.recent_topics}}

Rate niche relevance from 0.0 to 1.0:
- 1.0 = Perfect match, posts exclusively about this niche
- 0.7 = Strong match, frequently posts about this niche
- 0.4 = Moderate match, occasionally posts about this niche
- 0.0 = No match, never posts about this niche

Return only the number.

Why this approach:
The weighted scoring system balances multiple factors. Engagement rate gets the highest weight (30%) because it indicates real audience connection. Niche match is equally important—an influencer with great engagement in the wrong niche wastes budget. Follower fit prevents recommending creators too large or too small for campaign goals.

Step 5: Enrich Contact Information

Most social APIs don't provide email addresses. This phase finds creator contact details for outreach.

Configure Email Finder Integration

  1. Add HTTP Request node for Hunter.io or similar service
  2. Input: influencer username or profile URL
  3. Output: email address, confidence score, source
  4. Filter: Only accept emails with confidence > 70%

Hunter.io configuration:

Method: GET
URL: https://api.hunter.io/v2/email-finder
Query Parameters: {
  "domain": "instagram.com",
  "first_name": "{{$json.username}}",
  "api_key": "{{$credentials.hunter.apiKey}}"
}

Fallback strategy:
If email finder returns no results:

  1. Check profile bio for email addresses using regex: /[\w\.-]+@[\w\.-]+\.\w+/
  2. Check profile link for contact page URLs
  3. Mark as "Contact via DM" if no email found

Why this matters:
Email outreach converts 3-5x better than social media DMs for partnership proposals. The confidence score prevents wasting time on invalid addresses. Always include a fallback—missing contact info shouldn't disqualify otherwise perfect influencers.

Step 6: Generate AI Fit Explanations

The final AI step creates human-readable explanations for why each influencer was selected.

Configure Explanation Generator

Add OpenAI node with this prompt:

Campaign brief: {{$('Webhook').item.json.campaign_name}}
Target niche: {{$('Webhook').item.json.niche}}
Target geography: {{$('Webhook').item.json.geography}}

Influencer profile:
- Username: {{$json.username}}
- Platform: {{$json.platform}}
- Followers: {{$json.followers}}
- Engagement rate: {{$json.engagement_rate}}%
- Bio: {{$json.bio}}
- Recent topics: {{$json.recent_topics}}
- Score: {{$json.score}}/100

Write a 2-sentence explanation of why this influencer is a good fit for the campaign. Focus on specific alignment between their content and the campaign niche. Be concrete, not generic.

Example: "Posts weekly sustainable fashion hauls featuring UK eco-brands, with strong engagement from environmentally conscious audience. Recent collaboration with similar brand shows proven ability to drive conversions in this niche."

Why this works:
Generic explanations like "good engagement rate" don't help campaign managers make decisions. Specific references to content themes, audience demographics, and past brand collaborations provide actionable context. The 2-sentence limit forces clarity—longer explanations don't get read.

Step 7: Build and Export CSV Output

The final phase structures all data into a campaign-ready spreadsheet.

Configure CSV Builder

  1. Add a Function node to format data
  2. Sort influencers by score (highest first)
  3. Limit to target_count from campaign brief
  4. Structure columns in this order:
const sortedInfluencers = $input.all()
  .sort((a, b) => b.json.score - a.json.score)
  .slice(0, $('Webhook').item.json.target_count);

return sortedInfluencers.map(item => ({
  rank: sortedInfluencers.indexOf(item) + 1,
  username: item.json.username,
  platform: item.json.platform,
  profile_url: item.json.profile_url,
  email: item.json.email || 'Contact via DM',
  followers: item.json.followers,
  engagement_rate: item.json.engagement_rate + '%',
  niche_tags: item.json.niche_tags.join(', '),
  score: item.json.score,
  fit_reason: item.json.fit_explanation
}));
  1. Add a Spreadsheet File node
  2. Set format to CSV
  3. Set filename to: {{$('Webhook').item.json.campaign_name}}_influencers_{{$now.format('YYYY-MM-DD')}}.csv

Why this structure:
The rank column provides instant prioritization. Email placement near the front enables quick copy-paste for outreach tools. The fit_reason column at the end allows campaign managers to scan scores first, then read explanations for top candidates. Date-stamped filenames prevent confusion when running multiple campaigns.

Workflow Architecture Overview

This workflow consists of 15-20 nodes organized into 6 main sections:

  1. Input processing (Nodes 1-2): Webhook receives campaign brief, validates required fields
  2. Candidate discovery (Nodes 3-6): Parallel API calls to Instagram and TikTok discovery services
  3. Content filtering (Nodes 7-10): AI analysis for brand safety, rule-based follower/engagement filters
  4. Scoring and ranking (Nodes 11-13): AI niche relevance scoring, weighted algorithm, sort by total score
  5. Contact enrichment (Nodes 14-15): Email finder API, fallback bio parsing
  6. Output generation (Nodes 16-18): AI fit explanations, CSV formatting, file export

Execution flow:

  • Trigger: Webhook POST with campaign brief JSON
  • Average run time: 3-5 minutes for 20 influencers (depends on API response times)
  • Key dependencies: Social media discovery API, OpenAI/Claude, email finder service

Critical nodes:

  • HTTP Request (Social APIs): Handles platform-specific search queries and pagination
  • OpenAI (Content Filter): Analyzes profiles for explicit, political, or fake content
  • Function (Scoring): Applies weighted algorithm to rank influencers by campaign fit
  • OpenAI (Fit Explanation): Generates human-readable reasons for each recommendation
  • Spreadsheet File: Builds final CSV with all influencer data and rankings

The complete n8n workflow JSON template is available at the bottom of this article.

Critical Configuration Settings

Social Media API Integration

Required fields:

  • API Key: Your RapidAPI or Apify API key
  • Rate limit: 100 requests/hour (adjust Wait nodes accordingly)
  • Timeout: 30 seconds per request (increase for slow APIs)

Common issues:

  • Using free tier APIs → Results in incomplete data or rate limit errors
  • Not handling pagination → Misses quality influencers beyond first page
  • Always retrieve at least 100 candidates per platform for adequate filtering

OpenAI Configuration

Model selection:

  • GPT-4: Best accuracy for content analysis and niche matching ($0.03/1K tokens)
  • GPT-3.5-turbo: Faster and cheaper but less nuanced ($0.002/1K tokens)
  • Recommended: GPT-4 for content filtering, GPT-3.5-turbo for fit explanations

Temperature settings:

  • Content filtering: 0.1 (consistent, conservative decisions)
  • Fit explanations: 0.7 (more natural, varied language)

Scoring Algorithm Customization

Variables to adjust:

const WEIGHTS = {
  follower_fit: 20,      // Increase if follower count is critical
  engagement_rate: 30,   // Increase for engagement-focused campaigns
  niche_match: 30,       // Increase for highly specialized niches
  content_quality: 20    // Increase for premium brand partnerships
};

Why this matters:
Different campaign types need different priorities. A brand awareness campaign values follower count more (increase follower_fit to 30, decrease engagement to 20). A conversion-focused campaign needs high engagement (keep at 30 or increase to 40). Adjust weights based on campaign goals, but ensure total always equals 100.

Testing & Validation

Component testing:

  1. Test input validation: Send webhook with missing fields, verify error handling
  2. Test API responses: Check that social media APIs return expected data structure
  3. Test content filters: Manually review 10-20 filtered profiles to confirm accuracy
  4. Test scoring logic: Verify that high-scoring influencers genuinely match campaign brief
  5. Test email finder: Confirm email addresses are valid (send test emails to sample)

Quality checks:

Run the workflow with a known campaign brief where you've manually identified good influencers. Compare agent output to your manual list:

  • Are your top picks in the agent's top 10?
  • Are obvious mismatches filtered out?
  • Do fit explanations make sense?

Common issues and fixes:

Issue Cause Solution
All influencers filtered out Filters too strict Lower min_followers, reduce engagement threshold
Low-quality recommendations Scoring weights misaligned Increase niche_match weight, add content_quality analysis
Missing email addresses Email finder API limits Add bio parsing fallback, increase API quota
Slow execution (>10 min) Too many API calls Reduce candidate pool size, add parallel processing

Production Deployment Checklist

Area Requirement Why It Matters
Error Handling Retry logic with exponential backoff on API nodes Prevents workflow failure on temporary API outages
Monitoring Webhook health checks every hour Detect failures within 1 hour vs discovering issues days later
API Quotas Track usage across all services Avoid mid-campaign quota exhaustion
Data Privacy Store campaign briefs and results in secure database Comply with client confidentiality requirements
Documentation Comment each node with purpose and configuration notes Reduces modification time by 3-5 hours when updating
Version Control Export workflow JSON after each change Enables rollback if updates break functionality

Production setup:

  1. Move from manual trigger to scheduled webhook endpoint
  2. Add error notification via Slack or email when workflow fails
  3. Implement logging to track which campaigns have been processed
  4. Set up API key rotation schedule for security
  5. Create campaign brief templates for common use cases

Real-World Use Cases

Use Case 1: E-commerce Product Launch

  • Industry: Direct-to-consumer beauty brand
  • Scale: 50 influencers needed across micro (1K-10K) and mid-tier (10K-100K)
  • Modifications needed: Add two workflow runs with different follower ranges, merge results, add product category tags to niche field

Use Case 2: Local Business Awareness

  • Industry: Restaurant chain expansion
  • Scale: 20 local food bloggers per city
  • Modifications needed: Add city-level geography filtering, prioritize geo-tagged posts in scoring, reduce follower minimum to 500

Use Case 3: B2B SaaS Thought Leadership

  • Industry: Enterprise software
  • Scale: 10-15 LinkedIn and Twitter influencers in specific tech niches
  • Modifications needed: Replace Instagram/TikTok APIs with LinkedIn/Twitter APIs, adjust content filters for professional context, add company affiliation check

Use Case 4: Seasonal Campaign Refresh

  • Industry: Fashion retail
  • Scale: 30 influencers every quarter with rotating seasonal themes
  • Modifications needed: Store previous campaign results, add deduplication filter to find new creators, schedule quarterly automatic runs

Customizing This Workflow

Alternative Integrations

Instead of RapidAPI Social Media APIs:

  • Apify Instagram/TikTok Scrapers: Best for larger data volumes - requires changing HTTP Request nodes to Apify API calls
  • Phyllo API: Better for verified creator data with earnings info - swap out nodes 3-6, add authentication headers
  • Manual CSV upload: Use when working with existing influencer lists - replace Webhook with CSV trigger node

Workflow Extensions

Add automated outreach:

  • Add email sending nodes after CSV generation
  • Connect to Gmail or SendGrid API
  • Personalize email templates using fit_explanation field
  • Nodes needed: +4 (Loop, Email, Set, Wait for rate limiting)

Add campaign performance tracking:

  • Store recommended influencers in database (Airtable, PostgreSQL)
  • Add webhook for campaign managers to mark which influencers were contacted
  • Track response rates and conversion metrics
  • Performance improvement: Feedback loop improves future scoring accuracy

Add competitor analysis:

  • Scrape competitor brand mentions and tagged posts
  • Identify influencers already promoting similar products
  • Add "proven converter" flag to scoring
  • Nodes needed: +6 (HTTP Request for scraping, Function for analysis, Set for flags)

Integration possibilities:

Add This To Get This Complexity
Airtable database Campaign history and influencer relationship tracking Easy (3 nodes)
Slack notifications Real-time alerts when high-scoring influencers are found Easy (2 nodes)
Google Sheets sync Live dashboard for marketing team collaboration Medium (5 nodes)
CRM integration (HubSpot) Automatic contact creation for outreach sequences Medium (7 nodes)
Instagram DM automation Direct outreach for influencers without email Hard (10+ nodes, requires Instagram API approval)

Scaling considerations:

For campaigns requiring 100+ influencers:

  • Implement batch processing (20 influencers per batch)
  • Add parallel execution branches for faster processing
  • Use database storage instead of CSV for intermediate results
  • Expected performance: Process 100 influencers in 8-12 minutes vs 25-30 minutes sequential

For multi-platform expansion (YouTube, Twitter, LinkedIn):

  • Create platform-specific discovery branches
  • Normalize data structures across platforms in merge node
  • Adjust scoring weights per platform (engagement rates vary significantly)
  • Complexity: +8-12 nodes per additional platform

Get Started Today

Ready to automate your influencer discovery process?

  1. Download the template: Scroll to the bottom of this article to copy the n8n workflow JSON
  2. Import to n8n: Go to Workflows → Import from URL or File, paste the JSON
  3. Configure your services: Add API credentials for social media discovery, OpenAI, and email finder
  4. Test with sample data: Run with a test campaign brief to verify all filters and scoring work correctly
  5. Deploy to production: Activate the webhook and start submitting real campaign briefs

Need help customizing this workflow for your specific influencer marketing needs? Schedule an intro call with Atherial to discuss enterprise implementations, custom scoring algorithms, or multi-platform expansion.

Complete N8N Workflow Template

Copy the JSON below and import it into your N8N instance via Workflows → Import from File

{
  "name": "AI Influencer Discovery Agent",
  "nodes": [
    {
      "id": "webhook-trigger",
      "name": "Campaign Brief Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        250,
        300
      ],
      "parameters": {
        "path": "influencer-discovery",
        "responseCode": 200,
        "responseMode": "onReceived"
      },
      "typeVersion": 2
    },
    {
      "id": "parse-input",
      "name": "Parse Campaign Parameters",
      "type": "n8n-nodes-base.set",
      "position": [
        450,
        300
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "campaign_brief",
              "name": "campaign_brief",
              "value": "={{ $json.brief }}"
            },
            {
              "id": "geography",
              "name": "geography",
              "value": "={{ $json.geography || 'Global' }}"
            },
            {
              "id": "follower_min",
              "name": "follower_min",
              "value": "={{ $json.follower_min || 10000 }}"
            },
            {
              "id": "follower_max",
              "name": "follower_max",
              "value": "={{ $json.follower_max || 1000000 }}"
            },
            {
              "id": "niches",
              "name": "niches",
              "value": "={{ $json.niches || ['lifestyle', 'fashion', 'beauty'] }}"
            },
            {
              "id": "platforms",
              "name": "platforms",
              "value": "={{ $json.platforms || ['instagram', 'tiktok'] }}"
            }
          ]
        }
      },
      "typeVersion": 3
    },
    {
      "id": "brief-analyzer",
      "name": "Brief Analysis Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        700,
        300
      ],
      "parameters": {
        "text": "You are an expert influencer marketing strategist. Analyze the following campaign brief and generate a comprehensive discovery strategy:\n\nCampaign Brief: {{ $json.campaign_brief }}\n\nProvide your analysis in JSON format with:\n1. key_topics: array of main topics/hashtags to search\n2. target_demographics: demographics that fit best\n3. content_type_filters: types of content to prioritize\n4. red_flags: content patterns to avoid (explicit, political, controversial)\n5. engagement_metrics: what engagement ratios to look for\n6. authenticity_signals: indicators of real vs bot accounts\n\nReturn ONLY valid JSON, no markdown formatting.",
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "discover-influencers",
      "name": "Discover Influencers API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        950,
        300
      ],
      "parameters": {
        "url": "https://api.influencer-discovery.io/v1/search",
        "body": "{\n  \"platforms\": {{ JSON.stringify($json.platforms) }},\n  \"keywords\": {{ JSON.stringify($json.key_topics) }},\n  \"geography\": \"{{ $json.geography }}\",\n  \"followers_min\": {{ $json.follower_min }},\n  \"followers_max\": {{ $json.follower_max }},\n  \"niches\": {{ JSON.stringify($json.niches) }},\n  \"limit\": 100\n}",
        "method": "POST",
        "sendBody": true,
        "contentType": "json",
        "authentication": "none"
      },
      "typeVersion": 4
    },
    {
      "id": "prepare-filtering",
      "name": "Prepare for Filtering",
      "type": "n8n-nodes-base.set",
      "position": [
        1150,
        300
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "influencers",
              "name": "influencers",
              "value": "={{ $json.results || [] }}"
            },
            {
              "id": "analysis",
              "name": "analysis",
              "value": "={{ $json }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3
    },
    {
      "id": "filter-valid-profiles",
      "name": "Filter Valid Profiles",
      "type": "n8n-nodes-base.filter",
      "position": [
        1350,
        300
      ],
      "parameters": {
        "conditions": {
          "options": {
            "operator": {
              "type": "string",
              "operation": "exists"
            },
            "leftValue": "",
            "rightValue": "",
            "caseSensitive": true
          }
        }
      },
      "typeVersion": 2
    },
    {
      "id": "score-influencer",
      "name": "Score Influencer Fit",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1550,
        300
      ],
      "parameters": {
        "text": "Score this influencer profile for campaign fit. Analyze content moderation risks and authenticity:\n\nInfluencer Profile:\n- Username: {{ $json.username }}\n- Platform: {{ $json.platform }}\n- Followers: {{ $json.followers }}\n- Engagement Rate: {{ $json.engagement_rate }}\n- Bio: {{ $json.bio }}\n- Recent Posts: {{ JSON.stringify($json.recent_posts || []) }}\n\nBased on campaign requirements:\n{{ JSON.stringify($json.analysis) }}\n\nProvide scoring in JSON format:\n{\n  \"overall_fit_score\": <0-100>,\n  \"audience_alignment\": <0-100>,\n  \"engagement_quality\": <0-100>,\n  \"authenticity_score\": <0-100>,\n  \"content_moderation_risk\": <0-100>,\n  \"red_flags\": [\"list of concerns\"],\n  \"green_flags\": [\"list of positives\"],\n  \"recommendation\": \"APPROVED/CAUTIOUS/REJECTED\",\n  \"reasoning\": \"explanation\",\n  \"contact_outreach_strategy\": \"suggested approach\"\n}\n\nReturn ONLY valid JSON.",
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "format-results",
      "name": "Format Scored Results",
      "type": "n8n-nodes-base.set",
      "position": [
        1750,
        300
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "username",
              "name": "username",
              "value": "={{ $json.username }}"
            },
            {
              "id": "platform",
              "name": "platform",
              "value": "={{ $json.platform }}"
            },
            {
              "id": "followers",
              "name": "followers",
              "value": "={{ $json.followers }}"
            },
            {
              "id": "engagement_rate",
              "name": "engagement_rate",
              "value": "={{ $json.engagement_rate }}"
            },
            {
              "id": "overall_fit_score",
              "name": "overall_fit_score",
              "value": "={{ ($json | fromJson).overall_fit_score }}"
            },
            {
              "id": "audience_alignment",
              "name": "audience_alignment",
              "value": "={{ ($json | fromJson).audience_alignment }}"
            },
            {
              "id": "engagement_quality",
              "name": "engagement_quality",
              "value": "={{ ($json | fromJson).engagement_quality }}"
            },
            {
              "id": "authenticity_score",
              "name": "authenticity_score",
              "value": "={{ ($json | fromJson).authenticity_score }}"
            },
            {
              "id": "moderation_risk",
              "name": "moderation_risk",
              "value": "={{ ($json | fromJson).content_moderation_risk }}"
            },
            {
              "id": "recommendation",
              "name": "recommendation",
              "value": "={{ ($json | fromJson).recommendation }}"
            },
            {
              "id": "contact_strategy",
              "name": "contact_strategy",
              "value": "={{ ($json | fromJson).contact_outreach_strategy }}"
            },
            {
              "id": "reasoning",
              "name": "reasoning",
              "value": "={{ ($json | fromJson).reasoning }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3
    },
    {
      "id": "filter-approved",
      "name": "Filter Approved Only",
      "type": "n8n-nodes-base.filter",
      "position": [
        1950,
        300
      ],
      "parameters": {
        "conditions": {
          "options": {
            "operator": {
              "type": "string",
              "operation": "equals"
            },
            "leftValue": "={{ $json.recommendation }}",
            "rightValue": "APPROVED",
            "caseSensitive": true
          }
        }
      },
      "typeVersion": 2
    },
    {
      "id": "aggregate-results",
      "name": "Aggregate All Results",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        2150,
        300
      ],
      "parameters": {
        "include": "allFields",
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "influencers_data"
      },
      "typeVersion": 1
    },
    {
      "id": "prepare-csv",
      "name": "Prepare CSV Data",
      "type": "n8n-nodes-base.set",
      "position": [
        2350,
        300
      ],
      "parameters": {
        "mode": "raw",
        "rawData": "{\n  \"csv_headers\": [\n    \"username\",\n    \"platform\",\n    \"followers\",\n    \"engagement_rate\",\n    \"overall_fit_score\",\n    \"audience_alignment\",\n    \"engagement_quality\",\n    \"authenticity_score\",\n    \"moderation_risk\",\n    \"recommendation\",\n    \"contact_strategy\",\n    \"reasoning\"\n  ],\n  \"influencers\": \"={{ $json.influencers_data }}\"\n}"
      },
      "typeVersion": 3
    },
    {
      "id": "generate-csv",
      "name": "Generate CSV File",
      "type": "n8n-nodes-base.spreadsheetFile",
      "position": [
        2550,
        300
      ],
      "parameters": {
        "options": {
          "fileName": "influencer_discovery_{{ now.format('YYYY-MM-DD_HHmmss') }}.csv",
          "headerRow": true
        },
        "operation": "toFile",
        "fileFormat": "csv",
        "binaryPropertyName": "data"
      },
      "typeVersion": 2
    },
    {
      "id": "return-csv",
      "name": "Return CSV to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        2750,
        300
      ],
      "parameters": {
        "respondWith": "binary",
        "inputFieldName": "data",
        "responseDataSource": "set"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Prepare CSV Data": {
      "main": [
        [
          {
            "node": "Generate CSV File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Results": {
      "main": [
        [
          {
            "node": "Prepare CSV Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate CSV File": {
      "main": [
        [
          {
            "node": "Return CSV to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Brief Analysis Agent": {
      "main": [
        [
          {
            "node": "Discover Influencers API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Approved Only": {
      "main": [
        [
          {
            "node": "Aggregate Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Score Influencer Fit": {
      "main": [
        [
          {
            "node": "Format Scored Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Valid Profiles": {
      "main": [
        [
          {
            "node": "Score Influencer Fit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Scored Results": {
      "main": [
        [
          {
            "node": "Filter Approved Only",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare for Filtering": {
      "main": [
        [
          {
            "node": "Filter Valid Profiles",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Campaign Brief Webhook": {
      "main": [
        [
          {
            "node": "Parse Campaign Parameters",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Discover Influencers API": {
      "main": [
        [
          {
            "node": "Prepare for Filtering",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Campaign Parameters": {
      "main": [
        [
          {
            "node": "Brief Analysis Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}