Skip to content

vinimabreu/n8n-lead-triage

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

n8n-lead-triage

An n8n workflow that triages inbound leads with Claude, built on one rule most "AI + n8n" projects get wrong: n8n routes, the AI decides, and the intelligence lives in a tested service, not in a node.

Drop an LLM prompt straight into a workflow and you get something that demos well and rots fast: no tests, no versioning, no way to see why it sent a hot lead to spam, and a silent failure the day the API hiccups. This puts the model behind a small HTTP service with a schema, guardrails and a test suite, and lets n8n do what n8n is great at: receive, route, and fan out to your tools.

the workflow in n8n

The actual workflow running in n8n. A lead hits the webhook, the HTTP node asks the brain, and the Switch routes on one field.

What happens to a lead

  1. Any source POSTs a lead to the n8n Webhook (/lead-intake): a website form, a Typeform, an email parser, a CRM.
  2. An HTTP Request node calls the brain service with the lead.
  3. The brain classifies it (sales, support, spam, other), extracts what it can (company, budget, product interest), and returns a single action string.
  4. A Switch routes on that action to four branches: sales alert, support ticket, human review, or silent drop. You attach your own Slack, Gmail, HubSpot or Sheets nodes at the ends.

The Switch never sees the model. It switches on one clean field, which is why the workflow stays a dumb, reliable router instead of a place where AI logic quietly accumulates.

architecture

The line that matters: the model proposes, the code disposes

The brain (brain/app) asks Claude to classify and extract, and then code, not the prompt, decides the route (schema.py: decide_action). That separation is what makes the two guardrails possible:

  • Low confidence routes to a human. Below a configurable floor (default 0.6) the lead goes to needs_human no matter how the model labelled it. Routing a hot lead to the wrong bucket costs a sale; routing an unsure one to a person costs a minute.
  • A model failure also routes to a human, never to the void. API down, broken JSON, an intent outside the allowed set: each is caught, attached as a reason, and sent to needs_human. A triage bot that can silently drop a lead when its model stumbles is a liability with a webhook, not an automation.

Both are tested, and both are visible in the response's reasons field, so a human reviewing the queue sees exactly why the lead landed there.

Run the whole stack in one command

docker compose up -d --build          # demo mode, no API key needed

That starts n8n (http://localhost:5678) and the brain together. In demo mode the brain uses a keyword heuristic that clearly labels itself, so you can exercise the entire workflow for free. For the real classifier:

LLM_MODE=claude ANTHROPIC_API_KEY=sk-... docker compose up -d --build

Import workflows/lead-triage.json into n8n, activate it, and send a lead. This is a real captured run of the live stack:

$ curl -s -X POST localhost:5678/webhook/lead-intake \
    -H 'Content-Type: application/json' \
    -d '{"message":"Hi, can I get pricing for 200 units? We are Acme Foods.","email":"buyer@acme.com"}'

{ "channel": "sales",
  "notify": "[NORMAL] New lead: ... pricing for 200 units? We are Acme Foods.",
  "decision": { "action": "route_sales", "intent": "sales",
                "confidence": 0.9, "reasons": [] } }

And the guardrail firing on a vague message, captured the same way:

$ curl ... -d '{"message":"hello there"}'

{ "channel": "human_review",
  "decision": { "action": "needs_human",
                "reasons": ["confidence 0.50 below floor 0.6"] } }

All four routes (sales, support, drop, human) were verified end to end through the live n8n webhook, not just against the service in isolation.

What is in the repo

workflows/
  lead-triage.json      the main workflow (webhook -> brain -> switch -> 4 routes)
  error-handler.json    an Error Trigger workflow, so a workflow-level
                        failure pings a person instead of dying quietly
brain/
  app/schema.py         intents, actions, and decide_action (the routing policy)
  app/llm.py            Claude, a key-free demo brain, a scripted test double,
                        and strict validation of the model's reply
  app/triage.py         the engine: classify, validate, route, never lose a lead
  app/main.py           the FastAPI service n8n calls
  tests/                17 tests, no API key, no network
docker-compose.yml      n8n + brain, wired together

Tests

cd brain && pip install -r requirements.txt && python -m pytest

17 deterministic tests, no key and no network. They cover the routing policy, the confidence floor, every failure mode (model crash, invalid intent, non-numeric confidence) routing to a human, input limits enforced at the HTTP door before any model call, and the full demo loop end to end.

Making it yours

  • Change the categories. Edit INTENTS, ACTIONS and decide_action in schema.py, and add a Switch output in n8n. The prompt is built from the schema, so the model follows.
  • Attach your tools. Each branch ends in a Set node shaping a notification payload. Replace those ends with your Slack, Gmail, HubSpot or Sheets nodes. The drop branch stays silent on purpose.
  • Tune the guardrail. CONFIDENCE_FLOOR decides how cautious triage is. Raise it and more leads get a human glance; lower it and the model acts on its own more often.

Scope notes

This is the triage layer, not a CRM. It decides where a lead goes and why, and hands off cleanly; it does not store leads or send the notifications itself, because in n8n those are nodes you already have and want to own. The brain is stateless on purpose: every decision depends only on the message in front of it, which is what keeps it testable.

About

AI lead triage in n8n: the workflow routes, a tested HTTP service decides, and low confidence or any model failure routes to a human instead of dropping the lead

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors