id: ai-lead-qualification-and-routing
namespace: company.sales
description: |
Autonomous inbound lead qualification and sales routing pipeline.
Ingests new form signups via webhook, enriches company firmographics
using Google Gemini and Tavily live search, scores Ideal Customer Profile
(ICP) fit, and instantly routes high-value enterprise leads to VIP Slack channels.
triggers:
- id: weekly_lead_audit
type: io.kestra.plugin.core.trigger.Schedule
description: Weekly sweep to re-evaluate unprocessed or disputed leads. Shipped
disabled by default.
cron: "0 8 * * 1"
disabled: true
- id: inbound_lead_webhook
type: io.kestra.plugin.core.trigger.Webhook
description: Authenticated webhook endpoint triggered by website signup forms or
CRM integrations.
key: "{{ secret('WEBHOOK_KEY') }}"
inputs:
- id: lead_email
type: STRING
defaults: sarah.connor@acmecorp.com
description: Email address of the inbound prospect.
- id: company_name
type: STRING
defaults: Acme Cloud Solutions
description: Name of the organization submitting the inquiry.
- id: company_domain
type: STRING
defaults: acmecorp.com
description: Primary web domain used for firmographic enrichment.
- id: use_case_description
type: STRING
defaults: We need to orchestrate mission-critical financial pipelines across 4
cloud providers and manage 500 daily batch jobs.
description: Raw problem statement or use case submitted by the user.
- id: self_reported_team_size
type: STRING
defaults: "250-1000"
description: Team size range selected on the signup form.
tasks:
- id: enrich_and_score_lead
type: io.kestra.plugin.ai.agent.AIAgent
description: Queries live web sources to retrieve company funding and headcount,
then scores ICP fit and buying intent.
provider:
type: io.kestra.plugin.ai.provider.GoogleGemini
apiKey: "{{ secret('GEMINI_API_KEY') }}"
modelName: gemini-2.5-flash
configuration:
temperature: 0.1
maxToken: 4096
responseFormat:
type: JSON
jsonSchema:
type: object
required:
- company_name
- qualification_tier
- icp_fit_score
- key_intent_signals
- recommended_sales_angle
- executive_briefing
properties:
company_name:
type: string
qualification_tier:
type: string
enum:
- ENTERPRISE
- MID_MARKET
- SMB
- DISQUALIFIED
icp_fit_score:
type: integer
description: Score from 0 to 100 based on tech stack fit, scale, and buying
intent.
key_intent_signals:
type: array
items:
type: string
recommended_sales_angle:
type: string
executive_briefing:
type: string
contentRetrievers:
- type: io.kestra.plugin.ai.retriever.TavilyWebSearch
apiKey: "{{ secret('TAVILY_API_KEY') }}"
maxResults: 3
systemMessage: |
You are an expert Enterprise Sales Development and RevOps Director.
Your job is to evaluate inbound leads for an enterprise workflow orchestration platform.
Scoring Criteria:
- ENTERPRISE (Score 80-100): Over 250 employees, multi-cloud or complex infrastructure, explicit high-scale volume (>100 daily jobs), high buying intent.
- MID_MARKET (Score 50-79): 50-249 employees, growing data stack, moderate automation needs.
- SMB (Score 20-49): Under 50 employees, single-cloud, simple cron replacement.
- DISQUALIFIED (Score 0-19): Personal email providers (gmail, yahoo), spam, student projects, or completely irrelevant inquiries.
Always verify the company domain via web search to confirm legitimate operating status and headcount.
prompt: |
Evaluate the following inbound prospect:
- Lead Email: {{ inputs.lead_email }}
- Company Name: {{ inputs.company_name }}
- Domain: {{ inputs.company_domain }}
- Self-Reported Team Size: {{ inputs.self_reported_team_size }}
- Stated Use Case: {{ inputs.use_case_description }}
Search the company web presence, determine their tech footprint, calculate their ICP fit score, and return the structured qualification payload.
- id: parse_qualification_metrics
type: io.kestra.plugin.scripts.python.Script
description: Extracts qualification tier and generates a structured sales battle-card.
taskRunner:
type: io.kestra.plugin.core.runner.Process
inputFiles:
qualification.json: "{{ outputs.enrich_and_score_lead.textOutput }}"
outputFiles:
- sales-battle-card.md
script: |
import json
from kestra import Kestra
with open("qualification.json", "r", encoding="utf-8") as f:
data = json.load(f)
company = data.get("company_name", "Unknown")
tier = data.get("qualification_tier", "SMB")
score = data.get("icp_fit_score", 0)
signals = data.get("key_intent_signals", [])
angle = data.get("recommended_sales_angle", "Standard product demo.")
briefing = data.get("executive_briefing", "")
# Write executive battle card
card = f"""# Inbound Lead Battle Card: {company}
**Qualification Tier:** {tier} | **ICP Fit Score:** {score}/100
## Executive Summary
{briefing}
## Key Buying Intent Signals
""" + "\n".join([f"- {s}" for s in signals]) + f"""
## Recommended Sales Outreach Angle
{angle}
"""
with open("sales-battle-card.md", "w", encoding="utf-8") as out:
out.write(card.strip())
print(f"Lead processed: {company} -> Tier: {tier} (Score: {score})")
Kestra.outputs({
"qualification_tier": tier,
"icp_fit_score": score,
"company": company,
"angle": angle[:150]
})
- id: routing_gate
type: io.kestra.plugin.core.flow.If
description: Routes enterprise-tier leads immediately to VIP sales channels
while sending SMB leads to nurture queues.
condition: "{{ outputs.parse_qualification_metrics.vars.qualification_tier ==
'ENTERPRISE' or outputs.parse_qualification_metrics.vars.icp_fit_score >=
80 }}"
then:
- id: alert_vip_sales_channel
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
description: Alerts senior account executives on high-value inbound enterprise
leads.
url: "{{ secret('SLACK_WEBHOOK_URL') }}"
payload: |
{
"channel": "#sales-enterprise-inbound",
"text": "🔥 *VIP Enterprise Inbound Lead Detected: {{ inputs.company_name }}* 🔥\n\n*ICP Fit Score:* `{{ outputs.parse_qualification_metrics.vars.icp_fit_score }}/100`\n*Prospect:* `{{ inputs.lead_email }}`\n*Team Size:* `{{ inputs.self_reported_team_size }}`\n\n*Recommended Outreach Angle:*\n{{ outputs.parse_qualification_metrics.vars.angle }}\n\nReview the full battle card in Kestra execution `{{ execution.id }}`."
}
else:
- id: log_standard_nurture
type: io.kestra.plugin.core.log.Log
description: Records standard or SMB lead to standard self-service nurture queue.
message: "Lead for {{ inputs.company_name }} classified as {{
outputs.parse_qualification_metrics.vars.qualification_tier }} (Score:
{{ outputs.parse_qualification_metrics.vars.icp_fit_score }}). Routed
to automated email nurture track."
errors:
- id: alert_on_failure
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
description: Alerts technical operations if lead qualification fails.
url: "{{ secret('SLACK_WEBHOOK_URL') }}"
payload: |
{
"channel": "#revops-alerts",
"text": "❌ *Lead Qualification Pipeline Failed* ❌\nWorkflow `{{ flow.id }}` failed on prospect `{{ inputs.lead_email }}` (Execution `{{ execution.id }}`)."
}