Skip to main content

anchor-guard

Claim-level groundedness scoring for RAG-generated answers.

anchor-guard closes the blind spot that anchor-eval leaves open: a retrieval pipeline can score 95% on span recall and still produce hallucinated answers. anchor-guard decomposes each generated answer into atomic claims, attributes every claim to the exact character range in the source document that supports it, and blocks CI deploys when groundedness regresses — entirely on-prem, with no data egress.


The problem anchor-guard solves

anchor-eval proves that your retriever found the right spans. It does not prove that the LLM built a grounded answer from them.

Consider this scenario:

  1. The retriever correctly surfaces clause §4.2(b) from contract.pdf — anchor-eval scores a hit.
  2. The LLM ignores that clause and asserts the indemnification cap is $500K when the clause says $1M.
  3. anchor-eval scores: pass. The answer is wrong.

This failure is not hypothetical. It is the default mode of every RAG pipeline that evaluates retrieval but not generation. For a legal, healthcare, or financial services deployment, a confident wrong answer is worse than no answer.

anchor-guard catches it by asking a different question: is every claim in this answer actually entailed by the source span it was supposedly drawn from?


How it works

  Your RAG pipeline
  ─────────────────────────────────────────────────────────
  User query ──► Retriever ──► Context spans ──► LLM ──► Answer
                    │                                       │
                    │ (spans + answer go to anchor-guard)   │
                    └───────────────────────────────────────┘
                                      │
                              anchor guard check
                                      │
                    ┌─────────────────▼──────────────────────┐
                    │  1. Decompose answer into atomic claims  │
                    │  2. Attribute each claim to a source span│
                    │  3. Score NLI entailment per claim       │
                    │  4. Check abstention correctness         │
                    │  5. Detect PII / restricted content      │
                    │  6. Generate claim-level citations       │
                    │  7. Gate CI on regression vs. baseline   │
                    └────────────────────────────────────────-┘
                                      │
                              GuardReport (JSON)
                                      │
                    ┌─────────────────┼─────────────────┐
                    │                 │                  │
             anchor-review      anchor-ledger      CI exit code
           (SME HTML bundle)  (audit evidence)    (0 / 1 / 2)

anchor-guard runs entirely out of the production request path. It consumes answers after the fact — from files, OTel traces, or test fixtures. It cannot cause an outage and never adds to production latency.


Quickstart

pip install anchor-guard
# or: uv add anchor-guard

# Run a groundedness check on a set of answers
anchor guard check answers.json --corpus ./docs

# Save a groundedness baseline for CI regression gating
anchor guard baseline answers.json --output guard_baseline.json

# Regression gate: exits 1 if groundedness drops > 2%
anchor guard check answers.json --corpus ./docs \
  --baseline guard_baseline.json

# Generate an HTML review bundle for an SME
anchor guard review guard_report.json --output review.html

answers.json format

anchor-guard expects a JSON array of answer objects. The minimal shape:

[
  {
    "answer_id": "ans_001",
    "question_id": "q_001",
    "raw_answer": "The indemnification cap is $1M per the contract.",
    "retrieved_spans": [
      {
        "doc_id": "contract.pdf",
        "char_start": 4210,
        "char_end": 4580,
        "text": "The aggregate liability of either party shall not exceed one million dollars ($1,000,000)..."
      }
    ]
  }
]

When anchor-eval's QuestionSet is provided via --question-set, each answer is additionally checked against its expected_span — the character range the correct answer should be drawn from. This is the stronger, two-layer check described in Dependency on anchor-eval.


Commands

Command Description
anchor guard check Run the full pipeline: decompose → attribute → disclose → cite → gate.
anchor guard baseline Save current metrics as the regression baseline for a (prompt_version, model_version) pair.
anchor guard review Generate a self-contained HTML bundle for SME claim attribution review.

anchor guard check

anchor guard check <answers.json> [options]

Options:
  --question-set, -q  PATH   anchor-eval QuestionSet JSON (enables IOU gating against expected_span)
  --corpus,       -C  PATH   Source document directory (required for span text lookup)
  --config,       -c  PATH   GuardConfig JSON (thresholds, NLI model, features)
  --output,       -o  PATH   Write GuardReport JSON to this path
  --review-bundle,-r  PATH   Also write an anchor-review HTML bundle
  --baseline,     -b  PATH   Compare against this baseline; exits 1 on regression

Exit codes follow the same convention as anchor ci:

Exit Meaning
0 All checks passed, no regression
1 Groundedness or abstention regressed beyond tolerance
2 Corpus drift or configuration mismatch

anchor guard baseline

anchor guard baseline <answers.json> [options]

Options:
  --output, -o  PATH   Baseline file path (default: guard_baseline.json)
  --config, -c  PATH   GuardConfig JSON

Saves groundedness_rate, abstention_pass_rate, and ungrounded_claim_rate keyed to the (prompt_version, model_version) pair in the config. All three metrics participate in regression gating — a rise in ungrounded_claim_rate beyond tolerance triggers exit 1 the same as a drop in groundedness. When the version pair changes — which happens often in on-prem deployments where teams swap local models for GPU cost reasons — and no baseline exists for the new pair, a warning is emitted rather than an error.

anchor guard review

anchor guard review <guard_report.json> [options]

Options:
  --output, -o  PATH   HTML bundle path (default: guard_review.html)

Generates the anchor-review bundle. See SME calibration for the full workflow.


The five checks

1. Claim decomposition

The answer is split into atomic, independently verifiable claims. Each claim must be a complete declarative sentence that can be checked against a single source span without requiring context from other claims.

Primary: LLM-backed decomposition via any OpenAI-compatible /v1/chat/completions endpoint — local or external, whichever is configured for the environment.
Fallback: Sentence-boundary splitting when no LLM endpoint is configured (lower confidence, flagged in the report).

Answer: "The termination notice period is 30 days. Either party may terminate for 
         convenience. Liquidated damages apply only to Section 12 breaches."

Claims:
  [0] "The termination notice period is 30 days."
  [1] "Either party may terminate for convenience."
  [2] "Liquidated damages apply only to Section 12 breaches."

2. Span-level attribution

Each claim is attributed to the retrieved span that best supports it. Attribution uses a two-stage pipeline:

Stage 1 — NLI entailment: a small local model scores whether the span text entails the claim. This is a narrow task (span-level entailment, not open-domain NLI) that small models handle well — no frontier judge required.

Stage 2 — IOU gate (when anchor-eval QuestionSet is provided): the winning span is compared against the question's expected_span using intersection-over-union. A claim is only classified as GROUNDED when both NLI confidence and IOU meet their thresholds.

Claim:  "The termination notice period is 30 days."
Span:   contract.pdf §4210–4580  (NLI confidence: 0.92, IOU vs expected_span: 0.71)
Status: GROUNDED ✓

Claim:  "Liquidated damages apply only to Section 12 breaches."
Span:   contract.pdf §7100–7350  (NLI confidence: 0.41)
Status: UNGROUNDED ✗  ← LLM hallucinated; span does not entail this claim
Status Meaning
GROUNDED NLI confidence ≥ threshold and (IOU ≥ threshold or no expected_span)
UNGROUNDED No candidate span achieves NLI confidence ≥ threshold
ABSTAINED System correctly declined to answer a question with no corpus answer
PENDING_SME Attribution awaits SME review via anchor-review

Default thresholds (configurable in GuardConfig):

Parameter Default
iou_threshold 0.5
nli_confidence_threshold 0.7

3. Abstention correctness

For questions where no corpus answer exists (expected_span: null in the QuestionSet, corresponding to anchor-eval's negative_existence and implicit_negative archetypes), anchor-guard verifies the system responds with a recognizable abstention rather than fabricating an answer.

Two-sided check:

  • Should abstain, didn't: system hallucinated where it should have said "not in corpus." Flagged as high-severity.
  • Should answer, abstained: system incorrectly declined a question it should have answered.

abstention_pass_rate is a top-level metric in GuardReport and participates in regression gating. When enable_abstention_check is false, it is omitted (null) from the report and skipped in the regression gate — a disabled check never triggers a spurious regression.

4. Disclosure detection

Scans generated answer text for PII and restricted content. Runs entirely locally — no external API calls, no data egress.

Finding type Severity Pattern
pii_email High Email addresses
pii_phone High US phone numbers
pii_ssn Critical Social Security Numbers
pii_credit_card Critical Credit card numbers
restricted_term Medium Terms from the active guard pack

Disclosure findings are reported independently from groundedness — a clean answer can still contain PII, and a hallucinated answer may not. They are separate quality dimensions.

5. Citation generation

For every GROUNDED claim, anchor-guard emits a claim-level citation:

{
  "claim_id": "c_001",
  "claim_text": "The termination notice period is 30 days.",
  "doc_id": "contract.pdf",
  "char_start": 4210,
  "char_end": 4580,
  "nli_confidence": 0.92
}

Inline format: [contract.pdf §4210–4580]

Document-level citations ("Source: contract.pdf") are insufficient for legal and regulated use — the precise clause is required. Claim-level citations enable auditors to trace each assertion to the exact character range.


LLM backend configuration

Recommendation: use a model running inside your private network. NLI scoring and claim decomposition send retrieved span text and generated answer text to the configured endpoint. For legal, healthcare, and financial deployments that data is almost certainly regulated. A local model keeps it inside your infrastructure with no additional controls required. External providers are supported but require an explicit opt-in — see Data residency and the allow_external_calls flag below.

anchor-guard sends NLI scoring and claim decomposition prompts to a /v1/chat/completions endpoint. Which endpoint that is — and whether it sits inside your private network or reaches an external service — is entirely your decision.

# Any OpenAI-compatible server on the private network
# (vLLM, llama.cpp server, LM Studio, LocalAI, Ollama, HF TGI, …)
anchor guard check answers.json --corpus ./docs

# Custom endpoint and model
anchor guard check answers.json --corpus ./docs \
  --config guard_config.json

guard_config.json:

{
  "nli_provider": {
    "model": "llama3.2:3b",
    "base_url": "http://gpu-host:8000",
    "timeout_seconds": 60,
    "api_key": null
  },
  "iou_threshold": 0.5,
  "nli_confidence_threshold": 0.7,
  "enable_disclosure_check": true,
  "enable_abstention_check": true,
  "enable_citation_generation": true
}

base_url is the scheme + host + port of the server. anchor-guard always POSTs to {base_url}/v1/chat/completions. Any server that exposes this path works without additional configuration.

Credential resolution

api_key in the config file is optional. anchor-guard reads credentials from environment variables at runtime — no library files to edit, no secrets in version control:

Env var Used for
ANCHOR_NLI_API_KEY NLI scoring endpoint (nli_provider)
ANCHOR_DECOMPOSE_API_KEY Claim decomposition endpoint (decompose_provider); falls back to ANCHOR_NLI_API_KEY if unset
export ANCHOR_NLI_API_KEY=sk-...
anchor guard check answers.json --config guard_config.json

Separate decomposition and scoring models

By default, both claim decomposition and NLI scoring use nli_provider. To use a larger model for decomposition (higher fidelity) and a faster model for NLI (lower latency), add a separate decompose_provider:

{
  "decompose_provider": {
    "model": "llama3.1:70b",
    "base_url": "http://big-gpu:8000",
    "timeout_seconds": 120
  },
  "nli_provider": {
    "model": "llama3.2:3b",
    "base_url": "http://fast-gpu:8000",
    "timeout_seconds": 30
  }
}

When decompose_provider is absent, nli_provider is used for both stages.

Built-in provider wrappers

For external services, anchor-guard ships named wrappers that pre-configure the right endpoint and read API keys from standard environment variables:

Provider NLI scorer Claim splitter Env var
OpenAI OpenAINLIScorer OpenAIClaimSplitter OPENAI_API_KEY
Anthropic AnthropicNLIScorer AnthropicClaimSplitter ANTHROPIC_API_KEY
Azure OpenAI AzureOpenAINLIScorer AzureOpenAIClaimSplitter AZURE_OPENAI_API_KEY
Mistral AI MistralNLIScorer MistralClaimSplitter MISTRAL_API_KEY
Groq GroqNLIScorer GroqClaimSplitter GROQ_API_KEY
Together AI TogetherNLIScorer TogetherClaimSplitter TOGETHER_API_KEY

Import from anchor_guard.attribute.providers (scorers) and anchor_guard.decompose.providers (splitters).

Azure OpenAI via config file: set base_url to the resource base URL and model to the deployment name:

{
  "nli_provider": {
    "model": "my-gpt4o-deployment",
    "base_url": "https://mycompany-oai.openai.azure.com",
    "api_key": null
  },
  "allow_external_calls": true
}

The factory extracts the resource name from the hostname and routes to AzureOpenAINLIScorer / AzureOpenAIClaimSplitter automatically. AZURE_OPENAI_API_KEY is read from the environment when api_key is null.

Custom backends

For any other service — gRPC, a proprietary REST API, an in-process Python model — subclass the abstract base and implement one method:

from anchor_guard.attribute.nli_scorer import NLIScorer

class MyNLIScorer(NLIScorer):
    def score(self, premise: str, hypothesis: str) -> float:
        return my_internal_service.entailment_confidence(premise, hypothesis)

The same pattern applies to ClaimSplitter in anchor_guard.decompose.claim_splitter.

Data residency and the allow_external_calls flag

External provider wrappers are blocked by default. Calling one without opting in raises ExternalCallBlockedError immediately, before any network request is made. The flag is checked on every call, not once at construction time.

There are two usage paths, each with its own opt-in point:

Via the pipeline (CLI / GuardConfig)

Set allow_external_calls=True in GuardConfig. The pipeline factory (build_nli_scorer / build_claim_splitter in anchor_guard.pipeline) inspects base_url, detects known external provider hosts, routes to the appropriate named provider class, and passes config.allow_external_calls through. Every subsequent score() and split() call re-checks the flag — there is no way to call an external provider through the pipeline without it being True.

{
  "nli_provider": {
    "model": "gpt-4o-mini",
    "base_url": "https://api.openai.com",
    "api_key": null
  },
  "allow_external_calls": true
}

Via the Python API (direct construction)

When constructing a provider class directly — outside the pipeline — pass allow_external_calls=True to the constructor:

from anchor_guard.attribute.providers import OpenAINLIScorer
from anchor_guard.decompose.providers import OpenAIClaimSplitter

scorer = OpenAINLIScorer(allow_external_calls=True)   # reads OPENAI_API_KEY from env
splitter = OpenAIClaimSplitter(allow_external_calls=True)

For OpenAI-compatible local/private endpoints (the default path), use ANCHOR_NLI_API_KEY instead of the provider-specific env vars above.

CI / zero-dependency fallback

For CI environments without a running LLM endpoint, set "model": "sentence-boundary-fallback" to use the deterministic sentence-splitting fallback. Attribution quality is lower but the pipeline runs with zero dependencies.

In this mode the NLI scorer is replaced with a fixture that returns full confidence (1.0) for every claim, so the pipeline completes without a false regression exit. This mode is for smoke-testing pipeline wiring only — groundedness scores produced in fallback mode are not meaningful and must not be committed as a baseline.


Dependency on anchor-eval

anchor-guard has two operating modes depending on whether anchor-eval's QuestionSet is provided.

Standalone mode

anchor-guard runs independently. You provide answers and the retrieved spans from your own pipeline. No anchor-eval installation required.

anchor guard check answers.json --corpus ./docs

What you get:

  • NLI-based claim attribution against your provided retrieved spans
  • Abstention correctness (if your answer objects include retrieval_required)
  • Disclosure detection
  • Claim-level citations for grounded claims
  • Regression gating against a saved baseline

What you don't get:

  • IOU-gated attribution against a ground-truth expected span
  • Per-archetype groundedness breakdown
  • Correlation between retrieval quality and generation quality

Paired mode (recommended)

When anchor-eval's QuestionSet is available, each answer is additionally checked against its expected_span. This is the two-layer assurance claim:

"The retriever found the right span (anchor-eval), AND the LLM built its answer from that span (anchor-guard), AND the answer is grounded in the retrieved text (NLI) AND attributable to the ground-truth location (IOU)."

# Step 1: Generate and commit a QuestionSet with anchor-eval
anchor generate --corpus ./contracts --domain legal --output question_set.json

# Step 2: Run your RAG pipeline, collect answers (your code)
python run_rag.py --questions question_set.json --output answers.json

# Step 3: Score retrieval with anchor-eval
anchor ci --question-set question_set.json --corpus ./contracts \
  --baseline anchor_baseline.json

# Step 4: Score generation with anchor-guard
anchor guard check answers.json --corpus ./contracts \
  --question-set question_set.json \
  --baseline guard_baseline.json

The two baselines are independent. A retrieval regression exits from anchor ci; a groundedness regression exits from anchor guard check. Both gates run in the same CI pipeline.

Shared identity key

Both products use (doc_id, char_start, char_end) in Unicode codepoints as the durable span identity. This key survives re-chunking, re-embedding, and model swaps — the same property that makes anchor-eval benchmarks stable across pipeline changes applies equally to anchor-guard's attribution records.


SME calibration — anchor-review

The local NLI model is a judge, and judges make mistakes. anchor-guard's calibration track lets a domain expert (lawyer, clinician, compliance officer) review and correct individual claim attributions without touching the command line.

Workflow

anchor guard check answers.json \
  --question-set question_set.json \
  --review-bundle guard_review.html
      │
      ▼
  guard_review.html  ◄── open in any browser, no server required
      │
  SME clicks through each claim attribution:
    [accept]  — span correctly entails this claim
    [reject]  — span does not support this claim
    [abstain] — SME cannot determine
    + free-text comment
      │
  Export  calibration.json  (ed25519-signed)
      │
anchor guard check answers.json \
  --calibration calibration.json \
  --baseline guard_baseline.json
      │
  PENDING_SME claims resolved → final groundedness_rate updated

Design properties

  • Zero dependencies. The HTML bundle has all CSS and JS inlined. Opens in Chrome, Firefox, Safari, or Edge. Works in fully air-gapped environments.
  • Signed export. The calibration.json is signed with the reviewer's ed25519 key. anchor-guard verifies the signature before ingesting it.
  • Tamper-evident. The signature covers the canonical JSON of all calibration records. Any post-export modification fails verification.
  • Auditable. Every calibration ingestion is logged to anchor-ledger (when installed) with reviewer identity, timestamp, and verdict.

CI/CD integration

anchor-guard fits into the same CI pipeline as anchor-eval without additional infrastructure.

GitHub Actions example

- name: Score retrieval (anchor-eval)
  run: |
    anchor ci \
      --question-set question_set.json \
      --corpus ./contracts \
      --baseline anchor_baseline.json
  # exits 1 on retrieval regression, blocks deploy

- name: Score generation (anchor-guard)
  run: |
    anchor guard check answers.json \
      --corpus ./contracts \
      --question-set question_set.json \
      --baseline guard_baseline.json
  # exits 1 on groundedness regression, blocks deploy

Updating baselines

When you intentionally improve the pipeline (new model, better chunking, tuned prompt), update both baselines:

anchor ci --question-set question_set.json --corpus . --save-baseline anchor_baseline.json
anchor guard baseline answers.json --output guard_baseline.json

Commit both files. The baselines are version-controlled alongside the corpus and the question set — they define what "acceptable" means for this version of the pipeline.


The Anchor suite

anchor-guard is the second module in the six-module Anchor assurance suite. All modules are designed for fully on-prem, air-gapped deployment — no customer data transits a vendor API.

Module Purpose Phase
anchor-eval Span-anchored retrieval evaluation, archetype diagnosis, CI gating Shipped (v0.3.1)
anchor-guard Claim-level groundedness, abstention, citation, disclosure Phase 1 (this repo)
anchor-ledger OTel ingestion, append-only evidence store, compliance export Phase 1.5
anchor-mirror Production query drift, PII-redacted intent distillation Phase 2
anchor-shield Corpus security: injection detection, poisoning, ACL integrity Phase 2
anchor-review / anchor-studio SME calibration UI (static bundle → local web workspace) Phase 1 → 3

How they connect

  anchor-eval           anchor-guard          anchor-ledger
  ───────────           ────────────          ─────────────
  QuestionSet ────────► expected_span         OTel traces ──► local OTLP
  (expected_span)       IOU gate                               endpoint
                             │
                        GuardReport ─────────────────────────► evidence store
                             │
                        guard_review.html ──► SME ──► calibration.json
                                                           │
                                                      anchor-guard
                                                      (ingested back)

Every artefact exchange is local — files, a localhost OTLP endpoint, or a local web server. No external service dependencies at any integration point.

Governing rule

No component of the Anchor suite sits in the live production request path.

anchor-guard runs out-of-band against answer files or sampled OTel traces. The one exception — a local proxy sidecar for dev/staging/CI — is explicitly scoped to non-production environments. It is never permitted in production.


Key concepts

Term Definition
AtomicClaim A single, independently verifiable assertion extracted from an answer. The unit of attribution.
ClaimSet All atomic claims extracted from one answer.
SpanRef (doc_id, char_start, char_end) in Unicode codepoints. The shared identity key across anchor-eval and anchor-guard.
NLI confidence Entailment probability that a source span text logically supports a claim. Scored by a local model.
IOU threshold Minimum intersection-over-union between the winning span and the ground-truth expected_span for a claim to be classified as GROUNDED. Only active when a QuestionSet is provided.
groundedness_rate Fraction of claims classified as GROUNDED in a run. Top-level GuardReport metric.
abstention_pass_rate Fraction of abstention-required questions where the system correctly declined to answer.
GuardReport The complete output of an anchor-guard run: attributions, disclosure findings, regression findings, citations.
CalibrationExport Signed JSON produced by an SME in anchor-review containing accept/reject verdicts per claim.
guard pack JSON bundle of abstention signal phrases and restricted terms. guard-base-v0 ships with the package.

Packs

Guard packs configure abstention detection and restricted-term scanning. The active pack is resolved from the --corpus domain or set explicitly.

Pack Domain Ships with
guard-base-v0 General anchor-guard (default)

Custom packs:

{
  "pack_id": "guard-legal-v0",
  "version": "0.1.0",
  "abstention_signals": [
    "not addressed in the agreement",
    "the contract is silent on",
    "outside the scope of this document"
  ],
  "restricted_terms": ["PRIVILEGED", "CONFIDENTIAL", "ATTORNEY-CLIENT"]
}

Python API

anchor-guard can be used as a library inside evaluation scripts and notebooks.

from anchor_guard.decompose.claim_splitter import SentenceBoundaryFallback, OpenAICompatibleClaimSplitter
from anchor_guard.attribute.nli_scorer import OpenAICompatibleNLIScorer
from anchor_guard.attribute.span_matcher import SpanMatcher
from anchor_guard.citation.generator import CitationGenerator
from anchor_guard.disclosure.detector import DisclosureDetector
from anchor_guard.models.span import SpanRef

# Decompose
splitter = SentenceBoundaryFallback()
claim_set = splitter.split(
    answer_id="ans_001",
    question_id="q_001",
    raw_answer="The indemnification cap is $1M. Notice must be given 30 days in advance.",
)

# Attribute — point base_url at any OpenAI-compatible server in the private network
nli_scorer = OpenAICompatibleNLIScorer(base_url="http://localhost:11434", model="mistral:7b")
candidate_spans = [
    (SpanRef(doc_id="contract.pdf", char_start=4210, char_end=4580), "...shall not exceed one million dollars..."),
]
matcher = SpanMatcher(nli_scorer=nli_scorer, candidate_spans=candidate_spans)
result = matcher.attribute(claim_set, expected_span=SpanRef(doc_id="contract.pdf", char_start=4210, char_end=4580))

print(f"Groundedness rate: {result.groundedness_rate:.0%}")
# Groundedness rate: 100%

# Cite
citations = CitationGenerator().generate(result)
for c in citations:
    print(c.to_inline())
# [contract.pdf §4210–4580]

# Disclose
findings = DisclosureDetector().detect("ans_001", "The cap is $1M.")
# findings == []  (no PII in this answer)

Air-gapped deployment

anchor-guard is designed for fully disconnected environments. By default, no component makes outbound network calls. External providers (OpenAI, Anthropic, Azure, etc.) are available as opt-in wrappers — egress happens only when you explicitly configure one.

Requirement How it's met
No egress (default) Default config points to a local /v1/chat/completions endpoint. No outbound calls unless an external provider is configured.
Offline license ed25519-signed token at ~/.config/anchor/license.token. Verified locally.
Offline packs Guard packs are versioned signed archives distributed via sneakernet or internal artifact registry.
Reproducible runs A prior anchor guard check run is exactly reproducible on the same pack versions months later — an audit requirement.

License

The guard:claims entitlement is required for anchor guard check and anchor guard review. anchor guard baseline is always unlicensed — baselines must be writable in CI environments before a license is provisioned.

# Install license (air-gapped: copy token file manually)
anchor license install --token <path-to-token>

# Verify guard entitlement
anchor license verify
# guard:claims ✓

Content capture and OTel

anchor-guard can consume answers directly from OpenTelemetry GenAI traces when anchor-ledger is installed and an OTLP endpoint is configured.

Production OTel collectors frequently omit message content (gen_ai.prompt, gen_ai.completion) for privacy reasons. anchor-guard handles this gracefully:

Mode What's available Capability
Full content (dev/staging/CI) Spans + answer text + retrieved text All five checks
Metadata-only (production) Spans + latency + token counts Trajectory and abstention checks only
Sampled (production with content) Full fidelity on a configured sample rate All five checks on sampled traffic

The GuardReport records which mode was active. This constraint is a scoping item to raise during customer onboarding — discovering it mid-POC reads as a product defect.


Roadmap

v0.1.0 (current)

  • Folder structure, data models, and module stubs
  • DisclosureDetector — PII and restricted-term scanning (fully implemented)
  • SpanRef — shared identity model compatible with anchor-eval
  • RegressionGate — baseline comparison logic
  • SentenceBoundaryFallback — zero-dependency claim splitter for CI smoke tests
  • anchor-review HTML bundle generator stub

v0.2.0 (planned)

Attribution pipeline

  • SpanMatcher.attribute() — two-stage attribution (NLI confidence + IOU gate)
  • AbstentionChecker.check() — two-sided abstention correctness against guard pack signal phrases

Calibration loop

  • ReviewBundleGenerator.generate() — complete anchor-review static HTML bundle
  • CalibrationIngester — ed25519 signature verification + GROUNDED/UNGROUNDED verdict application from CalibrationExport

CLI (all commands fully implemented)

  • anchor guard check — full pipeline: decompose → attribute → disclose → cite → gate; includes --calibration (ingest SME verdicts) flag
  • anchor guard baseline — save groundedness metrics as regression baseline with version-mismatch warning
  • anchor guard review — generate anchor-review HTML bundle from a saved GuardReport

Infrastructure

  • LicenseGate.check() — offline ed25519 guard:claims entitlement verification
  • GuardReportRenderer.render_console() — Rich terminal summary with severity-grouped disclosure counts and regression highlighting
  • schema_version: "1" in GuardReport, ClaimSet, and CalibrationExport output files
  • content_mode: "full" | "metadata_only" in GuardReport
  • MAX_CLAIMS_PER_ANSWER enforcement with ClaimSet.truncated flag

Already implemented in v0.1.0 (ships with v0.2.0)

  • OpenAICompatibleClaimSplitter, OpenAICompatibleNLIScorer
  • Built-in provider wrappers: OpenAI, Anthropic, Azure OpenAI, Mistral, Groq, Together AI
  • CitationGenerator

v0.3.0 (current)

  • Custom guard pack authoring — GuardPack model, GuardPackLoader, anchor guard pack validate/new
  • content_mode: "full" | "metadata_only" in GuardConfig — skips NLI pipeline in metadata-only mode
  • --corpus flag on anchor guard check and anchor guard baseline — reads span text directly from source document files when not embedded in answers.json
  • span_text stored on ClaimAttribution at attribution time — anchor guard review now shows full span context without needing the original answers.json

v0.4.0 (planned — blocked on external modules)

The following items are explicitly blocked on modules that do not exist yet in the Anchor suite. They cannot be implemented inside anchor-guard alone.

Item Blocked on Phase
OTel trace ingestion → GuardReport evidence records anchor-ledger (Phase 1.5) 1.5
Sampled production monitoring with configurable sample rate anchor-ledger (Phase 1.5) 1.5
SME review queues and judge-drift dashboards anchor-studio (Phase 3) 3

Once anchor-ledger exists, anchor-guard will add:

  • anchor guard check --from-traces <otlp_export.json> — consume GenAI OTel spans as input instead of answers.json
  • GuardReportExporter — write GuardReport events as OTLP-compatible JSON for anchor-ledger ingestion
  • Sampled-mode evidence records: full fidelity on a configured sample rate, metadata-only on the remainder

Once anchor-studio exists, the static anchor guard review HTML bundle will be promoted into an SME review queue with multi-reviewer support, verdict history, and judge-drift dashboards.


License

anchor-guard is licensed under the Business Source License 1.1. anchor guard baseline always runs without a license. anchor guard check and anchor guard review require a guard:claims entitlement.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

anchor_guard-0.3.0.tar.gz (62.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

anchor_guard-0.3.0-py3-none-any.whl (70.6 kB view details)

Uploaded Python 3

File details

Details for the file anchor_guard-0.3.0.tar.gz.

File metadata

  • Download URL: anchor_guard-0.3.0.tar.gz
  • Upload date:
  • Size: 62.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for anchor_guard-0.3.0.tar.gz
Algorithm Hash digest
SHA256 7abe0a03df2304d493148f2aa05be42c38cb01c344f892077d63545e494b54df
MD5 07c80c6f160120ed1d0586fb27a66598
BLAKE2b-256 12ec6be12efd3aaa77d33ffa45cacaa8c5c036d44569512ebf67ea5b735e009c

See more details on using hashes here.

File details

Details for the file anchor_guard-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: anchor_guard-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 70.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for anchor_guard-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d547ff869a3c60e4fbf33b557b228b23417bcdf90ec14a21d2508d91e9033d46
MD5 8cc2ccc39d04a8fa4011ee463371b441
BLAKE2b-256 cfd00116350e73ebd916b3fcf80eace79711fc0e6d9cc43078c3c25005e23866

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 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