unlob Docs
Browse documentation

Grounding: one call, an evidence set with a receipt

Give ground an objective and a budget; get back evidence with provenance, and a receipt that says whether it is enough.

What it is

ground is the call to start with. Search retrieves passages; ground says what the retrieved evidence is — who originally published it, who republished it, what kind of source each item is, whether two items are actually independent, how fresh the set is — and whether it is enough to act on. No generated answer comes back. The evidence and its structure do, and the reasoning is yours, with whichever model you use.

curl -sG -H "x-api-key: $UNLOB_API_KEY" https://api.unlob.com/ground \
  --data-urlencode 'objective=what changed in the UK AI regulation position this week' \
  -d max_age=7d -d min_independent_origins=2 -d token_budget=3000

A call costs 5 credits, however many stories it expands on the server, and a call that runs and fails costs 1. See Pricing.

The request

ParameterMeaning
objectiveWhat you need evidence for — a question, a task, or a claim to check. q is accepted as an alias.
token_budgetCeiling on the evidence returned, in estimated tokens. Default 3000.
max_ageThe freshness contract: seconds, or 30m, 6h, 7d, 2w.
min_independent_originsOrigins with distinct owners required for sufficient. Default 2.
require_roleRoles of which at least one must be present for sufficient. Default primary,official; an empty string means no requirement.
latency_budget_msBound on the time spent expanding stories into their members.
claimExperimental: relate each item to this claim. See Provenance.
strip_instruction_likeRemove instruction-like sentences from snippets instead of only flagging them. See Untrusted content.
mode, vertical, lang, safeThe same meanings as on /search.

The response

{
  "status": "sufficient",
  "objective": "…",
  "evidence": [
    {
      "hit": { "id": "…", "url": "…", "host": "reuters.com", "snippet": "…" },
      "reason": "wire · 2 origins in this story · secondary source · owner: Thomson Reuters",
      "source_role": "secondary",
      "origin_type": "wire",
      "origin": "o:3f2a9c1e4b7d",
      "owner": "Thomson Reuters",
      "independence_score": 1.0,
      "age_secs": 2220,
      "risk_flags": []
    }
  ],
  "origins": [  ],
  "coverage": { "complete": true, "independent_origins": 2, "known_gaps": [] },
  "budget": { "token_budget": 3000, "context_tokens": 1420, "credits_billed": 5 },
  "next_actions": [],
  "provenance": { "method": "deterministic", "generated_at": 1757800000 }
}

Each evidence item is the representative passage of one origin. Republishes never appear as evidence; they are listed under the origin they copy. What each field means is on Provenance and independence; what coverage reports is on Coverage receipts.

Read status first

statusMeaningDo
sufficientAt least min_independent_origins origins with distinct owners, and a source in require_role presentRead evidence and act
insufficientEvidence exists but does not meet the barFollow next_actions, or say the evidence is thin
staleNothing inside max_age; stale_evidence shows what older material existsWiden max_age, or report that nothing recent was found
partialPart of the index was unreachableRetry; never treat the answer as complete
emptyNothing foundReformulate, or ask why_not before asserting absence

The status is computed by a fixed rule, in this order: partial if any part of the index failed to answer; empty if no evidence came back; stale if a window was set and nothing inside it was found; sufficient if the origin count and the role requirement are met; insufficient otherwise. No model is involved anywhere in the call, so the same corpus and the same request give the same status.

next_actions

When the set is not sufficient, next_actions says what would change that, as things you can do with this API: retry on a partial answer, widen_max_age with a suggested value, corroborate a specific item, a search with a filter hint (an authority or content-type filter when a required role is missing), why_not before concluding absence, or get_document when a snippet was truncated. They are suggestions in a fixed vocabulary, not instructions from the corpus.

Budgets

token_budget is honoured as a ceiling on the evidence returned; budget.context_tokens reports what was packed, estimated from the snippets and titles. latency_budget_ms bounds the per-story lookups: when it cuts in, coverage.not_searched.story_expansion_truncated is true and the unexpanded stories still contribute their best passage, just without corroboration.

When to use it

  • ground — “what should I know, and can I trust it”: evidence with provenance and a verdict on sufficiency.
  • search — “find me the page that says Y”: ranked passages with filters, and the cheapest call.
  • assemble_context — a budget-packed reading set ranked by corroboration, without provenance or a receipt.

Over MCP, ?profile=grounding lists only ground and get_document — see Profiles.

Next