Skip to main content

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 (L0L3, 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.

Reading a dossier quickly: trust "verified" + status "active" means the platform already executes this plan in pipelines. trust "mined" with a high ci95_low and healthy distinct_values is a strong promotion candidate. trust "inferred" with null evidence is a name-based hypothesis — useful context, not something to build on unattended.

bindings[] fields

plan_iduuid | nullThe persisted plan's id — set after write-back, so effectively always present on this surface.
truststringEmpirical grade: inferred (hypothesis), mined (corpus-tested), verified (human/platform confirmed).
statusstringPlan lifecycle: candidate (inert), active (executed by pipelines), retired.
ladderstringThe cost-ladder rung this answer came from: L0, L1, L2, or L3.
evidenceobject | nullThe corpus dossier: { n, agree, agreement, ci95_low, distinct_values, method, notes }. Null when the plan has not been measured.
sources[]arrayRegistry entries feeding the plan: { registry_id, role, canonical_name }. canonical_name is null when the registry row no longer exists.
combinestring | nullHow source values become the target value: first_of, template, date_from_parts, or amount_currency.
guardobject | nullDoc-class gate: { doc_type_id_in, doc_type_name_in }. Null when the plan applies to every document; a non-matching guard makes the plan abstain at execution.

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');
}

Frequently asked questions

Why rank by ci95_low instead of the raw agreement ratio?+
Because raw ratios ignore sample size: 3 agreements out of 3 documents is 100% but proves little, while 179 of 184 is 97% on real evidence. The Wilson 95% lower bound discounts small samples, so ranking and promotion gates compare a number that can only be high when both the ratio and the sample are.
What does distinct_values guard against?+
Coincidental agreement. If a plan and the authored label agree across 40 documents but every one of them carries the same value, the agreement is one data point wearing 40 costumes — a currency column that always says EUR proves nothing about the mapping. A healthy distinct_values count means the plan tracked the label across genuinely varying data.
Can I promote a candidate plan through this API?+
No — deliberately. This surface proposes and grades; activation, retirement, and verification happen through the platform's own registry governance so a promotion is always an accountable act. The dossier this endpoint returns is exactly what that promotion decision reads.
Why is canonical_name sometimes null on a source?+
The plan references a registry row that has since been merged away or deleted. The source is kept in the plan's provenance with a null name rather than dropped, so you can still see the plan's full shape — and treat the dangling reference as a hint that the plan predates a registry cleanup and may deserve re-mining.