What is a confidence threshold?
A confidence threshold is the score an automated decision must clear before it is acted on, sending anything below it to a person instead.
A confidence threshold turns a number into a policy. A model returns a score between 0 and 1. The threshold is the line your code compares it against, and the comparison decides what happens next: act on it, ask a person to confirm, or hand the item over untouched.
The number belongs to the model. The line belongs to you.
Three bands, not one line
One threshold gives two outcomes, which is usually too blunt. Two thresholds give three bands, and the middle one carries most of the value:
- Act. Above the upper line the system does the thing and records it.
- Confirm. Between the lines it prepares the action and waits for a yes.
- Escalate. Below the lower line it does nothing and routes the item to a person, with whatever it worked out attached.
| Band | What the code does | Who sees it at the time | Cost of being wrong |
|---|---|---|---|
| Act | Performs the action | Nobody, until someone reviews | A wrong action, already taken |
| Confirm | Prepares it, waits for a yes | The person asked | A minute of somebody's attention |
| Escalate | Stops, routes the item | Whoever owns the queue | A delay, and a queue to clear |
The bands are not equal in weight. Moving an item from confirm to act saves seconds. Moving one from escalate to act can cost you a customer. Size them by consequence, not by volume.
Where a published ladder fits
A vendor that returns a confidence number often publishes suggested bands beside it. TypeSafe's documentation for its System One model describes three in words rather than numbers: high confidence means a clear read you can proceed on without human involvement, medium means proceed with caution, and low means do not act, but route to a human or fall back to another system. Its worked example uses 0.9 and 0.5 as the lines, and the branch above 0.9 still confirms with the user before executing, because that example's action is a high stakes one.
The vendor states both caveats itself: the right values depend on your domain and on how the model performs there, and different actions inside one system should be gated at different levels according to the consequences of getting each wrong. A published ladder is a worked example to evaluate, not a setting to copy.
How to set one, as a procedure
A threshold is derived, not chosen, and deriving it takes an afternoon:
- Take a real sample. One to three hundred items you actually received, awkward ones included. Invented examples are always easier than real ones.
- Label it by hand first. Decide the right answer before you see any score. Labelling afterwards quietly turns into agreeing.
- Run the sample and keep each score beside its item and your label.
- Sort by score, highest first.
- Find the disagreement line, the point walking down that list where the model's answer starts differing from your label.
- Set the act floor above it, with room to spare, and the escalate floor where disagreement stops being occasional.
- Keep the sample and re-run it after a model or prompt change. A threshold is only valid for the setup it was measured on.
If disagreement is spread evenly through the sorted list instead of clustering at the bottom, the score is not separating easy items from hard ones and no threshold will fix that. The property being tested there has a name, calibrated confidence.
Both directions cost something
| Floor set | What you buy | What it costs | How you find out |
|---|---|---|---|
| Too low | Volume handled automatically | Wrong actions taken unattended | A complaint, or a receipt someone reads |
| Too high | Almost no wrong actions | A queue nobody clears | Slowly, or never |
Only one of those failures is visible. A wrong send arrives in somebody's inbox and gets reported. A queue growing faster than it is cleared just sits there, and the usual ending is people approving in batches without reading, which is having no threshold, with paperwork on top.
A probability is not a severity score
This is the commonest mistake, and easy to make because the numbers look alike.
For a yes-or-no question the returned probability is the answer, not a measure of how much. A 0.55 on "is this request fraudulent" means yes and no are close to equally likely, not "mildly fraudulent". Thresholded as an intensity it gives you a system that treats its most uncertain items as its moderate ones. TypeSafe's wire makes the distinction structural: choice and score answers carry a confidence derived from the shape of the answer's probability distribution, and yes-or-no answers carry no confidence field at all.
When you want intensity, ask for intensity, which the vendor's own advice puts as using a score question measuring along defined levels. One reason structured output is worth having is that it forces you to say which of the two you are asking for.
Escalation has to land somewhere a person looks
A threshold routing low scores into a queue nobody owns is decoration. The path needs four things before the line means anything: a named owner rather than a team alias, a place they already work such as an inbox or a helpdesk view, a time limit, and a stated default for when that limit passes, because "it sat there" is also a decision, just not one anybody made.
When a threshold is the wrong tool
A floor is a way of spending a number you already trust. Five situations where there is no such number, and adding a line to your code only hides that:
- The score does not separate. If the disagreement in your sorted sample is spread through it rather than piled at the bottom, every floor you pick splits the pile at random. Fix the question or the model, or read calibrated confidence for what to measure first.
- Ordinary code already knows. Amount over a figure, sender on a list, date in the past, two fields equal. Arithmetic and lookups are exact, free and reviewable by anyone. A model score is a probabilistic instrument for questions arithmetic cannot answer, and it is strictly worse for the ones it can.
- The volume is too low to measure on. A floor is derived from a sample. If you see twenty of these a month, you cannot find the disagreement line, and a number copied off a vendor page is a guess with a decimal point on it. Have the person do the twenty.
- Being wrong is unacceptable and nobody is downstream. A threshold makes uncertainty visible. It does not make the model right, and it cannot invent a reviewer. Where there is no acceptable error rate, the honest answer is not a higher floor, it is not running that step unattended.
- The decision has legal consequences for a person. Hiring, credit, benefits, discipline. These are not gated by a number at any value. Sorting and surfacing the case for a human reviewer is fine. Letting the floor decide is not, however well calibrated the score behind it is.
What this looks like on WorkerKit today
WorkerKit runs two shapes of worker, and only one has a number to threshold on.
A decision worker judges each item with typed questions and routes on the answer in code, with no agent loop in between. A confidence floor is required, and below it the worker does not act: the item escalates to a person.
An agent worker returns work rather than a calibrated number, so its three bands are built out of controls instead of a score.
| Band | How it is built on an agent worker | Where it surfaces |
|---|---|---|
| Act | Instruction says do it, app held at Write | A run receipt |
| Confirm | Instruction says draft and stop, app held at Read | A draft waiting in your own account |
| Escalate | Instruction says ask, contact rules cap who it may reach | A message to you, item untouched |
The load-bearing row is the middle one. Holding an app at Read in the app firewall makes the worst case a wrong draft instead of a wrong send, and unlike a line in an instruction it is enforced outside the model, which is the subject of an instruction is not a control. A decision worker's reads and actions go through that same door, one tool call on its own key.
Support Inbox Triager is the shape in practice: it reads, sorts and drafts on its schedule, and a person sends. Receipts make each run reviewable, which is how you learn whether your floor sits near right, and the order to roll that out in is in rolling out an AI worker safely.
FAQ
What is a good confidence threshold to start with?
There is no portable number. A threshold is a property of your items and your model together, so it has to be measured: label a sample of your own real items by hand, score them, sort by score, and find where the model starts disagreeing with you. Set the floor above that point. A vendor's published ladder is an example to evaluate against that sample, not a setting to copy.
Can I use one confidence threshold for everything a system does?
You should not. Different actions carry different consequences and deserve different floors: reading a record can be gated far lower than sending a message or moving money. One global threshold is either too loose for the risky actions or too tight for the cheap ones, usually both at once.
Does a high confidence score mean the answer is correct?
No. A confidence score is derived from the shape of the model's own probability distribution, so it says the answer is concentrated rather than spread. That is agreement with itself, not with the world. A confident model can be confidently wrong, which is why the escalation path still matters.
What does a 0.5 mean on a yes-or-no question?
It means yes and no are close to equally likely, not that the thing is half true. A yes-or-no probability is not a severity score, and reading it as an intensity is the commonest error with these systems. If you want to know how much rather than whether, ask a question that measures along defined levels instead.
How does a confidence threshold work on a WorkerKit worker?
A decision worker declares a required confidence floor and does not act below it: the item escalates to a person. An agent worker returns work rather than a score, so its equivalents are structural: the instruction telling it when to stop and ask, the app firewall holding an app at Read so the worst case is a wrong draft, contact rules limiting who it can reach, and a receipt per run.