Evidence-gated claims, continuity anchors, and receipts for agent workflows.
Language is a proposal, not an authority. When an AI agent says "tests pass" or
"the code is thread-safe," those are claims — not facts. nlai provides the
irreducible mechanism for tracking what was claimed, checking it against
constraints, and producing content-addressed receipts that prove the decision.
from nlai import gate, Anchor
# Gate agent output — extract claims, produce receipt
result = gate("The tests definitely pass and the code is thread-safe.")
print(result.verdict) # "pass" (no anchors to violate)
print(result.claims) # [Claim("definitely", assertive), ...]
print(result.receipt.receipt_id) # "sha256:..."
# Add constraints
anchors = [
Anchor(id="no-thread-claims", description="Don't claim thread safety",
forbidden=("thread-safe", "thread safe")),
]
result = gate("The code is thread-safe.", anchors=anchors)
print(result.verdict) # "block"
print(result.violations) # [Violation("no-thread-claims", ...)]Claims start as unsupported. Attach evidence to promote them.
Contradictions between claims are detected and tracked.
from nlai import gate, Evidence, attach_evidence
# 1. Gate extracts unsupported claims (sentence-level text)
result = gate("The system definitely passes all tests.")
claim = result.claims[0]
print(claim.text) # "The system definitely passes all tests"
print(claim.status) # "unsupported"
# 2. Attach evidence — promotes to "supported"
evidence = Evidence(kind="test_result", reference="pytest exit 0")
claim = attach_evidence(claim, evidence)
print(claim.status) # "supported"
# 3. Later, gate new text against the prior supported claim
result2 = gate(
"The system definitely fails all tests.",
prior_claims=[claim],
)
contested = result2.contested_claims
print(contested[0].status) # "contested"
print(contested[0].conflicts_with) # ("The system definitely passes all tests",)
# verdict is still "pass" — contradictions don't block, they contest
print(result2.verdict) # "pass"| Status | Meaning |
|---|---|
unsupported |
No evidence attached. Default state for extracted claims. |
supported |
Evidence record(s) attached. Not independently validated — the kernel records, it doesn't verify. |
contested |
Conflicting claims detected. Sticky — only humans resolve. Evidence doesn't un-contest. |
Status transitions:
unsupported+ evidence →supportedsupported+ conflict →contestedunsupported+ conflict →contestedcontested+ evidence →contested(sticky)
The kernel that Agent Governor builds on. Same law, smaller jurisdiction.
- Claims require evidence
- Decisions produce receipts
- Anchors enforce continuity
- Contradictions are tracked, not resolved
- Violations resolve deterministically
A regex hook can block dangerous strings. But the moment someone asks:
- What exactly was checked? The receipt records the subject hash.
- What policy was violated? The violation names the anchor, with evidence.
- Can I verify the result later?
verify_receipt()works offline, anytime. - Can I trust the checker? The gate is deterministic — same inputs, same receipt_id.
A regex detects patterns. nlai attests decisions. That's the difference.
# Regex: "was it blocked?"
blocked = bool(re.search(r"rm -rf", agent_output))
# nlai: "what happened, provably?"
result = gate(agent_output, anchors=my_policy)
# result.verdict, result.receipt, result.violations, result.claims
# — all content-addressed, all verifiable, all auditable- No daemon, no socket, no RPC
- No adaptive policy, no orchestration
- No external dependencies (stdlib only)
- No "lite mode" weaker enforcement
pip install nlaiRequires Python 3.10+. Zero dependencies.
# The gate function
gate(text, *, anchors=None, prior_claims=None) -> GateResult
# Data types
GateResult(verdict, receipt, claims, violations)
Receipt(receipt_id, schema_version, timestamp, gate, verdict, subject_hash, evidence_hash)
Anchor(id, description, required, forbidden, severity, constraint_class)
Claim(text, strength, status, span, evidence, conflicts_with) # text = surrounding sentence
Violation(anchor_id, severity, description, evidence)
Evidence(kind, reference, source)
# Evidence operations
attach_evidence(claim, evidence) -> Claim # Promote UNSUPPORTED → SUPPORTED
contest_claim(claim, conflicting_text) -> Claim # Mark as CONTESTED
find_contradictions(claims, prior_claims) -> list[Claim] # Opposing-pair detection
# Utilities
canonical_json(obj) -> bytes
content_hash(data: bytes) -> str
verify_receipt(receipt) -> bool
extract_claims(text) -> list[Claim]
assertiveness_score(text) -> float| Verdict | Meaning |
|---|---|
pass |
No violations |
warn |
Violations found, but only at warn severity |
block |
Violations at correct or reject severity |
observe |
Informational only (used by infrastructure) |
Every gate() call produces a content-addressed receipt:
receipt_id = H(schema_version + gate + subject_hash + evidence_hash)
Same inputs = same receipt_id. Timestamp is metadata, not identity.
Receipts can be verified offline with verify_receipt().
nlai (kernel)
^
agent_gov (runtime + policy + orchestration)
^
plugins / clerk / phosphor (distribution surfaces)
nlai is the foundation. Agent Governor adds regime detection, lane routing,
multi-agent coordination, and everything else needed for production governance.
Apache-2.0