---
title: "AI Matcher"
description: "Ring's AI matching engine — LLM-powered Matcher with eight scored factors, baseline NeuralMatcher fallback, moderation summaries, and a training pipeline over the event log"
locale: "en"
---
# AI Matcher

> **Info**
> Use **Founder** / **Developer** tabs in the docs sidebar to filter this page. The feature loop (create → match → notify) lives in [Opportunities](/docs/features/opportunities.md); this page is the **engine** behind the scores.

The AI Matcher is Ring's matching engine: it scores every candidate against an opportunity across **eight factors**, explains *why* in ≤160 characters, and falls back to a baseline vector matcher when no LLM is configured. The same AI surface also summarizes entity moderation reports for the admin queue.

| Previous | Ring equivalent |
|----------|-----------------|
| Keyword search on listings | Scored candidate matching with LLM explanations |
| One model, hard-coded | Model router (`lib/ai/model-router`) with task classes |
| Matching quality guesswork | Training pipeline learns from `opportunity_matched` / `application_success` events |
| Manual moderation triage | LLM one-sentence report summaries → admin queue + tunnel notify |

## Eight scoring factors

`MatchFactors` in `lib/ai/types.ts` (each 0–100): `skillMatch`, `experienceMatch`, `industryMatch`, `locationMatch`, `budgetMatch`, `availabilityMatch`, `careerMatch`, `cultureMatch`.

Runtime thresholds are **clone config**, not kingdom-wide SLAs. Defaults (`ring-config.json → matcher`): `scoreThreshold` **0.7**, `maxMatches` **10**, `autoApprove` **false**, `autoApproveMinScore` **0.7**, `llmConfidenceGate` **0.8**. Explanations are truncated to **≤160 characters** by `MatchingService`.

### For founders

## Why this matters for your clone

- **Matches find members.** New opportunities run the matcher pipeline and notify the best fits — members don't have to search the feed.
- **Explanations build trust.** Each notification carries a short "why this matches you", not just a score.
- **You control the gates.** Tune `scoreThreshold`, `maxMatches`, and auto-approve in **Admin → Platform Settings → AI → Matcher**; leave auto-approve off until you trust your vertical's data.
- **Moderation gets easier.** Entity reports are LLM-summarized in one sentence for your admin queue.

### Operator checklist

1. Keep Matcher thresholds at defaults until you have real traffic.
2. Review match quality bands (high ≥80 / medium 60–79 / low <60) in Matcher analytics — they are signals, not guarantees.
3. When confident, raise `maxMatches` or enable `autoApprove` with its score and LLM confidence gates.

### For developers

## Engine modules (verified)

| Module | Role |
|--------|------|
| `lib/ai/matcher.ts` | `Matcher` class — LLM scoring + explanations; `cache()`-wrapped candidate profile loading |
| `lib/ai/neural-matcher.ts` | `NeuralMatcher` baseline — tag/vector similarity via `lib/ai/vector-store` when LLM is unavailable |
| `lib/ai/matcher-moderation-notify.ts` | LLM one-sentence summaries of entity moderation reports → admin queue + tunnel channel |
| `lib/ai/training-pipeline.ts` | `AITrainingPipeline` — supervised examples from the event log (`opportunity_matched`, `application_success`) |
| `lib/ai/model-router/` | Model catalog, task classes, and resolution |
| `lib/ai/user-profile-loader.ts` | Maps `users` documents → `UserProfile`; capped by `MATCHING_MAX_CANDIDATES` |
| `lib/ai/llm-client.ts` | `createLLMClientAsync` / `isLLMAvailableAsync` availability gates |
| `lib/ai/types.ts` | `MatchFactors`, `LLMConfig`, `AIOperationError` |

## Configuration

**Environment (fallbacks only — config wins)**

{`MAX_MATCHES_PER_OPPORTUNITY=10   # fallback cap
MATCHING_SCORE_THRESHOLD=0.7      # fallback min score
MATCHING_MAX_CANDIDATES=200       # candidate scan cap`}

`Matcher` prefers the resolved AI config from `features/admin/platform-settings/resolved-ai-config`; env values are fallbacks read at construction.

**Clone config (`ring-config.json → matcher`)**

{`"matcher": {
  "scoreThreshold": 0.7,
  "maxMatches": 10,
  "autoApprove": false,
  "autoApproveMinScore": 0.7,
  "llmConfidenceGate": 0.8
}`}

Overrides exist per clone; `MATCHER_AUTO_APPROVE` / `MATCHER_AUTO_APPROVE_MIN_SCORE` env can also toggle auto-approve.

### How a match run flows

`OpportunityMatchingService` → `Matcher` (LLM) or `NeuralMatcher` (baseline) → `MatchFactors` + explanations → notification fan-out. Matched users open the opportunity; their reactions feed the training pipeline's event collection.

## Related documentation

  
- [features/opportunities](/docs/features/opportunities.md) — Same-workflow: the create → match → notify loop that consumes this engine.

  
- [architecture/discovery-mutation-sync](/docs/architecture/discovery-mutation-sync.md) — Deep-dive: how new opportunities trigger the matcher pipeline and keep match cards fresh.

  
- [features/admin](/docs/features/admin.md) — See-also: Matcher thresholds live in the admin platform settings.
