Evidence, Sources & Guards
Read a binding resolution's response: trust grades, the corpus evidence dossier with Wilson bounds, source roles, combine operations, and doc-class guards.
Each entry in resolutions[].bindings[] is one plan with its dossier — everything an agent (or a human) needs to decide whether to trust the binding. Bindings are ranked: verified-active plans first, then by the evidence's Wilson lower bound, descending. The core grading fields are trust (inferred → mined → verified, in ascending order of empirical backing), status (candidate, active, or retired — this endpoint only ever creates candidate), and ladder (L0–L3, the rung that produced or recalled the plan on this call).
The evidence object is the plan's promotion dossier, measured by executing the plan across documents where both its sources and an authored label were present: n (documents tested), agree (documents where the plan reproduced the label), agreement (agree / n), and ci95_low — the Wilson 95% lower bound, the number gates actually compare against, because a 3-for-3 plan should not outrank a 179-for-184 one. distinct_values is the coincidence guard: agreement across one repeated value (every document saying "EUR") is close to no signal, however high the ratio. method records how the plan was born (mining, synthesis, or human). evidence is null for a plan that has not been measured — an unmeasured plan is never dressed up as a measured one with zeros.
sources[] names the registry entries the plan reads: each with registry_id, its plan-local role (the handle the combine step refers to), and canonical_name — resolved fresh at answer time in one registry query. A source whose registry row has since been merged away or deleted keeps its place with canonical_name: null rather than being silently dropped, so a plan's provenance is always complete even when the registry has moved on. combine is the operation that turns source values into the target value: first_of (priority order, first non-null wins), template (string assembly that abstains unless every referenced role resolved), date_from_parts, or amount_currency.
guard is the plan's doc-class gate: doc_type_id_in and/or doc_type_name_in restrict which document classes the plan applies to (names are matched case-insensitively — a fallback for workspaces where type ids are unstable). A null guard means the plan applies to every document. At execution time a guard mismatch makes the plan abstain, never error — the same contract as a missing source or a transform that cannot parse its input. Plans are deterministic end to end: execution never involves an LLM, only the L3 *authoring* rung does.
bindings[] fields
One binding, annotated
{
"plan_id": "4a6c8e0b-2d4f-4a7c-9e1b-3f5d7a9c1e3b",
"trust": "mined", // corpus-tested, not yet human-verified
"status": "candidate", // inert until promoted
"ladder": "L2", // produced by corpus mining on this call
"evidence": {
"n": 184, // documents where plan + label were both present
"agree": 179, // documents where the plan reproduced the label
"agreement": 0.9728,
"ci95_low": 0.9391, // Wilson lower bound — what gates compare
"distinct_values": 172, // 172 distinct agreed values: real signal
"method": "mining",
"notes": null
},
"sources": [
{ "registry_id": "9b1d3f5a-7c9e-4b2d-8a4c-6e0f2b4d6a8c", "role": "rechnungsnummer", "canonical_name": "Rechnungsnummer" }
],
"combine": "first_of",
"guard": { "doc_type_id_in": null, "doc_type_name_in": ["Rechnung", "Invoice"] }
}Filtering to actionable plans (TypeScript)
const res = await fetch('https://api.talonic.com/v1/binding-resolutions', {
method: 'POST',
headers: {
Authorization: 'Bearer tlnc_your_api_key',
'Content-Type': 'application/json',
},
body: JSON.stringify({
targets: [{ field_key: 'invoice_number', data_type: 'string' }],
min_trust: 'mined',
}),
}).then((r) => r.json());
for (const { field_key, bindings } of res.resolutions) {
const best = bindings.find(
(b) => b.evidence && b.evidence.ci95_low >= 0.9 && b.evidence.distinct_values >= 5,
);
console.log(field_key, best ? `bind via ${best.sources.map((s) => s.canonical_name).join(' + ')}` : 'abstained');
}