Skip to content
Talk to our solutions team

Values

Every directional read, cell read and pattern read returns a Value. It is either a hit or a miss, it knows why it missed, and it carries the provenance of the hit.

out.Set("loanAmount", bbox.Doc().Right("Loan Amount").Currency());
// read coercion

Whether a value was extracted.

rule LoanAmountPresent "the amount must be readable" salience 20 {
when
bbox.Doc().Right("Loan Amount").Missing()
then
findings.Critical("LoanAmountPresent", "extraction",
strings.Sprintf("Loan amount not found: %s",
bbox.Doc().Right("Loan Amount").Reason()));
}

Explains a miss: which stage failed, rather than an empty string that could mean any of four things — label not found, label found but nothing beside it, value found but the coercion rejected it, or scope excluded it.

This is the first thing to put in a finding when an extraction fails, and the first thing to log when a rule silently produces nothing.

Renders the provenance of a hit: what text matched as the label, on which page, at what distance.

Reason explains a failure; Why explains a success. When a rule extracted the wrong value — matched the label in the footer rather than the body — Why is what tells you.

rule TraceAmountRead "record where the amount came from" salience 5 {
when
bbox.Doc().Right("Loan Amount").Found()
then
log.Debug("loan amount provenance",
"why", bbox.Doc().Right("Loan Amount").Why());
}

The extracted text, or "".

The value as a number, or 0.

Thousands separators and a leading currency sign are stripped before parsing, so a bare "$1,234" reads as 1234 rather than as zero.

Each returns another Value, so they compose with Found(), Or() and Str().

Strips currency symbols and thousands separators, leaving a bare number. Accounting parentheses are handled.

Replaces a hand-escaped regular expression that the production corpus repeated 328 times.

rule CaptureLoanAmount "the amount, as a bare number" {
when
bbox.Doc().Right("Loan Amount").Found()
then
out.Set("loanAmount", bbox.Doc().Right("Loan Amount").Currency());
}

Extracts the first number in the value.

Extracts a percentage as a bare number.

A %-suffixed number is preferred wherever it sits in the value; only when the value contains no % does the first bare number win. That ordering matters on a line like "Rate 6.125% (APR 6.310%)".

Normalises to YYYY-MM-DD.

A value that does not parse is a miss, not a zero date. The corpus guarded dates with != "0001-01-01" in seven places before this existed; with a miss there is no sentinel to compare against — ask Found().

Normalises an affirmative or negative to "Yes" or "No".

Single-letter forms count: a form’s answer column is routinely a lone Y or N.

Title-cases the value.

Trims the value. Present for symmetry — reads already trim — so a chain can be written uniformly.

Keeps only the first substring matching the pattern.

ParameterTypeMeaning
patternstringA regular expression

The last resort, kept so the coercion set above can stay closed. Reaching for it repeatedly is a signal that a coercion is missing — worth reporting rather than working around.

Substitutes a fallback when the read missed.

ParameterTypeMeaning
fallbackstringThe value to use instead

The result is found — but it carries no confidence, because it was supplied rather than extracted. That distinction survives into the output, so a downstream consumer can still tell a default from a reading.

rule PropertyTypeWithDefault "unstated property type is single family" {
when
in.Has("application")
then
out.Set("propertyType",
bbox.Doc().Right("Property Type").Or("Single Family"));
}

Use it where the absence has a defined meaning. Where absence is a problem, raise a finding instead — a default quietly papers over a document you could not read.

The computed extraction confidence, from 0 to 1.

A real score, not a constant: label edit distance, value OCR confidence, alignment and proximity all contribute. It is worth gating on.

rule LowConfidenceAmount "the amount was read, but not clearly" {
when
bbox.Doc().Right("Loan Amount").Found() &&
bbox.Doc().Right("Loan Amount").Confidence() < 0.8
then
findings.Warn("LowConfidenceAmount", "extraction",
strings.Sprintf("Loan amount read at %s confidence",
to.Fixed(bbox.Doc().Right("Loan Amount").Confidence(), 2)));
}

The metadata a delivery profile may surface. The engine never inspects these; they ride along with out.Set and a profile decides which reach the caller.

Lets the engine carry the extracted text without a conversion at the call site.

A miss becomes null, which is what makes out.Set skip it — so writing a missing value does not put an empty string in your output where a consumer would read it as data. You rarely call this directly; it is why out.Set(path, someRead) behaves correctly.

A read that missed and a read that found an empty string are different, and the API keeps them different at every step: Missing() distinguishes them, Reason() explains which stage failed, Or() marks a supplied value as unscored, and EngineValue() keeps a miss out of the output entirely.

The one thing that collapses the distinction is Str() — a miss and an empty hit both give "". Guard with Found() before Str() whenever the difference matters.