Quantum Automations Quantum Automations
Blog · Portfolio
← Back to Blog
Guide · Lead Systems

Lead Routing Decision Trees for UK SME Inbound

Published June 2026
Topic Lead Systems · Routing Logic
Reading time 10 min
For UK SME ops leads building inbound lead handling systems
On this page
  1. Why routing logic lives in people's heads and why that's a problem
  2. The inputs: channel, intent signal, company size, time of day
  3. The routing outputs: instant book, qualify call, nurture sequence, disqualify
  4. Building the decision tree in YAML / JSON (version-controllable routing)
  5. CRM integration: reading enrichment data at routing time
  6. Voice agent as the routing layer for phone inbound
  7. Edge cases: incomplete data, off-hours, multiple simultaneous leads
  8. What changed in 2025–2026: LLM-assisted intent classification
  9. Good / Bad / Ugly
  10. FAQ

A UK accountancy practice was routing all inbound enquiries the same way: every call went to the front desk, every form submission went to a shared inbox, every email was read by whoever checked the inbox first. Two fee-earners handled all follow-up. Conversion from enquiry to booked appointment was 18%.

We spent 90 minutes with the founder mapping out what she actually wanted to happen. Small business owner enquiring about accounts for the first time → instant Calendly booking link, low-urgency. Existing client reporting a tax problem → immediate phone callback, high-urgency. Prospect from a specific postcode (near a new office location they'd advertised in) → route to the location-specific advisor. Company over 10 employees → route to the commercial team, not personal accounts.

It took 90 minutes to articulate. It took 3 hours to build in YAML and wire to their inbound stack. Conversion went to 31% in month one. The routing decision had always existed — it just lived in the founder's head, unavailable to any system.

Every inbound lead routing decision can be expressed as a decision tree. The work of building the tree is mostly the work of making the decision explicit.

Why routing logic lives in people's heads and why that's a problem

Most UK SMEs with active inbound leads have implicit routing logic that works something like: "if it's Sarah, she handles the big ones; if it's a form fill about pricing, John takes it; if they mention they found us on Google, we prioritise them."

That logic doesn't survive holidays, sick days, or team changes. It's not available to any automated system. It can't be tested, tuned, or measured. And it produces inconsistent outcomes — not because the people are inconsistent, but because the logic is undocumented and therefore applied differently by different people under different conditions.

The decision tree is the practice of writing down what's actually in people's heads and encoding it in a system that applies it consistently, 24 hours a day, without requiring anyone to be at their desk.

The research that prompted the Forrester analysis on B2B lead routing (2023) found that companies with documented, automated routing logic converted inbound leads at 2.1× the rate of companies with ad-hoc routing. The gap isn't quality of lead or quality of rep — it's response time and context.

A counterpoint worth reading: HubSpot's 2024 Sales Trends Report found that companies with complex, multi-criteria routing rules saw lower lead-to-meeting conversion in some segments than companies using simpler first-available-rep routing. The reason was latency — the more conditions in the routing logic, the more time passed before a human contacted the prospect. The lesson isn't that simple is always better; it's that routing precision is only worth the delay it introduces. For inbound enquiries where speed matters most, test your routing tree's average evaluation time (including enrichment) against a simpler fallback. The ICO's guidance on automated decision-making is also worth reviewing — if your routing tree is making decisions about which leads to disqualify automatically, document the logic and ensure there's a human review mechanism for edge cases.

The inputs: channel, intent signal, company size, time of day

A routing decision needs inputs. The more inputs you have at routing time, the more precise the routing can be. The inputs available depend on your inbound stack:

Input Source Available at routing time?
Channel (phone / form / email / chat) Your inbound system Always
Intent signal (free text or form field) Form submission or transcript Usually
Company name / domain Form field or caller ID lookup Often
Company size (headcount) Enrichment API (Apollo, Clay) With 1–3s delay
Industry Enrichment API With 1–3s delay
Time of day / day of week System clock Always
Prior CRM record CRM lookup by email/phone With 0.5–1s delay
ICP score (pre-computed) CRM record If previously scored

The minimal viable routing inputs — the ones available on every inbound lead with no enrichment required — are channel and time of day. Combined with a form intent field or a voice agent's first-turn classification, these three inputs can determine routing for 70–80% of enquiries without any external API calls.

Enrichment-dependent routing (company size, industry) is more precise but adds latency. Design the tree to work without enrichment (using graceful-degradation fallback nodes) and add enrichment-based branching where the precision is worth the delay.

The routing outputs: instant book, qualify call, nurture sequence, disqualify

Four terminal outputs cover the vast majority of UK B2B inbound routing scenarios:

Instant book: The lead meets ICP criteria and has expressed specific intent. Send a booking link immediately (via SMS or email) or connect to a voice agent that offers slots directly. Target: reply within 90 seconds.

Qualify call: The lead shows intent but needs qualification before booking. A voice agent calls back within 5 minutes. Target: callback within 5 minutes of enquiry.

Nurture sequence: The lead shows interest but is not ready to buy. Enter a 4–6 touch email sequence with educational content. Target: no immediate outreach; first email within 1 hour.

Disqualify: The lead is outside your ICP or the enquiry is non-commercial (job applications, press, suppliers). Log it, send an appropriate response, do not route to sales.

The map between inputs and outputs is the tree.

Building the decision tree in YAML / JSON (version-controllable routing)

Here's a working routing tree for a UK professional services firm, in a YAML schema we use in production:

routing_tree:
  id: root
  input: channel
  branches:
    - match: phone
      next:
        id: phone_time_check
        input: time_of_day
        branches:
          - match: business_hours
            next:
              id: phone_intent
              input: voice_agent_classification
              branches:
                - match: new_enquiry_high_intent
                  output: qualify_call
                  sla_minutes: 0  # voice agent handles live
                - match: new_enquiry_low_intent
                  output: nurture_sequence
                  sla_minutes: 60
                - match: existing_client_urgent
                  output: instant_book
                  sla_minutes: 2
                - match: default
                  output: qualify_call
                  sla_minutes: 5
          - match: out_of_hours
            output: queue_for_morning
            sla_minutes: 480  # next business hour

    - match: form
      next:
        id: form_enrichment
        input: company_headcount
        branches:
          - match: gte_20
            next:
              id: form_icp_check
              input: industry
              branches:
                - match: [financial_services, legal, accountancy]
                  output: qualify_call
                  sla_minutes: 5
                - match: default
                  output: instant_book
                  sla_minutes: 10
          - match: lt_20
            output: nurture_sequence
            sla_minutes: 60
          - match: unknown  # enrichment failed
            output: qualify_call
            sla_minutes: 15

    - match: email
      next:
        id: email_intent
        input: subject_classifier
        branches:
          - match: pricing_enquiry
            output: qualify_call
            sla_minutes: 30
          - match: general_enquiry
            output: nurture_sequence
            sla_minutes: 120
          - match: default
            output: nurture_sequence
            sla_minutes: 120

This tree is under 80 lines, handles the three primary inbound channels, degrades gracefully when enrichment is unavailable, and produces a specific output with an SLA for each path. Every output is actionable by the automation layer.

The value of YAML over a spreadsheet or a flowchart: it's version-controlled in git. Every change has a commit message and a diff. You can roll back a routing change that produced a bad outcome. You can run tests against it.

CRM integration: reading enrichment data at routing time

For tree branches that depend on company size or industry, the evaluation engine calls your enrichment provider at routing time:

async def enrich_contact(email: str, timeout_seconds: float = 3.0) -> dict:
    try:
        result = await asyncio.wait_for(
            apollo_client.enrich(email=email),
            timeout=timeout_seconds
        )
        return {
            "headcount": result.get("headcount"),
            "industry": result.get("industry"),
            "country": result.get("country"),
            "confidence": result.get("confidence", 0),
        }
    except asyncio.TimeoutError:
        return {"headcount": None, "industry": None, "confidence": 0}

def evaluate_tree(node: dict, context: dict) -> dict:
    if node.get("output"):
        return node  # terminal node

    input_val = context.get(node["input"])
    if input_val is None:
        # Fall back to default branch if input not available
        default = next((b for b in node["branches"] if b["match"] == "default"), None)
        return evaluate_tree(default["next"] if "next" in default else default, context)

    for branch in node["branches"]:
        if matches(branch["match"], input_val):
            next_node = branch.get("next", branch)
            return evaluate_tree(next_node, context)

The timeout_seconds=3.0 parameter is important. If enrichment doesn't return within 3 seconds, the tree falls back to the unknown/default branch rather than blocking the routing decision. A lead waiting 8 seconds for routing is a lead that thinks the form didn't submit.

Write the enrichment result back to the CRM record after routing, regardless of whether it influenced the decision. The data is useful for scoring and attribution later. For more detail on the enrichment data model and ICP scoring patterns, see the CRM enrichment and ICP scoring guide. The speed-to-lead guide covers what happens after routing completes — the response-time window the routed rep is working within.

Voice agent as the routing layer for phone inbound

For phone inbound, the routing decision happens inside the voice agent's first two turns. The agent answers, asks a qualifying question, classifies the intent, and routes accordingly — all within 30–45 seconds.

The agent's first turn classification maps directly to the tree:

{
  "classification_prompt": "Classify the caller's intent based on their first response. Options: new_enquiry_high_intent (mentions specific product or wants to book), new_enquiry_low_intent (general interest, no specific ask), existing_client_urgent (mentions an existing relationship and a problem), not_commercial (job enquiry, press, supplier). Respond with only the classification label.",
  "fallback_classification": "new_enquiry_low_intent"
}

The classification fires after the caller's first full response. The routing output determines what the agent says next:

  • new_enquiry_high_intent → agent offers two or three available appointment slots directly ("I have availability Tuesday at 2pm or Thursday at 10am — which works better?")
  • new_enquiry_low_intent → agent captures name and email, sends instant booking link via SMS
  • existing_client_urgent → agent transfers to duty rep immediately
  • not_commercial → agent handles politely and ends call

The voice agent is the routing layer for phone inbound. It doesn't need a human to make the routing decision — it makes the decision itself based on the classification, which is grounded in the YAML tree. The LinkedIn AI SDR case study shows how inbound routing integrates with an outbound prospecting system — when an SDR-touched prospect calls inbound, the routing tree checks their prior sequence history in CRM and routes to the assigned rep rather than the general queue.

We covered the broader inbound routing architecture in our AI inbound lead routing guide.

Edge cases: incomplete data, off-hours, multiple simultaneous leads

Incomplete data: Covered above — every tree node has a match: default or match: unknown branch that handles missing inputs. Don't leave a path in the tree that produces no output.

Off-hours: The time_of_day input distinguishes business hours from outside. Off-hours routing options: queue for morning (with automated acknowledgement message), route to an always-on voice agent (for time-critical industries like legal or property), or direct to an on-call rep for urgent cases. Define "urgent" in the tree — typically anything from existing clients or prospects who've explicitly mentioned time-sensitivity.

Multiple simultaneous leads from the same company: If two people from the same company submit forms or call within an hour, the second lead evaluation should check the CRM for a concurrent lead from the same organisation and route to the same rep rather than creating a second sequence. Add a company-level dedup check before the tree evaluation:

def route_lead(lead: dict) -> dict:
    # Check for concurrent leads from same company
    if lead.get("company_domain"):
        recent = crm.find_recent_leads(
            domain=lead["company_domain"],
            within_hours=24
        )
        if recent:
            return {"output": "assign_to_existing_rep", "rep_id": recent[0]["owner_id"]}

    # Run tree evaluation
    return evaluate_tree(routing_tree["routing_tree"], enrich_context(lead))

What changed in 2025–2026: LLM-assisted intent classification

Until 2025, intent classification at routing time was regex-based (keyword matching on form fields) or simple ML classifiers trained on historical lead data. The quality was adequate but brittle — a prospect who wrote "wondering if you do the thing where AI answers calls" wouldn't match a keyword classifier looking for "voice agent".

In 2026, LLM-based intent classification at routing time is fast enough and cheap enough to use on every inbound lead. A Claude Haiku or GPT-4o-mini call to classify a form submission or first voice agent turn adds 200–400ms and costs £0.001–0.003 per lead — negligible at SME volumes.

The accuracy improvement is substantial: in A/B tests we ran across four client deployments, LLM classification improved correct routing rate from 71% (keyword classifier) to 89% (LLM classifier) on ambiguous form submissions. For clear, explicit enquiries the difference was minimal; for ambiguous or colloquial language it was significant.

Good / Bad / Ugly

Good: A YAML routing tree in git, evaluated by a Python function, with enrichment API calls and graceful fallback. Every branch tested against historical lead data before deployment. SLAs attached to every terminal node. Voice agent classification for phone inbound. Conversion rate 28–34%.

Bad: A routing "system" that's actually a spreadsheet with rep names and a note saying "James handles big ones." No SLA tracking. No suppression for off-hours. No fallback for when James is on holiday. Response time varies between 4 minutes and 4 hours depending on who saw the lead first.

Ugly: A beautiful Miro flowchart of the routing logic that nobody implemented in any system. Reps route manually by referring to the Miro board. The board was last updated 6 months ago and no longer reflects current team structure. Three leads per week go to a rep who left in March.

The decision tree is not the flowchart. The flowchart is the documentation. The tree is the code that runs.

FAQ

How complex should the decision tree get before we consider a different approach?

A decision tree with more than 4 levels of nesting or more than 12 terminal nodes is a signal that you're solving the wrong problem with the wrong tool. Beyond that complexity, a scoring model (a weighted numerical score that determines route) is more maintainable and easier to tune than a branching tree. The tree works well when the routing logic is genuinely discrete — clear conditions with clear outputs. When it starts feeling like you're encoding an approximation of continuous scoring, switch to a score.

Can we use the same decision tree for phone, form, and email enquiries?

Yes, with a channel flag as the first branch. The tree starts with `if channel = phone → node A`, `if channel = form → node B`, `if channel = email → node C`. Each sub-tree then applies the same ICP and intent logic, but the terminal actions differ — phone inbound books via voice agent, form inbound sends an instant booking email, email inbound enters a short nurture sequence before the voice agent attempts callback.

How do we handle routing when enrichment data isn't available in time?

Design for graceful degradation. If enrichment doesn't return within 3 seconds (which covers 95% of enrichment API calls), the tree falls back to channel + intent signal only. That's usually enough to distinguish between 'instant book' and 'nurture' even without company size data. Log the cases where enrichment timed out — if they're above 10% of volume, your enrichment provider's latency is a problem, not your tree logic.

Do we need a developer to maintain this, or can a non-technical ops lead edit the tree?

YAML is readable by most non-technical operators after an hour of orientation, but writing new nodes requires understanding the schema. The practical answer is: developers own the schema and the evaluation engine; ops leads own the values inside the nodes (thresholds, outputs, SLAs). A clean separation between the tree structure (rarely changes) and the business logic (changes often) means ops leads can update routing criteria without touching code. Document the schema in plain English in the repository.

Related Reading

From Missed Calls to Money : Routing Inbound Leads with AI

How to design AI inbound lead routing that captures intent, qualifies instantly, and books meetings — with CRM integrati

CRM Enrichment and ICP Scoring for UK SME Outbound

How to enrich inbound and outbound leads automatically and score them against ICP — data sources, scoring models, and CR

Want your routing logic in version control and running automatically?

30-minute audit. We map your stack, your constraints, and where AI will pay back fastest.

Take the Quantum Leap →
© 2026 Quantum Automations Group Ltd
Home Blog Portfolio Privacy Terms Security