Expert matching
How the platform decides which experts are offered a lead, and in what order the SDM sees them.
Everything here is read from the code on main. The last section names the file and function
behind each rule, so you can check a rule or follow a change to it.
Matching has two steps. When a lead opens for bids, the matcher decides who is on the shortlist, using two hard filters. Each time the shortlist is shown, the platform ranks it, using the same facts as the four ticks on each match card, plus how many of the lead’s skills each expert holds. No score is involved: the same lead and the same profiles always give the same shortlist in the same order.
When the matcher runs
The matcher runs once per lead, when the customer first approves the requirements document (BRD). That approval releases the lead to the bid pool, and the matcher runs straight after it. In the assistant, the customer gets their confirmation first and the matcher runs once the reply has been sent, so a long shortlist never makes them wait. A later approval that corrects the document doesn’t run it again, and the SDM cannot re-run it.
When it finishes, every expert on the shortlist who hasn’t been told yet gets a notification: “You’ve been matched to lead #N — lead title” (the email’s subject leaves the title out). Each expert is told once, a few at a time. An expert the SDM adds by hand keeps their place on the shortlist even if they don’t pass the filters. An expert the SDM invites after the lead is in the bid pool is told straight away.
Nothing is lost if a run is interrupted. Each night, while the lead is in the bid pool, the platform finishes what was missed:
- A matcher run that never finished — the approval marks the lead, and a run that completes clears the mark. A lead still marked ten minutes after its approval has its matcher run again.
- A notification that failed to send — the expert is not marked as told, and the send is tried again every night until it lands or the bid pool closes.
Once the bid pool closes, nobody is told about the lead any more.
What matching reads
The hard filters, the ranking and the four ticks read the facts below, and nothing else.
From the lead:
| Field | What it means |
|---|---|
| Product | The vendor product the work is on. Optional. |
| Industry | The customer’s industry. Optional. |
| Location | The customer’s country, or only a region when no country is set. Optional. |
| Languages | The languages the work needs, as a list. Can be empty. |
| Skills | The skills the work needs, as a list. Can be empty. |
From the expert’s profile (stored):
| Field | What it means |
|---|---|
| Active account | Only experts whose account is active in this organisation are considered at all. |
| Products | The products the expert says they work in. |
| Available | Whether the expert is marked available for work. |
| Industries | The industries the expert serves. |
| Location | The expert’s country and region. |
| Languages | The languages the expert speaks. |
| Skills | The skills the expert holds, as a list. Can be empty. |
| Indicative day rate | What a day of the expert’s time is expected to cost. Optional. Shown on the card; neither the filters nor the ranking use it. |
| Name | The expert’s first and last name. |
About the expert, worked out when needed (not stored on the profile):
| Fact | How it is worked out |
|---|---|
| Certifications per product | The number of the expert’s approved certifications on each product. A certification with no product counts for nothing. Its expiry date is not checked: an approved certification counts. |
| Active projects | The leads in this organisation the expert is delivering now. A lead that has been delivered, or has left the portfolio, doesn’t count. |
| Completed projects | The expert’s leads that reached delivery or later. Shown on the card; neither the filters nor the ranking use it. |
| Past CSAT | The average overall score of the completed customer CSAT responses on the leads the expert delivered, with the number of responses. |
From the organisation’s settings: the active-project cap (below).
Seniority, vetting, engagement class, day rate and the expert’s bio are not read by the filters, the ranking or the ticks. Some of them show on the match card for the SDM to weigh.
The hard filters
An active expert makes the shortlist only if they pass both of these:
- Product. The expert lists the lead’s product on their profile. Listing it is enough here; certifications only affect the ranking. If the lead names no product, nobody is filtered out on product.
- Availability and capacity. The expert is marked available, and they have fewer active projects than the organisation’s active-project cap.
Nothing else filters an expert out. Industry, location, language and skills don’t. They only affect the ranking. An expert who fails a filter is recorded as excluded for that lead. They don’t appear on the shortlist and aren’t told about the lead.
The ranking
The shortlist is put in order whenever it is shown, from current data. Each key below only breaks ties that the keys above it leave:
- Certifications on the lead’s product. More approved certifications first. The count is the expert’s level on that product. If the lead names no product, everyone ties here.
- The lead’s skills held. More first: how many of the lead’s skills the expert holds. A skill the lead lists twice counts once, and a skill the lead doesn’t ask for counts for nothing. If the lead names no skills, everyone ties here.
- Industry tick. Met before not met.
- Location + language tick. Met before not met.
- Capacity tick. Met before not met. Everyone met it when the matcher ran, but availability and workload can change after that.
- Past CSAT. Higher average first. Experts with no CSAT come after everyone who has one.
- Name. Alphabetical, ignoring case and accents. Then an internal expert id, so two experts can never tie.
Day rate is not a ranking key: two experts who tie on everything above are ordered by name, whatever their rates.
The order reads the same facts as the ticks, but the first two keys count certifications and skills rather than ticking them. So an expert with more certifications on the product ranks above one with fewer, even when the second expert holds more of the lead’s skills or meets a tick the first doesn’t, such as Industry. Skills decide the order only between experts with the same number of certifications, and the ticks only between experts who also hold the same number of the lead’s skills.
Experts the SDM adds
The SDM (or an admin) can add an expert the matcher left out, using Invite an expert, with an optional note. An invited expert:
- skips both hard filters;
- comes after every ranked expert, with no “#n of N” position, marked Added by the SDM. If several experts are invited, they are ordered among themselves by the same seven keys;
- is told about the lead straight away if it is already in the bid pool. Otherwise they are told with everyone else when it opens.
Inviting an expert who is already on the shortlist keeps their ranked place.
The SDM’s note on a match
Any match the SDM has left a note on shows it on the card as one muted line, followed by who wrote it and when. That covers an invited expert’s note and a note on a ranked expert, such as a recorded decline: in the demo, Elin Bergqvist’s card on LEAD-001 reads “Declined — full until November; suggested revisiting for the CRM configuration follow-on”, then the SDM’s name and the date. The note stays on the card when the matcher runs again. If the person who wrote it can no longer be found, the line shows the note and the date only.
Looking at the lead as it stood at an earlier moment, the card shows a note only if it had been written by then. An expert the matcher left out and the SDM later invited is not on the shortlist at any moment before the invite.
The active-project cap
The cap sets how many active projects an expert can have before they count as full:
- Default 3. A whole number from 1 to 20.
- Set by an admin or SDM on Settings → Matching. A value outside 1–20 is refused with a message. If nothing is set, or the stored value isn’t valid, the cap is 3.
- Used by both the capacity filter, when the matcher runs, and the Capacity tick, every time a card is shown. Changing it affects shortlists made from then on. It doesn’t change who is already on a shortlist, but it does change the Capacity tick, and with it the ranking.
The four ticks
Each match card has four ticks. Each one is met or not met, with a short reason that shows on hover, keyboard focus or a tap. If the lead doesn’t ask about something, that tick counts as met.
| Tick | Met when | Reasons it shows |
|---|---|---|
| Product | The expert holds at least one approved certification on the lead’s product. Listing the product without a certification is not met. | ”3 Scheduler certifications” · “Knows Scheduler · no certification” · “Doesn’t list Scheduler” · “Lead names no product” |
| Industry | The expert serves the lead’s industry. | ”Works in Healthcare” · “No Healthcare experience listed” · “Lead names no industry” |
| Location + language | Both halves are met. Location: same country as the lead, or the same region when the lead names only a region. Language: speaks at least one of the lead’s languages. | ”Same country (NL) · Speaks Dutch” · “Based in Germany, lead is in NL · Speaks Dutch and English” · “Same country (NL) · Doesn’t speak German or French” · “Lead names no language” |
| Capacity | The expert is available and has fewer active projects than the cap. | ”Available · 1 of 3 active” · “At capacity · 3 of 3 active” · “Unavailable” |
Country, region and language are compared ignoring case. Languages are stored as codes and shown by name (“nl” reads “Dutch”). Price, past CSAT and the lead’s skills held are shown as figures on the card, not as ticks. The Skills line reads “2 of 3 the lead needs”, or “Lead names no skills” when the lead has none.
Who sees what
- SDM and admin: the Matching section of the lead’s workspace, which shows the shortlist in ranked order. Each card shows “#n of N”, the four ticks, and the expert’s class, vetting, experience, availability, projects, location, indicative cost, past CSAT, industries and the lead’s skills held, plus the SDM’s note where there is one. Excluded experts aren’t shown. Seeing the section and inviting experts are separate permissions (Experts). On the demo tenant only, an info button in the section’s header opens a short note: the facts the demo matches on (the ones above), that the matching engine and routing policy can be set up however the vendor delivers work, and a link to the Sustentus team’s contact page. The guided walk’s matching step shows the note’s title and the same link in its bubble.
- Whoever reviews bids (SDM and admin by default): the same four ticks on each bid card (Proposals).
- The expert: their own four ticks for each lead they are matched to, on their bid pool and on the lead’s bid page. They never see their position, other experts, or any score.
- Vendor, CSM and customer: don’t see the shortlist by default.
Shortlists made before the current rules
The order is worked out each time the shortlist is shown, so it is never stored. A shortlist the matcher made under earlier rules keeps the experts it picked, and shows them in today’s order. Nothing is re-run. Only leads matched after a rule change go through the new filters.
Where it lives in the code
Paths are relative to the repository root.
| Rule | File | Function or constant |
|---|---|---|
| When the matcher runs (customer approves the BRD) | packages/services/src/db/services/leads/index.ts | approveBrd → runLeadExpertMatcher |
| The matcher: active experts, filter, write rows, notify | packages/services/src/db/services/matching/run-lead-expert-matcher.ts | runLeadExpertMatcher |
| The two hard filters, applied | packages/services/src/db/services/matching/filter-eligible-experts.ts | filterEligibleExperts |
| Product filter rule | packages/services/src/shared/match-criteria.ts | knowsLeadProduct |
| Availability + capacity filter rule | packages/services/src/shared/match-criteria.ts | hasCapacity |
| Lead fields the rules read | packages/services/src/shared/match-criteria.ts | toMatchCriteriaLead, MatchCriteriaLead |
| Expert profile fields the rules read, skills included | packages/services/src/db/services/expert-engagement/index.ts | findFacts |
| The lead’s skills an expert holds, and the card’s Skills line | packages/services/src/shared/match-criteria.ts | leadSkillsHeld, skillsHeldLine |
| Approved certifications per product | packages/services/src/db/services/expert-evidence/index.ts | approvedCertificationCounts (counted by countCertificationsByProduct) |
| Active and completed projects | packages/services/src/db/services/matching/expert-metrics.ts | getExpertTrackRecords (counted in the database by a $group that mirrors trackRecordBucket in match-criteria.ts) |
| Past CSAT and vetting | packages/services/src/db/services/expert-engagement/index.ts | findMatchSignals |
| The four ticks | packages/services/src/shared/match-criteria.ts | evaluateMatchCriteria |
| The ranking and its seven keys | packages/services/src/shared/match-criteria.ts | rankMatches, leadProductCertifications, leadSkillsHeld |
| The shortlist as the SDM sees it, ranked, with positions | apps/web/lib/queries/workspace.ts | buildAggregate (calls rankMatches) |
| An expert’s own ticks on their bid pool and bid page | packages/services/src/db/services/matching/expert-criteria.ts | getExpertCriteriaForLeads (called by findBidPoolLeads) |
| Invite an expert | packages/services/src/db/services/matching/lead-expert-match-service.ts | addManualMatch |
| The SDM’s note on the card, and the shortlist as at a moment | apps/web/lib/workspace/match-note.ts | matchNoteAt, onShortlistAt |
| Telling matched experts | packages/services/src/db/services/matching/lead-expert-match-service.ts | notifyPendingMatches → notifyExpertLeadMatch |
| The active-project cap: default, range, reading a stored value | packages/services/src/shared/match-criteria.ts | DEFAULT_ACTIVE_PROJECT_CAP, MIN_ACTIVE_PROJECT_CAP, MAX_ACTIVE_PROJECT_CAP, resolveActiveProjectCap |
| The cap as a setting | packages/services/src/db/services/tenant-setting/registry.ts | matching.activeProjectCap |
| Reading and saving the cap | packages/services/src/db/services/tenant-setting/index.ts | getActiveProjectCap, setActiveProjectCap |
| Settings → Matching (admin and SDM) | apps/web/app/(app)/settings/matching-actions.ts | saveActiveProjectCap |