Skip to main content

Provenance Required Policy

The provenance-required policy enforces OWASP LLM09b (misinformation / overreliance, sub-control "provenance"). It is the stricter cousin of the Grounding Policy: where grounding accepts a threshold like "groundedness score >= 0.6 is fine," this handler is binary — cite-or-fail.

Three independent checks:

  1. Unsupported-claim tolerance — how many claims may go uncited before the policy fires.
  2. Minimum citation count — total citations across the run must meet a floor.
  3. Source-type allowlist — every citation must reference an approved source type (e.g., knowledge_base, verified_corpus, internal_doc).

Aligns with NIST AI RMF MS-2.1 (Measure → Truthfulness).

Rules

RuleTypeDefaultDescription
require_citations_per_claimbooleantrueWhen true, unsupported claims are counted against max_unsupported_claims
max_unsupported_claimsinteger0Tolerance — claims allowed without citation (0 = strict)
min_citationsinteger1Minimum total citation count across the run
allowed_source_typesstring[][]Empty = any type accepted; non-empty = citations must reference one of these
action_on_violationstring"block""block" or "warn"

Optional: scan_mid_execution (boolean, default false) — enables defensive mid-run check on streaming surfaces.

How It Works

PhaseWhat it does
before_workflowStashes rules on context._provenance_rules. No enforcement (claims don't exist yet).
mid_execution (opt-in)Same evaluation as after_workflow — runs only if scan_mid_execution=true.
after_workflowPrimary enforcement — full claim/citation inventory check.

Evaluation order (short-circuits on first violation):

  1. Unsupported-claim tolerance — if len(unsupported_claims) > max_unsupported_claims.
  2. Minimum citation count — if len(citations) < min_citations.
  3. Source-type allowlist — first citation with disallowed source type.

Context Attributes Read

AttributePhasePurpose
context.citationsmid, afterList of citation objects (str OR dict with source_type/type/kind/source)
context.unsupported_claimsmid, afterList of claim strings, OR an integer count
context.grounding_entriesmid, afterOptional per-step grounding records (read for richer metadata)

Example Policy

Regulated knowledge agent — every claim must cite an internal knowledge-base or verified corpus source, no exceptions:

{
"require_citations_per_claim": true,
"max_unsupported_claims": 0,
"min_citations": 1,
"allowed_source_types": [
"knowledge_base",
"verified_corpus",
"internal_doc"
],
"action_on_violation": "block"
}

SDK Integration

import waxell_observe as waxell

waxell.init()

@waxell.observe(agent_name="compliance-assistant", enforce_policy=True)
async def answer(question: str) -> str:
# Populate citations as you generate the response.
async with waxell.WaxellContext(agent_name="compliance-assistant") as ctx:
result = await retrieve_and_answer(question)
ctx.set_citations([
{"source_type": "knowledge_base", "id": "kb-1234", "title": "..."},
{"source_type": "verified_corpus", "id": "vc-9876"},
])
# after_workflow: blocks if no citations or wrong source type
return result

Observability

FieldExample
Categoryprovenance-required
Actionblock
Reason"3 unsupported claim(s) detected; tolerance is 0."
Metadata{"phase": "after", "signal": "unsupported_claims", "count": 3, "limit": 0, "owasp": "LLM09"}

Disallowed source type:

FieldExample
Reason"Citation source type 'web_search' not in approved list ['knowledge_base', 'verified_corpus']."
Metadata{"signal": "disallowed_source_type", "source_type": "web_search", "owasp": "LLM09"}

Common Gotchas

  • unsupported_claims can be either a list or an integer count. The handler handles both. If your runtime emits a count, the metadata count field reflects that integer; if it emits a list, count is len(list).
  • min_citations=0 disables the citation-floor check. Set to 1 (the default) to require at least one citation.
  • Source-type lookup tries four keys on dict citations. In order: source_typetypekindsource. Plain-string citations are treated as the source type itself.
  • Case-insensitive matching on source types. "Knowledge_Base" and "knowledge_base" are equivalent.
  • Citations with empty/missing source type are skipped silently during the allowlist check — they don't fire a violation. To enforce a present source type, use a separate validator.
  • Grounding vs Provenance. Grounding scores claims for support strength; provenance demands a citation regardless of score. Often deployed together — grounding warns at low scores, provenance blocks at zero citations.
  • before_workflow is a no-op for enforcement. It only stashes the rules; the actual check happens at after_workflow once claims exist.

Next Steps