Skip to main content

Evidence Gate

Stop your AI from making up facts about your own data.

A tiny, zero-dependency gate you call before an LLM generates anything. It looks at the records you actually have and returns whether the model may summarize, whether the data is stale or low-quality, and the exact caveats to inject into your prompt.

It is the missing step between "retrieve" and "generate" in most RAG and agent pipelines: a check that the evidence is actually good enough to speak from.

import { evidenceGate, presets } from "evidence-gate";

const gate = evidenceGate({ records: myRecords, rules: presets.FINANCE });

if (!gate.allowedActions.summarize) {
  return gate.caveats.join(" ");   // e.g. "No financial statements available — the AI must not invent numbers."
}

const prompt = `${systemPrompt}\n\nDATA RULES:\n- ${gate.caveats.join("\n- ")}\n\n${userPrompt}`;

The problem

LLMs answer confidently even when the underlying data is missing, stale, or partial. Over your own database that means a chatbot inventing a quarter that doesn't exist, quoting a number from a cached/secondary source as if it were authoritative, or saying "as of today" about data that's months old.

Content-safety guardrails (toxicity, PII) don't catch this. This is a grounding problem, and it needs a grounding gate.

What it does

Given a set of evidence records and a rules preset, Evidence Gate returns:

{
  status: "available" | "quality_warning" | "fallback" | "missing",
  freshness: "fresh" | "stale" | "unknown",
  allowedActions: { summarize, compare, /* + your forbidden actions forced to false */ },
  warnings: [{ level, code, message }],
  caveats: ["...strings ready to inject into the prompt..."]
}
  • status — is there enough authoritative evidence to speak from at all?
  • allowedActions — gate generation on summarize; forbidden actions (e.g. personalized_advice, diagnose, claim_realtime) are always false.
  • caveats — drop straight into your system prompt so the model self-limits.

It is fully domain-agnostic. The same engine works for finance, healthcare, support, legal — a domain is just a preset.

Install

npm install evidence-gate
# or
pip install evidence-gate-py

The PyPI package is evidence-gate-py (the plain evidence-gate name on PyPI belongs to an unrelated project). The import name is unchanged — from evidence_gate import evidence_gate, presets.

Records

Each record is one observation/period you have evidence for:

{
  date: "2026-03-31",   // ISO date of the observation
  qualityScore: 92,     // optional 0-100
  quality: "clean",     // optional "clean" | "review"
  flags: ["RESTATED"],  // optional data-quality flags
  tier: "primary"       // optional "primary" (default) | "fallback" (cached/secondary)
}

Presets

A preset is a ruleset. Adding a vertical = copying a preset, never touching the core.

export const FINANCE = {
  primaryLabel: "financial statements",
  staleDays: 135,
  minRecords: 4,
  qualityThreshold: 70,
  forbiddenActions: ["personalized_advice", "claim_realtime"],
};

Ships with FINANCE, HEALTH, and SUPPORT examples. Override any message via rules.messages.

Decision log — an audit trail for every gate call

AI answers today come with references, but no proof: nothing shows the evidence behind an answer was complete, fresh, and authoritative when the model spoke. The gate is where that decision happens — so the gate can log it.

Opt in with decision and every call also returns a JSONL-serializable decision record: which ruleset ran, a digest of the evidence it saw (the evidence itself is not stored — it may be sensitive), and the outcome.

const gate = evidenceGate({
  records,
  rules: presets.FINANCE,
  decision: { id: "req-001", at: new Date().toISOString() },
});
appendFileSync("decisions.jsonl", JSON.stringify(gate.decision) + "\n");

Later, prove a decision was made over a given evidence set by replaying its digest: evidenceDigest({ records, supporting }) === logged.digests.evidence. Digests are FNV-1a 64 over canonical JSON — deterministic and identical across the JS and Python ports (not cryptographic; they detect drift, not adversaries). See examples/decision-log.mjs for the full flow.

Use it as an MCP server

Give an agent a fact-checker it calls before it speaks. The package ships an MCP server exposing a check_evidence tool, so any MCP-compatible agent (Claude, IDE assistants, etc.) can gate itself.

npm install evidence-gate @modelcontextprotocol/sdk   # the SDK is an optional peer

Register it with your client:

{
  "mcpServers": {
    "evidence-gate": { "command": "npx", "args": ["evidence-gate-mcp"] }
  }
}

The tool accepts { records, supporting?, preset?, rules? } and returns the gate result. Instruct your agent to call it first and refuse to answer when allowedActions.summarize is false.

Why trust it

The engine is intentionally small and pure — no network, no dependencies, all logic unit-tested. It runs in production today inside DaddyInvestor, a Thai-language financial-data application, gating an LLM over real, messy, sometimes-missing SEC filings.

License

MIT

Metadata

Release files for evidence-gate-py 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for evidence-gate-py 0.2.0
File Size Uploaded
evidence_gate_py-0.2.0.tar.gz 7.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for evidence-gate-py 0.2.0
File Interpreter ABI Platform
evidence_gate_py-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 15.0 kB

Release files / evidence_gate_py-0.2.0.tar.gz

Download URL evidence_gate_py-0.2.0.tar.gz
Size 7.5 kB
Tags Source
SHA-256 checksum
How to use checksums
2fb9e7a687a4ab41cfc7a385c89ce3d032a1d8814b08a8cf9a78eaebc1f86994
BLAKE2b-256 checksum
How to use checksums
9d0d3eb84d00f25143925ad2bb62551acaa26a4b382389b67522a06c5e00ce92
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.1

Release files / evidence_gate_py-0.2.0-py3-none-any.whl

Download URL evidence_gate_py-0.2.0-py3-none-any.whl
Size 7.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a2c81012386d9b1526834c9bb1642c61b7f99fdec5afe4e4698392e3ef3fb85e
BLAKE2b-256 checksum
How to use checksums
f6b61dc1711b047fa7b2111c5ac7336c687e02d2400482a4f3ec447a362b9c0c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.1

Release history Release notifications | RSS feed

1.0.1

2 release files

1.0.0

2 release files

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page