Skip to main content

AI lead qualification

This workflow scores a lead as soon as it is submitted via the form, records qualified leads in Snowflake and notifies the salesperson by email.

Loading the diagram…

The need​

Every lead submitted via the form must be qualified to know whether it deserves the salesperson's attention. An AI agent scores it automatically: qualified leads are recorded in Snowflake and the salesperson is notified by email, the others are published as unqualified on a Google Pub/Sub topic consumed by the CRM.

What the workflow does​

  1. New lead (form) — the Trigger node captures the form submission (triggerId form.submitted). The lead data arrives in data.
  2. Score the lead (AI) — the AI Agent node evaluates the lead with the gemini-1.5-pro model (structured output). The score is stored in context.agentOutput.answer.score.
  3. Score ≥ 60? — the Condition node routes the lead according to its score.
  4. Record the qualified lead — if the score is high enough, the Snowflake node inserts the lead in the leads_qualifies table.
  5. Notify the salesperson — the Send an email node sends the result to the sales team.
  6. Publish the unqualified lead (CRM) — otherwise, the Send Google Pub/Sub node publishes lead_rejected on the CRM's Pub/Sub topic.

What you need​

Construction​

Copy the workflow definition and paste it into the editor (the Trigger node is recreated automatically, it is not in the snippet):

[
{
"id": "agent-103",
"name": "Score the lead (AI)",
"config": {
"type": "AGENT",
"model": {
"provider": "GEMINI",
"name": "gemini-1.5-pro"
},
"systemPrompt": "You score B2B leads from 0 to 100, with a score field and a summary.",
"message": "Here are the lead details: {{ data.company }}",
"outputKey": "agentOutput",
"responseFormat": "{\"type\": \"object\", \"properties\": {\"score\": {\"type\": \"number\", \"minimum\": 0, \"maximum\": 100}, \"synthesis\": {\"type\": \"string\"}}, \"required\": [\"score\", \"synthesis\"]}",
"tools": []
},
"parents": [
"trigger"
],
"position": {
"x": 0,
"y": 200
},
"next": "cond-103"
},
{
"id": "cond-103",
"name": "Score ≥ 60?",
"config": {
"type": "CONDITION",
"conditionCode": "return context.agentOutput.answer.score >= 60;",
"conditions": [
{
"value": true,
"next": "db-103"
},
{
"value": false,
"next": "event-103"
}
]
},
"parents": [
"agent-103"
],
"position": {
"x": 0,
"y": 400
}
},
{
"id": "db-103",
"name": "Record the qualified lead",
"config": {
"type": "DATABASE_SNOWFLAKE",
"query": "INSERT INTO leads_qualifies (company, score) SELECT '{{ data.company }}', {{ context.agentOutput.answer.score }}",
"outputKey": "snowflakeResult"
},
"parents": [
"cond-103"
],
"position": {
"x": 0,
"y": 600
},
"next": "email-103"
},
{
"id": "email-103",
"name": "Notify the salesperson",
"config": {
"type": "SEND_EMAIL",
"to": [
"ventes@agence-leads.fr"
],
"subject": "New scored lead: {{ data.company }}",
"content": "AI score: {{ context.agentOutput.answer.score }}",
"sendAsHtml": true
},
"parents": [
"db-103"
],
"position": {
"x": 0,
"y": 800
}
},
{
"id": "event-103",
"name": "Publish the unqualified lead (CRM)",
"config": {
"type": "SEND_EVENT",
"provider": {
"type": "GCP_PUBSUB",
"projectId": "mon-projet-crm",
"topicId": "leads"
},
"body": "{\"event\": \"lead_rejected\", \"company\": \"{{ data.company }}\"}"
},
"parents": [
"cond-103"
],
"position": {
"x": 800,
"y": 600
}
}
]

Check that it works​

  • Expected data: the agent message references {{ data.company }} — make sure the trigger payload actually exposes this data. The score is read from the agent's output key (default context.agentOutput); the condition and the email use context.agentOutput.answer.score.
  • Deploy the workflow (Deploy a workflow), then trigger the real scenario: every execution generates a trace you can view (View traces).

Variations​

  • If you change the agent's output key, update all the references that use it (condition and email).
  • The structured output forces the agent to return a reliable JSON object (score, summary) usable by the condition; without it, the agent's response is plain text.
  • Without a configured tool, the AI Agent node behaves in conversational mode: it answers but does not trigger external calls.

Going further


See also: Examples and integrations