Skip to main content

sitewitness

An agent over your site that shows its work.

Point it at a folder of texts (HTML or Markdown) and JSON data files, and you get a question-answering API with a trust protocol enforced in code, an evaluation runner, and a static page that shows every answer's trace. First instance: bsandova.com/ask.

pip install sitewitness            # add [embed] for local embeddings (sentence-transformers)
sitewitness index                  # texts → passages + BM25 (+ embeddings), data files → schemas
sitewitness serve --port 8000      # POST /ask {question} · GET /health
sitewitness ask "How many …?"      # one question from the terminal, trace on stderr
sitewitness eval golden.json --api http://localhost:8000
sitewitness page ask/ --api https://api.example.com --example "How many …?"

The protocol

Five rules, each a check in protocol.py, each a flag in the trace. The first violation replaces the answer with a refusal and names itself in trace.enforced.

rule what it catches
require_tool_use an answer produced without calling any tool
numbers_need_tool a digit in the answer with no read_data or search result in the conversation
forbid_code fenced code, def/import, or HTML in the answer
quotes_need_verification a quotation of 40+ characters without a quote call that came back found
sources_must_exist a Sources: line naming a file or page the site does not have

Plus caps: tool calls, output tokens, wall time; a budget per UTC day; a rate per address per hour. Rules are switched only in sitewitness.toml, never by a prompt.

Tools the model gets

list_sources · describe_source (schema of a JSON file) · read_data (dotted path, find filter, clipped) · search (BM25, plus embeddings with reciprocal rank fusion when present) · quote (verbatim check through quotecheck's fold).

Config

[site]
name = "example.com"
base_url = "https://example.com"
texts = ["texts/**/*.html"]
[site.data]
"surf/data.json" = "Surf forecast verification: skill by lead, quality counts."

[model]
name = "claude-sonnet-5"
max_output_tokens = 700
price_in_per_m = 3.0      # configured list prices; the trace says so
price_out_per_m = 15.0

[limits]
max_tool_calls = 8
daily_budget_usd = 4.0
per_ip_per_hour = 12
store = "sqlite:.sitewitness/limits.db"

[server]
allowed_origins = ["https://example.com"]
eval_key_env = "SITEWITNESS_EVAL_KEY"   # X-Eval-Key bypasses the per-address limit, never the budget

ANTHROPIC_API_KEY in the environment. Every trace carries: model requested and used, turns, tools with inputs and sizes, tokens, cost from the configured prices, the protocol flags, what was enforced, and today's budget.

Evaluation

golden.json: {"questions": [{"q": "…", "kind": "number|text|quote|decline", "expect": "…"}]}. sitewitness eval scores each question (substring match, or a refusal when expect is DECLINE), counts protocol violations from the traces, writes eval.json and appends to eval-history.json, and exits 1 when misses exceed --allowed-misses, so it can gate a deploy.

No framework, no network in the 44 tests. Apache-2.0.

Metadata

Release files for sitewitness 0.1.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 sitewitness 0.1.0
File Size Uploaded
sitewitness-0.1.0.tar.gz 159.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sitewitness 0.1.0
File Interpreter ABI Platform
sitewitness-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 190.3 kB

Release files / sitewitness-0.1.0.tar.gz

Download URL sitewitness-0.1.0.tar.gz
Size 159.8 kB
Tags Source
SHA-256 checksum
How to use checksums
b1f1119664b97019c5ae5215eea72ad567bb089563a8611527c9cdd76feb3f5d
BLAKE2b-256 checksum
How to use checksums
e0d5e57ca8dd920a72033814e8865bd1a62120cefd53b2b5b761e41920c81c7a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.

Transparency log

Release files / sitewitness-0.1.0-py3-none-any.whl

Download URL sitewitness-0.1.0-py3-none-any.whl
Size 30.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
06fc87e65d49d8c33150fa50aa082be103f7fdf64edeeb8b0ed2e81d5c973e4b
BLAKE2b-256 checksum
How to use checksums
b68f1754f2185cfdf5f89d5ba86a2857db50c18c219a845ceebf91a9cb57df51
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

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