> ## Documentation Index
> Fetch the complete documentation index at: https://docs.extend.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Confidence Scores

> How Extend scores its confidence in each extracted value, how to read those scores, and how to route on them.

A confidence score tells you how confident the model is in an extracted value, as a number between 0 and 1 (closer to 1 is more confident). Use them to trust high-confidence values automatically and route the rest to human review.

## The two scores

Every entry in the `output.metadata` object can carry two independent scores:

| Field                | Description                                                                 |
| -------------------- | --------------------------------------------------------------------------- |
| `logprobsConfidence` | From the language model, based on token probabilities during generation.    |
| `ocrConfidence`      | From the OCR system, about how reliably the underlying text was recognized. |

`logprobsConfidence` is being phased out. The `extraction_light` processor has never returned it, and `extraction_performance` version `4.6.0` and later return `null`. Prefer `ocrConfidence` and the [Review Agent](/extraction/review-agent) scoring system for new integrations. See [Extraction Performance versions](/model-versioning/extraction/extraction-performance).

## Accessing confidence scores

Scores live in `output.metadata`, keyed by path-like notation that mirrors `output.value`. A root field uses its own name (`invoice_number`); nested and repeated fields use `arrayName[index].propertyName`.

```json
{
  "value": {
    "invoice_number": "INV-123",
    "line_items": [{ "description": "Item A", "quantity": 2 }]
  },
  "metadata": {
    "invoice_number": { "logprobsConfidence": 1.0, "ocrConfidence": 0.99 },
    "line_items[0].description": { "logprobsConfidence": 0.98, "ocrConfidence": 0.95 }
  }
}
```

### Working with arrays

Confidence is reported at every level of an array — the array as a whole, each item, and each property within an item:

```json
{
  "metadata": {
    "line_items": { "logprobsConfidence": 0.98 },
    "line_items[0]": { "logprobsConfidence": 0.99 },
    "line_items[0].description": { "logprobsConfidence": 1.0, "ocrConfidence": 0.95 },
    "line_items[1].description": { "logprobsConfidence": 0.97, "ocrConfidence": 0.92 }
  }
}
```

### Reading scores programmatically

Look up a field's entry by its path key, then read `logprobsConfidence` / `ocrConfidence`.

```python
metadata = result.output.metadata

# A specific field's scores
invoice = metadata["invoice_number"]
ocr = invoice.ocr_confidence

# Flag low-confidence fields for review
for field, meta in metadata.items():
    if (meta.ocr_confidence or 0) < 0.9:
        print(f"Low confidence on {field} — route to review")
```

```typescript
import { Extend } from "extend-ai";

const output = result.output as Extend.ExtractOutputJson;
const metadata = output.metadata;

// A specific field's scores
const invoice = metadata.invoice_number;
const ocr = invoice?.ocrConfidence;

// Flag low-confidence fields for review
for (const [field, meta] of Object.entries(metadata)) {
  if ((meta?.ocrConfidence ?? 0) < 0.9) {
    console.log(`Low confidence on ${field} — route to review`);
  }
}
```

```java
import ai.extend.types.ExtractOutputJson;

ExtractOutputJson output = (ExtractOutputJson) result.getOutput().get().get();
var metadata = output.getMetadata();

// A specific field's scores
var invoice = metadata.get("invoice_number");
var ocr = invoice.getOcrConfidence();

// Flag low-confidence fields for review
metadata.forEach((field, meta) -> {
    if (meta.getOcrConfidence().orElse(0.0) < 0.9) {
        System.out.println("Low confidence on " + field + " — route to review");
    }
});
```

```go
metadata := result.Output.GetExtractOutputJSON().Metadata

// A specific field's scores
invoice := metadata["invoice_number"]
_ = invoice.OcrConfidence // *float64

// Flag low-confidence fields for review
for field, meta := range metadata {
	if meta.OcrConfidence == nil || *meta.OcrConfidence < 0.9 {
		fmt.Printf("Low confidence on %s — route to review\n", field)
	}
}
```

## Routing on confidence in Workflows

In [Workflows](/workflows/overview), conditional steps can branch on an extraction step's confidence — for example, send low-confidence documents to manual review and auto-process the rest.

**Aggregate access:**

* `{{extractionStepName.avgConfidence}}` — average across all fields.
* `{{extractionStepName.minConfidence}}` — minimum across all fields.

These aggregates summarize the per-field confidence scores described above. On processors where `logprobsConfidence` is `null` (such as `extraction_performance` 4.6.0+ and all of `extraction_light`), build routing on `ocrConfidence` and the [Review Agent](/extraction/review-agent).

![Routing a workflow on average confidence](https://files.buildwithfern.com/extendconfig.docs.buildwithfern.com/23758d63e215af786ae7e2730a2807375aed7ddb1412dccc338ca96538b28446/assets/images/conditional_extraction/routing_on_avg_confidence.png)

**Specific-field access:**

* `{{extractionStepName.output.metadata.field_name.ocrConfidence}}` — a field's OCR confidence. Prefer this for new integrations.
* `{{extractionStepName.output.metadata.field_name.logprobsConfidence}}` — a field's model confidence. **Legacy:** this is `null` on `extraction_performance` 4.6.0+ and is never set on `extraction_light` (see the [phase-out note above](#the-two-scores)), so a condition built on it will silently never fire on current processors.

**Example Conditional Logic:**

| Goal                                                                | Condition                                                                    |
| ------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| Route to manual review if any field is low-confidence               | `{{extractionStepName.minConfidence}} < 0.9`                                 |
| Route to manual review if the invoice number has low OCR confidence | `{{extractionStepName.output.metadata.invoice_number.ocrConfidence}} < 0.95` |
| Auto-process if average confidence is high                          | `{{extractionStepName.avgConfidence}} >= 0.98`                               |

Array and nested-object confidence access (for example `line_items[0].description`) is not currently supported in conditional steps.

## Limitations and best practices

While confidence scores are a valuable tool for assessing the reliability of extracted data, it's important to recognize their limitations to use them effectively.

### Not a guarantee of accuracy

A high confidence score indicates a high probability of correctness, **but it doesn't guarantee accuracy**. Even with a high score, there's always a chance of errors, so critical data should always be cross-verified.

### Context matters

Confidence scores are calculated from the model's understanding of the data. They may not account for nuances or context that a human reviewer who understands your business would recognize. Because of this, it's imperative to supply sufficient context on the value you want extracted so the model can determine whether it is confident or not.

For example, if you name a field `company_name` on an extractor designed for invoices, the model may not be confident which name you're asking for, since there are often a couple of different company names on an invoice.

### Best practices

* **Provide clear field descriptions.** Ambiguous field names lead to lower confidence scores — this is your biggest lever on both accuracy and confidence. See [Field Names and Prompt Crafting](/extraction/best-practices/field-names-and-prompt-crafting).
* **Test and iterate.** Monitor confidence patterns in your specific use case and adjust your review thresholds accordingly.