Technical Deep-Dive May 29, 2026 · 12 min read · Field Service Ops

How the CrewOps Dispatch Agent Decides Who Gets the Job

A technical deep-dive into the scoring model, routing algorithm, and exception handling logic that powers CrewOps' autonomous dispatch engine.

Dispatch AI Scoring Model TSP Routing Exception Handling Autonomy Layers

The Dispatch Problem in 90 Seconds

A dispatcher at a 30-truck HVAC shop does this job in real time, every day, with no algorithm:

  1. A new job comes in — residential AC repair, 2pm window, zip code 95128
  2. She scans which techs are currently available
  3. She checks who has the right EPA 609 certification
  4. She estimates drive time from each tech's current location (mentally, with some Google Maps help)
  5. She checks who hasn't had a complaint in the last 30 days
  6. She picks someone and moves on

This works fine at 8 trucks. At 25, it starts falling apart. At 40, she's making decisions based on gut feel and crossed fingers — and that's when the $300 missed-window callbacks start.

The dispatcher bottleneck has four layers:

CrewOps was built to remove that bottleneck. Not to replace dispatchers — to do the triage work they don't have time for, so they can handle the exceptions that actually need a human.

Here's how the agent actually works.

The Scoring Model

The Scoring Model: How Each Tech Gets Rated Against a Job

When a new job arrives, the agent doesn't pick the closest available tech. It scores every available technician against every dimension of the job, then ranks them. The winner gets the dispatch.

Here's the full scoring breakdown:

1. Skill Match (weight: 30%)

Does this tech actually know how to do this job? This isn't just "HVAC" — it's the specific capability required.

Job requirements: Carrier Infinity series heat pump, R-410A refrigerant Tech certifications: EPA 608 Universal + Carrier Infinity certified ✓ +15pts Tech certifications: EPA 608 Universal + generic heat pump cert ⚠ +5pts Tech certifications: EPA 608 Universal only ✗ 0pts

If a tech can't handle the job's technical requirements, they're excluded entirely — not scored low, removed from the candidate pool.

2. Certification & License Check (binary gate, not scored)

Before scoring even begins, the agent verifies:

A tech fails this gate → excluded from scoring. The agent logs why (helpful for the dispatcher reviewing the queue).

3. Distance + Traffic-Adjusted ETA (weight: 25%)

Not "straight-line distance." Real drive time.

The agent pulls:

It calculates: can this tech arrive within the job window, accounting for current traffic?

If not, that tech is deprioritized. If they'd arrive 40+ minutes late even in ideal conditions, they're excluded.

Tech A: 4.2 miles, 12 min drive time ETA 1:52pm ✓ in window Tech B: 7.8 miles, 19 min drive time ETA 2:11pm ✓ in window Tech C: 11.4 miles, 28 min drive time ETA 2:28pm ⚠ cutting it close Tech D: 18.1 miles, 41 min drive time ETA 2:41pm ✗ outside window

4. Current Job Status (weight: 20%)

Where is this tech right now?

A tech 5 minutes from finishing their current job ranks higher than one just starting a 90-minute job — even if the second tech is geographically closer.

5. Shift Remaining (weight: 15%)

Does this tech have enough hours left to complete this job and travel to the next one?

Job estimated duration: 90 minutes Travel to next job: 20 minutes Tech shift ends: 5:00pm Current time: 2:30pm 150 min remaining Current time: 4:15pm 45 min remaining (not enough time)

Jobs that would push a tech past their scheduled shift end are flagged, not automatically excluded — the dispatcher reviews flagged assignments.

6. Customer History with This Tech (weight: 10%)

Has this customer been assigned to this tech before? How did it go?

Customer: thegarciaproperty@example.com Tech Maria S.: 3 prior visits, avg 4.8 stars +10pts Tech James K.: 1 prior visit, avg 3.2 stars -15pts Tech David L.: no prior visits 0pts

This is not a dominant factor — but in a close call between two equally-skilled, equally-located techs, it breaks the tie.

7. Equipment & Parts on the Truck (binary gate, then weight: included in job fit)

Some jobs require tools or parts the tech might not have. The agent checks:

A Worked Example

A Concrete Worked Example

It's 2:00pm. A new job arrives: residential heat pump repair, 1317 Willowbrook Lane, job window 2pm–5pm, estimated 90 minutes.

Candidate techs:

Tech Location Skills Certs Current Status Shift End Customer History Parts on Truck
Maria S. 3.1mi / 11min Heat pump specialist EPA 609 Between jobs (free) 6:00pm 3 prior visits, 4.8★ R-410A 25lb + common capacitors
James K. 6.4mi / 18min Master HVAC EPA 608 Universal En route, ETA done 2:15pm 5:00pm 1 prior visit, 3.2★ R-410A 25lb
David L. 8.2mi / 24min HVAC + Electrical EPA 609 Mid-job, ETA done 3:15pm 7:00pm No history R-410A 50lb
Priya N. 2.8mi / 8min HVAC EPA 609 Between jobs 4:30pm No history R-410A 25lb

Scoring:

Dimension Maria S. James K. David L. Priya N.
Skill Match (30%) 30 30 30 30
ETA Fit (25%) 25 20 8 25
Job Status (20%) 20 12 0 20
Shift Remaining (15%) 15 13 15 9 (only 90min left vs 90min job)
Customer History (10%) +10 -15 0 0
Total Score 100 60 53 84

Winner: Maria S. — 100/100. Available now, closest, known to the customer, has parts.

Priya N. scores 84 — she's very close and available, but she'd be cutting it razor-thin on shift time (90min job + return travel, 4:30pm end doesn't work). Flagged for dispatcher review.

Routing Math

The Routing Math: TSP-Style Optimization, Not Greedy Assignment

Most dispatch systems do this: find the best tech for the next job, assign them, repeat. Greedy next-job optimization.

It sounds reasonable. It isn't.

Here's why: a dispatcher running greedy assignment at 7am might assign techs to early-window jobs that look good in isolation — but collectively, they scatter techs across the city in ways that make 3pm jobs unreachable. You get a technically-correct sequence of individual decisions that produces a catastrophically bad day.

CrewOps does TSP-style optimization. Instead of "who's best for this job?" the question is: "how do we route all available techs across all remaining jobs today in a way that maximizes coverage, minimizes drive time, and leaves zero jobs unserviced?"

The agent solves this as a constrained optimization problem:

Maximize: Jobs completed + Customer satisfaction score Subject to: - Each job assigned to exactly one tech - Each tech's route respects shift hours - No tech exceeds max consecutive drive time (60min) - All job windows satisfied (or explicitly deferred with dispatcher sign-off) - Parts availability per vehicle

This runs at the start of each day (morning optimization pass), then re-solves whenever a significant event changes the state — a job completes early, a tech calls out, a new urgent job arrives.

The output isn't a static schedule — it's a live, continuously-improving route plan that the dispatcher can see and the techs receive via their mobile app.

┌─────────────────────────────────────────────────────────┐ Morning Route Plan — 8 Techs · 47 Jobs ├─────────────────────────────────────────────────────────┤ Maria S.: [Depot] → Job 12 → Job 7 → Job 31 → Job 3 ETA: 9:15am | Est. done: 5:12pm | 4 jobs, 18.3mi James K.: [Depot] → Job 22 → Job 9 → Job 18 → [Depot] ETA: 9:30am | Est. done: 5:45pm | 4 jobs, 22.1mi David L.: [Depot] → Job 5 → Job 28 → Job 14 ETA: 9:00am | Est. done: 6:00pm | 3 jobs, 14.7mi Priya N.: Route under review — job 26 window tight └─────────────────────────────────────────────────────────┘

Why End-of-Day Route Quality Beats Single-Job Optimization

At 7am, you have 40 techs and 80 jobs. The greedy approach picks the best tech for job #1, then job #2, then job #3 — each in isolation. By 3pm, you're left with the hardest jobs (furthest from remaining techs, tightest windows) and the most exhausted techs.

TSP optimization front-loads the problem: it looks at all 80 jobs and all 40 techs simultaneously and solves for the best overall day, not the best next decision.

Backtesting result: TSP-style routing reduced missed windows by 34% and average drive time per tech per day by 22 minutes — measured against real dispatch logs from pilot customers.
Exception Handling

Exception Handling: The Decision Tree the Agent Walks

Every day throws something unexpected. Here's how the agent handles the five most common exceptions:

1. Tech Runs Long

Trigger: A tech's current job hasn't completed within the expected time window.

Decision tree:

  1. If ETA overrun < 15 min: flag the tech's next job as "arriving late," auto-update customer ETA via SMS
  2. If ETA overrun 15–30 min: re-score the tech's remaining route; if downstream jobs are now at risk, propose reassignment to the dispatcher
  3. If ETA overrun > 30 min: immediately open the tech's remaining jobs for re-bid, notify the dispatcher, and surface replacement options ranked by score
  4. If the tech marks "job complete" late in the app: close the job, update route, recalculate next-job ETA, push new ETA to the customer automatically
Tech Marcus is 22 min over on Job #412 (heat pump thermostat issue) → Next job is Job #418 at 3117 Oak Valley Dr. → Current ETA: 3:47pm → New ETA: 4:09pm (exceeds 4pm window) → Agent flags Job #418 for dispatcher review → Options surfaced: Priya N. (+2pts after recalibration), David L. (available 4:15pm) → Dispatcher approves Priya reassignment → customer notified automatically

2. Customer Reschedules

Trigger: Customer calls or messages to change the time, or no-shows.

Decision tree:

  1. If reschedule request: validate against tech availability, check parts inventory, propose a new slot from available options
  2. If no-show detected (tech arrives, customer unreachable): hold the job open for 20 minutes, notify dispatcher, and assign the tech to a nearby walk-in or emergency job if one exists
  3. If reschedule creates a gap: leave the slot open; notify the dispatcher of the "tentative" window so they can try to fill it (or leave it as buffer time for the tech's route adjustment)

3. Part Not Available on Truck

Trigger: Tech diagnoses a job and needs a part they don't have.

Decision tree:

  1. Check nearby supply depots / supply trucks for the part
  2. Calculate detour time cost vs. sending a different tech who's closer to the supply depot
  3. If detour is < 45 min: route the tech through the depot, push updated ETA to customer
  4. If detour is > 45 min: reassign the job to a tech who has the part on their truck; current tech gets routed to next job while supply is sourced
  5. If no tech has the part: flag for dispatcher, log the part as "unavailable," send customer notification that we'll reschedule once the part is sourced

4. Weather Event

Trigger: Severe weather warning or active storm conditions in the service area.

Decision tree:

  1. Pull weather API data: active alerts, road conditions by zip code
  2. If weather affects job zone AND job is non-emergency: defer all jobs in the zone, notify customers with rescheduling CTA
  3. If job is emergency (no heat, gas leak, water main break): score techs who can still operate in conditions, flag reduced-speed routes
  4. If roads are impassable: park affected techs, route around weather zones, surface delay ETAs
  5. Dispatcher sees a unified weather dashboard showing all affected jobs and recommended actions — one-click defer if appropriate

5. Tech Calls Out

Trigger: Tech notifies the system (or dispatcher notifies the system) that they're not coming in.

Decision tree:

  1. Identify all jobs assigned to that tech for today
  2. Re-score each job across all remaining techs
  3. Auto-generate proposed reassignments, ranked by score
  4. Dispatcher reviews reassignments in bulk via a single approval action
  5. Customers of reassigned jobs receive an SMS: "Your technician has been updated. [New tech name] will arrive around [new time]. Reply STOP to opt out of SMS."
  6. If no available tech can cover a job, flag it for the dispatcher to call the customer directly
The Human Override Layer

The Human Override Layer: How the Agent Earns Autonomy

The agent isn't running your dispatch board on day one. Here's how the trust is built:

Phase 1: Shadow Mode (Days 1–14)

The agent watches the board, scores all jobs, and shows its proposed assignments — but doesn't dispatch anything. The dispatcher sees the agent's recommendations next to the human assignments and can compare them.

┌──────────────────────────────────────────────────────────┐ Agent Recommendation — Job #1047 ├──────────────────────────────────────────────────────────┤ Customer: 7419 El Camino Real, San Jose Job type: Commercial HVAC preventive maintenance Window: 10am–1pm Agent pick: David L. (Score: 94) Dispatcher pick: Marcus T. (Score: 61) Agent reasoning: David is 2.1mi away with no current job; Marcus is 18min away and still mid-job. [Accept Agent] [Keep Marcus] [Review Later] └──────────────────────────────────────────────────────────┘

This is how the agent learns: when the dispatcher overrides, the system logs why. After 14 days, the agent has enough override history to understand when human judgment exceeds its model — and when it doesn't.

Phase 2: Supervised Autonomy (Days 15–30)

The agent now dispatches automatically — but surfaces every decision to the dispatcher in a review queue. Dispatchers can pull back any assignment with one click. Override rate is tracked and reported.

When override rate drops below 5% of total dispatches, the system flags the shop as candidate for full autonomy.

Phase 3: Full Autonomy (Day 31+)

The agent runs the board unsupervised. Exceptions and boundary cases still surface to the dispatcher — the system is conservative about uncertainty. If the agent encounters a situation it hasn't seen before, it defers to the dispatcher automatically rather than guessing.

The dispatcher is never replaced. They become the exception handler and quality controller — a much better job than staring at a board for 8 hours trying to hold 40 variables in their head.
Roadmap

What's Next: The Roadmap

The current dispatch agent handles real-time job assignment and day-level routing. Here's what's coming:

Multi-Day Planning
The agent currently optimizes today's route. Next phase: it will optimize across a rolling 3-day window, anticipating known demand patterns (e.g., "Thursday the school district has 6 jobs scheduled") and pre-positioning techs to reduce travel.

Predictive Callbacks
Right now, the agent responds to what's happened. The next layer adds prediction: based on job type, equipment age, and seasonal patterns, it will flag jobs with high callback probability before the tech leaves the property — "this capacitor has a 40% failure rate at this age, order the replacement now."

Autonomous Customer Communications
Today, the agent sends ETAs and rescheduling notifications. Soon: it will handle customer confirmations, no-show follow-ups, and post-job satisfaction checks — all without dispatcher involvement. Dispatchers review the message log, not the composing.


Try the Dispatch Simulator
See how the agent handles a live dispatch scenario — input a job, watch the scoring, see the routing output.
Run the Dispatch Simulator →