Skip to content

Earlier posts.

Five posts written between March and May 2026 for ScopeBlind’s earlier products, kept for the record. Each is as it was written, with its dashes rewritten, and a note above it says what else changed: a fact corrected, a sentence we could not stand behind removed, or a link to a page that has gone left as words. The other posts of that time are not kept. For what ScopeBlind does now, see the blog and the changelog.

Open source shows what could run. Receipts prove what did run.

· Tom Farley

Archived from May 2026. Versions and links may be out of date. Corrected since: the record format is described in an IETF Internet-Draft, an individual submission, not a standard in progress. Removed: a sentence about another project’s design, a pointer to a browser check that does not read these receipts, and links to retired pages.

When xAI published the For You feed algorithm to xai-org/x-algorithm on 15 May 2026, the headline was transparency. The release answers a real question: what code is candidate to run when X ranks your timeline?

It doesn't answer the next one: was this code, in this version, with these model artifacts and this config, what ran when your feed was ranked at 09:24 this morning?

That's not a complaint. Publishing the code is genuinely useful. But "the code is open" and "this output came from that code" are different claims. The first is a property of the repository. The second is a property of a specific execution. Closing the gap between them is what cryptographic execution receipts do.

What this proves: execution binding, not ranking quality. The receipt proves that a specific output was bound to specific code, model artifacts, config, and input commitments at signing time. It does not prove the output is fair, truthful, or beneficial.

What the gap looks like

A recommender ranking is a function of four things:

  1. Code: the ranker source, version-controlled.
  2. Model artifacts: trained weights, ONNX/torchscript files, calibration tables.
  3. Configuration: feature flags, thresholds, A/B assignments, sampling rates.
  4. Input: the user's interaction features at ranking time.

The output is an ordered list of items. The published repo gives you (1). It does not give you a way to bind any specific output to a specific (1, 2, 3, 4) tuple. Without that binding, "the algorithm is open" can be true while the running system uses different weights, a tweaked config, or a different code path entirely. Nobody is accusing anyone of doing that. The point is that the open repo, on its own, cannot rule it out.

What a receipt binds

A post-ranking receipt is a small signed object emitted after the ranker runs. It commits to:

  • algorithm_commit: git SHA of the code that ran
  • model_artifacts: SHA-256 of every model file loaded
  • config_hash: JCS-canonical hash of the runtime config
  • input_commitment: Merkle root over user features (private, not exposed)
  • output_root: Merkle root over the ranked output list
  • opened_outputs: optional disclosure of top-N items

Signed once with Ed25519. Wire format is RFC 8785 (JCS) over the payload, signature appended. Verification is offline; no vendor cloud required.

The receipt doesn't reveal the user's private history. It commits to it. An authorised auditor with the right opening can verify the commitment matches the data they hold. Everyone else sees only that something was committed, and that the ranking was produced by exactly that code, models, and config.

The worked example

VeritasActa/x-algorithm-receipts is an Apache-2.0 wrapper around the published Phoenix pipeline. It ships two execution paths:

  • Mock mode (default): generates a synthetic Phoenix-style ranking event, signs it, and writes a verifiable receipt. Useful for instant verification without downloading the 2.9 GB Phoenix artifacts.
  • Real mode: runs phoenix/run_pipeline.py against a local clone of xai-org/x-algorithm with the upstream artifacts in place, hashes source, models, and config, commits to exact pipeline stdout lines, parses Phoenix ranked rows into structured {rank, post_id, score} records, and signs.

Both paths produce a v2 Ed25519 receipt and a JWKS for offline verification:

npm install
npm run demo
npx @veritasacta/verify examples/x-feed-demo.receipt.json --jwks examples/demo.jwks
node scripts/inspect-receipt.mjs examples/x-feed-demo.receipt.json

The verifier prints a Sigil visual fingerprint (a deterministic ASCII glyph derived from the payload hash plus issuer key) and reports signature validity. The inspector then prints the semantic fields:

✓ algorithm repo         https://github.com/xai-org/x-algorithm
✓ algorithm commit       git:published-demo-mock-2026-05-15
✓ pipeline               phoenix/run_pipeline.py
✓ model artifacts        5 file commitment(s)
✓ input commitment       merkle-rfc6962-sha256:...
✓ output root            merkle-rfc6962-sha256:...
✓ ranked items root      merkle-rfc6962-sha256:...
✓ selected count         50
✓ structured top-N       10

Three commands: install, verify, inspect. No accounts, no API keys, no cloud calls. The verifier is open-source Apache-2.0 on npm (@veritasacta/verify). The receipt format is documented as an active IETF Internet-Draft, draft-farley-acta-signed-receipts.

Real-mode receipt (v0.3.0)

The repo also ships a real-mode receipt at examples/x-feed-real.receipt.json, bound to a real ranking pass against xai-org/x-algorithm@0bfc2795. The wrapper executed uv run run_pipeline.py against the actual Phoenix artifacts, hashed 212 source files plus 8 model/config/corpus artifacts, committed to exact stdout lines, parsed 30 Phoenix ranked rows into structured records, and signed the event. Anyone can clone, download the artifacts, re-run, and verify offline.

Reproducibility

Run the wrapper twice with the same input. The two receipts have different issued_at timestamps and signatures, but the cryptographic commitments to the input and the ranked output match exactly:

COMMITMENT COMPARISON (these MUST match for reproducibility)
✓ algorithm_commit         git:published-demo-mock-2026-05-15
✓ input_commitment         merkle-rfc6962-sha256:5a8c2650b2c284da8e...
✓ output_root              merkle-rfc6962-sha256:909f48e943c1f67380...
✓ ranked_items_root        merkle-rfc6962-sha256:909f48e943c1f67380...

RUN-LEVEL FIELDS (these SHOULD differ across independent runs)
✓ issued_at  pass A: 2026-05-16T11:48:07.963Z
             pass B: 2026-05-16T11:48:08.015Z
✓ signature  pass A: 29ef72c3e960f72200c513e96e88bc7c...
             pass B: fa0aa85b37f08684cf53aeec48cae295...

This demonstrates how reproducibility can be made cryptographically checkable when the same input and artifacts are re-run. The receipt format makes any mismatch immediately visible field-by-field, instead of leaving it as a verbal claim. Whether a production recommender is itself reproducible is a property of that system, not of the receipt.

Tamper detection

Flip one character anywhere in the signed payload and the verifier rejects the receipt with a spec-cited error:

✗ Signature: INVALID
  Error:  invalid_signature
  Spec:   draft-farley-acta-signed-receipts-03 §6.1
  Hint:   The receipt has been modified or signed by a different key than the one provided.

This is the core security property of signed receipts: any change to any committed field invalidates the signature. There is no way to selectively edit the payload without re-signing it, and re-signing requires the private key held by the original issuer.

What this proves, and what it doesn't

Receipts prove that a specific output came from a specific code, model, config, and input. They do not prove:

  • the output is fair
  • the output is truthful
  • the output is socially beneficial
  • the model was trained on legally sourced data
  • the algorithm is good for users

Those are different audit problems. They require different methods. Conflating them is how "AI governance" becomes vague enough to mean nothing.

What receipts do solve is the substrate. You cannot answer fairness, truthfulness, or social benefit questions until you can first answer "is the thing you measured the thing that actually ran." Today, for production recommender systems, the answer is no. The receipt closes that one specific gap, precisely.

Where this fits

Cryptographic execution receipts aren't a recommender-specific idea. The same primitive shows up across:

  • AI agent decisions. Lesson 18 of microsoft/ai-agents-for-beginners walks through receipts for agent tool calls.
  • Supply chain readings (cold chain, provenance).
  • Software releases (SLSA-aligned provenance).
  • Continuous-control attestations on ScopeBlind's own infra.

The wire format is the same in every case: JCS-canonical payload, Ed25519 signature, verification by @veritasacta/verify. The recommender profile (recommender.post_ranking.v1) is one of several profiles of the format, which is described in an IETF Internet-Draft, an individual submission.

A caveat I want to be explicit about

Receipts are an engineering primitive, not a regulatory artifact. Whether a deployment of receipt-emitting recommenders satisfies DSA Article 27, AI Act Article 12, or any specific national requirement depends on retention, access control, the auditor's authority, and the regulator's view. Don't read this post as legal advice. Read it as: here is a working cryptographic layer you can adopt or extend.

If you build on it, let me know. If you find a bug, file an issue. If you think the framing is wrong, I would genuinely like to hear why.

VeritasActa/x-algorithm-receipts | @veritasacta/verify | IETF draft | browser verifier | microsoft Lesson 18

Where Decision Receipts Fit in the Agent Supply Chain

· Tom Farley

Archived from April 2026. The protect-mcp of this post’s time did not enforce Cedar policies: an evaluation that failed allowed the call. It was fixed in 0.7.0 (advisory GHSA-hm46-7j72-rpv9); use the current version. Removed or corrected since: a count of implementations, a bullet about another project’s repository, and the line on canonical JSON (RFC 8785 does not normalize strings). The discussions it links were open in April 2026; some have closed since.

An AI agent running in your infrastructure right now, one building software through tool calls or operating over customer data, leaves surprisingly little evidence of what it did. The internal logs your operator maintains are trustworthy only if you trust the operator. The build output matches a lockfile that nobody signed. The model version is a string in an environment variable. If a regulator asks "did your agent do something it should not have?" you have storytelling, not evidence.

This is not a philosophical problem. AI agents are now doing production builds, deploys, trading decisions, code review, and infrastructure operations. The single-human-in-the-loop model of software auditing breaks down when the "human" is a stochastic system making thousands of decisions per hour. The question auditors, regulators, and counterparties actually want answered is narrow: at each consequential moment, did the agent do what it was authorized to do, and is there verifiable proof?

Over the past few weeks a workable answer has taken shape, distributed across four attestation layers owned by different people and working groups. The layer I work on, decision receipts, is the one this post goes deepest on, because it is both the newest and the one I can speak to with first-hand authority. The other three layers (identity, tool integrity, build provenance) are the adjacent evidence that receipts compose with.

The four layers

  • 1. Agent identity. Attests to WHO is calling. Anchor: Raza Sharif's IETF draft draft-sharif-mcps-secure-mcp: per-message ECDSA signing
  • 2. Tool integrity. Attests to WHAT definitions the agent was given. Anchor: Signed MCP server manifests, in-toto attestations
  • 3. Decision receipts. Attests to WHAT the agent was authorized to do at each call. Anchor: draft-farley-acta-signed-receipts: Ed25519 + JCS + hash chain
  • 4. Build provenance. Attests to HOW the artifact was produced. Anchor: SLSA v1 + agent-commit v0.1

Agent identity answers WHO. Raza Sharif's IETF draft proposes per-message ECDSA signing for MCP protocol messages so each request from an agent to a tool server carries a signature that traces back to a stable agent DID. Agent equivalent of mTLS at the message level. Does not answer what the agent was authorized to do with that identity, or how the agent was built.

Tool integrity answers WHAT DEFINITIONS. An MCP server's tool descriptions get fed directly into the LLM's prompt, which means a tampered description is a prompt injection vector. A signed MCP server manifest pinned by digest, plus SLSA provenance for the server binary, closes this at load time. The in-toto attestation model is the natural schema. Does not answer whether the agent used those definitions correctly.

Build provenance answers HOW. SLSA provenance v1 was already the accepted format for build-output evidence; until a few hours before this post, there was no agent-specific build type. On April 17, 2026, Andrew McNamara published agent-commit/v0.1 as a draft SLSA provenance build type for AI-agent-produced commits. It captures agent identity (model, runtime, tools), sandbox policy, subagent delegation, and eBPF-observed runtime behavior as byproducts. The design correctly treats the agent as untrusted input and the builder platform as the trust anchor. Does not answer whether each step was authorized by the governance layer.

Decision receipts

Everything above is either pre-call (identity, tool integrity) or post-call (build provenance). The missing piece is at-call: a signed record of each policy evaluation, at the moment the decision is made, that anyone with the public key can verify offline later.

A decision receipt is a small JSON object:

Decision receipt

{
  "receipt_id": "rcpt-3f2a9c81",
  "tool_name": "Bash",
  "decision": "allow",
  "policy_id": "autoresearch-safe",
  "policy_digest": "sha256:8f3a...",
  "timestamp": "2026-04-17T12:34:56Z",
  "parent_receipt_hash": "sha256:a8f3c9d2",
  "signature": "ed25519:7b4a..."
}

Three invariants bind the format to verifiability:

  • JCS canonicalization (RFC 8785) before signing. Sorted keys, minimal whitespace. Any conformant implementation produces the same bytes for the same payload. Determinism is in the wire format, not the code.
  • Ed25519 signatures (RFC 8032) over the canonical payload. Deterministic, fixed-size, widely implemented, no nonce dependency. A receipt signed by one implementation verifies against any other conformant verifier.
  • Hash chain linkage. Each receipt carries the SHA-256 of its predecessor's canonical form. Insertions, deletions, and reorderings all break later receipts. The session chain is tamper-evident as a whole, not just per-receipt.

A reference verifier CLI, @veritasacta/verify, ships on npm with exit codes 0 (valid), 1 (tampered), 2 (malformed).

What receipts prove

  • Every policy check that ran, in order, with its exact decision
  • The policy that was evaluated, by both name (policy_id) and content digest (policy_digest)
  • The agent's authorization state at each tool call, including every deny
  • Tamper-evident session history: insertions, deletions, and rewrites all break the chain

What receipts do not prove

  • That the tool call actually did what it claimed (receipts are upstream of the runtime)
  • That the agent's aggregate behavior stayed within its declared profile across sessions
  • That the agent binary was not tampered with before the session started
  • The identity of the caller in a cryptographic sense (that is the identity layer)

Each receipt layer boundary is what the adjacent layers exist to cover. Build provenance with eBPF byproducts catches runtime-vs-authorization mismatches. Identity signatures catch impersonation. Tool integrity catches manifest tampering. Receipts catch governance-gate bypass, policy mismatch, and chain tampering, and they are the only layer that proves per-call authorization.

The composition

A complete session verification runs each layer in sequence. For every tool call:

  1. Identity. Verify the per-message ECDSA signature on the tool call against the agent's DID. Check DID continuity across any signing-key rotation.
  2. Tool integrity. Verify the tool definition hash matches the declared tool set in the attestation.
  3. Decision receipt. Verify the Ed25519 signature. Walk the chain back to genesis. Verify policy_digest matches the declared policy.
  4. Build provenance. Find the corresponding eBPF observation in the SLSA byproducts. Cross-check: every observation should have a receipt authorizing it; every receipt should map to observed behavior consistent with the authorization.

A receipt without a corresponding observation (authorized but not performed) is usually benign. An observation without a receipt (performed but not authorized) is a policy bypass and should fail the whole attestation.

Decision receipts ride in the SLSA provenance as a byproduct alongside the eBPF observations:

Byproduct entry in agent-commit/v0.1

{
  "name": "decision-receipts",
  "mediaType": "application/vnd.acta.receipts+json",
  "annotations": {
    "spec": "draft-farley-acta-signed-receipts-01",
    "chain_length": 147,
    "receipts": [ /* per-call receipts */ ]
  }
}

Worked example

An agent in Claude Code, governed by a Cedar policy called autoresearch-safe, is asked to build and publish an npm package. The policy forbids publishing without human approval.

  • Step 1: npm install. Identity signs the Bash-call MCP message. Tool set includes Bash at the pinned digest. Receipt rcpt-001 records { decision: allow, policy_id: autoresearch-safe }. SLSA byproduct observes the process spawn and registry egress.
  • Step 2: npm build. Same pattern. Receipt rcpt-002 links to rcpt-001.
  • Step 3: npm test. Same pattern. Receipt rcpt-003.
  • Step 4: npm publish. Identity signs, tool hash matches. Receipt rcpt-004 records { decision: DENY, policy_id: autoresearch-safe, reason: no_publish_without_human }. SLSA byproduct shows no corresponding network egress to the registry. The deny held.

At the end of the session, the verifier can confirm: the chain is intact, every step was authorized by the declared policy, the deny in step 4 was not bypassed, and the observed runtime behavior matches the authorizations. The deny in the receipt chain is the difference between "nothing was published" and "nothing was published because the policy said no."

Where to engage

The layers above are not any single organization's project. If you are working on any of them, the discussions open at the time were:

If you are building an implementation, the IETF drafts for identity (draft-sharif-mcps-secure-mcp) and decision receipts (draft-farley-acta-signed-receipts) are the format anchors.

The framing above is a description of where the work has converged, read back against itself. If the description is wrong in useful ways, file an issue on any of the threads above or email me.

When AI Finds Zero-Days, Who Proves What Happened?

· Tom Farley

Archived from April 2026. The protect-mcp of this post’s time did not enforce Cedar policies: an evaluation that failed allowed the call. It was fixed in 0.7.0 (advisory GHSA-hm46-7j72-rpv9); use the current version. Removed since: a section on other projects’ integrations, and a sentence that called the draft a standard. It is an individual Internet-Draft.

LLMs are getting good at finding vulnerabilities. Frontier models now discover real zero-day exploits in production software. The security community is adapting quickly to the discovery side. But the disclosure side is still stuck in 2015.

When a human researcher finds a vulnerability, trust is implicit. The researcher's reputation is the evidence. The timeline lives in email threads nobody can independently audit.

When an AI agent finds a vulnerability autonomously, that process breaks down. The agent doesn't have a reputation. The email thread doesn't prove when the scan actually happened. And when the same agent discovers dozens of vulnerabilities per day, manual coordination becomes impossible.

SHA-3 commitments are a start

Some organizations use cryptographic commitments for vulnerability disclosure. A SHA-3 hash proves "we had this information at this time." Useful for priority. But a hash only answers one question.

A responsible disclosure process needs to answer five:

  1. WHO performed the action? (Ed25519 signature with key ID)
  2. WHAT policy governed it? (Cedar policy digest)
  3. WHEN did it happen? (signed timestamp, tamper-evident)
  4. WHAT CAME BEFORE in the chain? (previousReceiptHash linking)
  5. HOW can anyone verify it? (offline, zero network calls)

A hash answers #3. Receipts answer all five.

The receipt-signed disclosure chain

Vulnerability Lifecycle

DISCOVER  Agent finds timing side-channel in auth module
          Receipt: vulnerability ID, severity, CWE
    |
ASSESS    Agent reports internally, escalates critical to human
          Receipt: CVSS score, recommended action
    |
DISCLOSE  Human approves responsible disclosure to vendor
          Receipt: notified parties, embargo terms, approval
    |
PATCH     Fix developed, tested, reviewed
          Receipt: patch hash, test results, reviewer
    |
DEPLOY    Fix deployed to production
          Receipt: deployment target, rollback status

Each step: Ed25519-signed, chain-linked, Cedar policy-bound

Verify the entire chain

npx @veritasacta/verify disclosure-chain.jsonl
# Exit 0: every signature valid, chain intact
# Exit 1: tampered
# Exit 2: malformed

Cedar policies: governance at decision time

When an AI agent scans codebases autonomously, what stops it from disclosing to the public before the vendor can patch? Or deploying a fix to production without review?

The answer is policy enforcement at decision time, not after-the-fact review. Cedar evaluates authorization in milliseconds:

vulnerability-disclosure.cedar

// Agent CAN scan code and report internally
permit(principal, action == Action::"scan_code", resource);
permit(principal, action == Action::"report_finding", resource)
  when { context.report_destination == "internal" };

// Agent CANNOT disclose externally without human approval
forbid(principal, action == Action::"disclose_vulnerability", resource)
  when { context.disclosure_target == "external"
      && context.human_approval != true };

// Agent CANNOT deploy patches to production without approval
forbid(principal, action == Action::"deploy_patch", resource)
  when { context.environment == "production"
      && context.human_approval != true };

// Agent MUST escalate critical findings
forbid(principal, action == Action::"report_finding", resource)
  when { context.severity == "critical"
      && context.escalated_to_human != true };

Every policy evaluation produces a receipt that includes the policy digest, a SHA-256 hash of the Cedar file. If someone changes the policy after the fact, the hash won't match.

Getting started

Install and verify

# Install the MCP gateway with receipt signing
npm install protect-mcp

# Verify a receipt chain
npx @veritasacta/verify disclosure-chain.jsonl --key <public-key-hex>

# View the complete example
# github.com/ScopeBlind/examples/tree/main/security-vulnerability-disclosure

For regulated industries (healthcare, finance, government), "the AI found and fixed it" is not sufficient evidence. A receipt chain proving every step was followed per policy, independently verifiable by any auditor, is.

IETF Draft | Security Example | protect-mcp | @veritasacta/verify | Design Issue

Your AI Agent Needs a Track Record, Not a Trust Badge

· Tom Farley

Archived from March 2026. Versions, products and links may be out of date, and the protect-mcp of this post’s time did not enforce Cedar policies: an evaluation that failed allowed the call. It was fixed in 0.7.0 (advisory GHSA-hm46-7j72-rpv9); use the current version. Corrected since: “issuer-blind”, now “issuer-agnostic”; the draft was at version 01 then and is at 03 now; the conformance tests have moved; and two lines now say what the receipts record: the calls that pass through the gate.

You cannot static-analyze a hallucination.

That's the fundamental problem with how we're securing AI agents today. We run static scans on MCP server code, slap a badge on the README, and hope for the best. But when the core execution path is non-deterministic, static analysis tells you nothing about what the agent will actually decide to do at 3am on a Sunday.

Static scanning tells you your code doesn't have a specific SQL injection vulnerability. It tells you nothing about whether the LLM will decide to DROP TABLE users because it misinterpreted a natural language instruction.

Scanners check before install. Nothing checks during runtime.

That's the gap. And it's why so many capable agentic workflows are stuck as local CLI demos. The security team asks "how do we know it's safe?" and the honest answer is: "We checked the code. We can't check the decisions."

The shift to runtime evidence

To get agents out of the lab and into production, we have to stop trying to predict every possible edge case in advance and start generating proof of what actually happened at runtime.

If an agent makes a consequential decision, you need to be able to prove:

  • Which agent made the decision
  • What tool it called
  • What the policy evaluation was
  • That the record of this event hasn't been altered

Centralized logging (console.log dumped into Datadog) isn't proof. The person who runs the server can edit the log, delete entries, or rewrite history. Regulators, auditors, and CISOs know this. "Check our dashboard" is not evidence.

Signed receipts that verify without trusting anyone

This is why we built ScopeBlind and submitted the receipt format to the IETF as draft-farley-acta-signed-receipts (version 01 at the time).

Instead of just logging tool calls, protect-mcp generates a cryptographically signed JSON receipt for every tool call that passes through it. Ed25519 signature over JCS-canonicalized JSON. Each receipt references its parents, forming a causal chain: a directed acyclic graph of every decision the agent made.

In 2 minutes, your agent goes from an untrusted black box to an entity with a verifiable history:

npx protect-mcp --policy policy.json -- node your-server.js

Every tool call gets a signed receipt. The receipts chain together. You can trace exactly how the agent got from point A to point B.

But here's where it gets interesting.

You don't have to trust us

We open-sourced the verifier. It's Apache 2.0. It runs offline. It's issuer-agnostic: it doesn't know or care that ScopeBlind issued the receipt. It checks the Ed25519 signature against the canonical JSON and tells you if the receipt has been tampered with. That's it.

Try it yourself right now: veritasacta.com/verify

Paste a receipt. Verification runs entirely in your browser. No API call. No account. No data leaves your machine. View the page source if you want to confirm.

That's the difference between "trust our dashboard" and "verify it yourself."

The verifier lives on veritasacta.com (the open protocol site), not on scopeblind.com. Because verification shouldn't depend on the vendor who issued the receipt. If ScopeBlind disappeared tomorrow, the receipts would still verify.

What this means for deploying agents

If you're trying to get an agent past your security team, stop arguing about hypotheticals. Do this:

  1. Wrap your MCP server with protect-mcp in shadow mode (it watches but blocks nothing)
  2. Run your agent through 10,000 test loops
  3. Hand the signed receipts to your CISO
  4. They verify every receipt offline at veritasacta.com/verify, without trusting you, without trusting us
  5. The receipts are a signed record of every decision the gate made across those 10,000 consecutive runs (they cover only the calls that pass through the gate)

That's not a trust badge. That's a track record. And a track record is what gets agents into production.

The standard

The receipt format is defined in draft-farley-acta-signed-receipts (version 01 at the time), submitted to the IETF. The verification algorithm is deterministic: any implementation that follows the spec produces the same result. We published conformance tests so anyone can build a compatible verifier.

The format uses two RFCs: Ed25519 signing (RFC 8032) and JCS canonicalization (RFC 8785). Nothing proprietary. Nothing that requires our servers. The receipts are self-contained proof.

How BlindLLM Uses Signed Receipts to Prove AI Comparison Results

· Tom Farley

Archived from March 2026. BlindLLM is a separate site, described here as it was then. Corrected since: the licences (the protocol and the verifier are Apache-2.0) and “issuer-blind”, now “issuer-agnostic”. Removed: three sentences we could not support, and the closing invitation to try BlindLLM.

Every week, a new AI benchmark drops. A new leaderboard shuffles. A new startup claims their model "outperforms GPT-4 on reasoning tasks" with a screenshot of a cherry-picked example. And every week, the same question goes unasked: how do you know?

AI model comparisons today operate on trust. You trust the evaluator ran the test fairly. You trust the prompts weren't tuned to favor one model. You trust the results weren't edited after the fact. There is no cryptographic proof, no audit trail, no way for a third party to independently verify that the comparison happened the way it was described.

For casual benchmarks, this is fine. For enterprise procurement decisions, regulatory compliance, and cross-organizational AI evaluation, it is not.

The blind comparison problem

Consider what a trustworthy AI comparison actually requires:

  1. Blindness. Neither the user nor the models should know which is "Model A" vs "Model B" during evaluation.
  2. Immutability. Once the comparison runs, the results cannot be altered without detection.
  3. Verifiability. A third party should be able to confirm the comparison happened as described.
  4. Completeness. The record should capture the full decision chain.

How BlindLLM works

BlindLLM is a comparison arena where AI models debate each other on substantive questions. It is not a chatbot playground. It is a proving ground designed to produce verifiable evidence of AI capability.

  • Step 1: Prompt submission. You provide a prompt, or select from curated battle prompts. The prompt is sent to two models simultaneously. The assignment of which model is "A" and which is "B" is randomized and hidden.
  • Step 2: Blind response generation. Both models generate their responses independently. Neither model knows it is being compared. The responses are presented to a judge with positional labels only.
  • Step 3: Judgment. The judge evaluates both responses on specified criteria (reasoning depth, factual accuracy, clarity) and selects a winner or declares a draw.
  • Step 4: Receipt issuance. The platform produces a signed receipt: a structured JSON document containing the prompt hash, model identifiers, positional assignments, verdict, and timestamp. Signed with Ed25519.
  • Step 5: Public anchoring. The receipt is optionally anchored to the Veritas Acta evidence chain, a tamper-evident public record.

The three-layer architecture

  • BlindLLM. The courtroom. Handles prompt routing, blind assignment, judging, and the user interface.
  • ScopeBlind. The notary. Manages key issuance, signing policy, and runtime controls via protect-mcp.
  • Veritas Acta. The public record. Defines the receipt format, provides independent verification, and maintains the open protocol.

These layers are intentionally separate. You can verify a BlindLLM receipt without contacting BlindLLM. You can use the Veritas Acta format without using ScopeBlind. The verification path is issuer-agnostic by design.

A concrete receipt

When a battle completes, the receipt produced looks like this:

Simplified battle receipt

{
  "type": "decision_receipt",
  "prompt_hash": "sha256:9f3a...",
  "participants": ["claude-opus-4", "gpt-4o"],
  "positions": {"A": "gpt-4o", "B": "claude-opus-4"},
  "verdict": "B",
  "judge": "automated",
  "criteria": ["reasoning_depth", "factual_accuracy"],
  "timestamp": "2026-03-27T14:32:00Z",
  "signature": "ed25519:xK7m..."
}

The prompt_hash commits to the exact prompt without revealing it. The signature covers every field via JCS canonicalization: change one character and the signature invalidates.

Verification without trust

Anyone holding this receipt can verify it independently:

Verify offline: Apache-2.0 licensed, no account needed

npx @veritasacta/verify receipt.json

This checks the Ed25519 signature against the canonical representation. No phone home. No API key. No network access needed. The math either checks out or it doesn't.

This matters for three concrete scenarios:

  • Enterprise AI procurement. Signed receipts turn "we tested it and Claude was better" into a verifiable artifact.
  • Regulatory compliance. Signed receipt chains provide tamper-evident records.
  • Cross-organizational trust. When Org A shares benchmarks with Org B, the results can be verified independently.

What this is not

BlindLLM is not a general-purpose benchmark suite. It does not replace MMLU, HumanEval, or domain-specific evaluation frameworks. It is designed for head-to-head comparisons on open-ended, qualitative tasks: the kind of evaluation that is hardest to make rigorous and easiest to manipulate.

The receipt does not prove the comparison was good, only that it happened as described. A poorly designed prompt still produces a verifiable receipt. The cryptography guarantees integrity, not quality.

The broader pattern

BlindLLM is one application of a broader principle: consequential machine decisions should produce verifiable evidence. Today it is AI model comparisons. Tomorrow it is agent tool calls, automated code reviews, or algorithmic hiring decisions.

The stack is open. The Veritas Acta protocol is Apache-2.0 licensed. The verification CLI is Apache-2.0 licensed. The receipt format is specified in an IETF Internet-Draft. If you are building systems where AI makes decisions that matter, the infrastructure to make those decisions provable already exists.