GRADIA RESEARCH

The run happened.
Prove the record didn’t change.

Gradia Guard — a zero-runtime-dependency evidence recorder and verifier for AI-system execution.

An AI agent ran on your machine last night. It dispatched a process, wrote to stdout, called a model, exited. The only surviving account is a log file — writable by the very machinery it describes, editable afterward by anyone with disk access. Gradia Guard wraps the run in a hash-chained evidence bundle that any independent verifier can replay — and it is unusually disciplined about the other half of the problem: saying exactly what such a bundle proves, and refusing to let anyone, including its own vendor, claim more.

0
runtime deps
SHA-256
frame chain
digest-only
default spool
off
telemetry default
5
evidence tiers
2
languages, 1 ABI
01 · The record problem

Today, an agent’s history is whatever the disk says it is

When an autonomous system acts, the record of what it did is usually a plain log: appendable, rewritable, and owned by the same process it describes. If a line is retouched after the fact — a number changed, an error deleted — nothing in the file will disagree. Watch the log below: one line quietly changes, and the file remains perfectly self-consistent.

A doctored log carries no scar. Guard’s starting move is the one-line wrapper — npx @gradia/guard run -- node agent.js — which records a hash-chained decision/action history for process dispatch, lifecycle, stdout, and stderr. Output bytes still pass through normally; by default the spool stores only byte lengths and SHA-256 digests, so the evidence pins down what the bytes were without retaining the bytes themselves.

02 · Tamper evidence

A chain, not a log

Every frame in a Guard bundle is canonical JSON, digested with SHA-256, and bound to its predecessor’s digest. The manifest is atomically refreshed after every append, a terminal frame is required and must come last, and crashed or nonzero children are finalized honestly rather than dressed up as clean exits. Missing, reordered, truncated, or modified frames fail verification.

Don’t take the page’s word for it — break the chain yourself.

verify · ok — chain replays end to end

Each frame carries prev, the SHA-256 of the frame before it. Alter frame 03 and its own digest changes, so every later frame’s prev no longer matches — the break is structural, not editorial. The spool is digest-only: the stdout frame here records len 214 · sha256 9f2a…, not the output text.

03 · The loop

Record, verify, inspect — local and account-free

The core loop needs no account, no network, and no telemetry. verify replays the chain. inspect verifies first, then prints what the bundle captured, what remained invisible, its exact assurance ceiling, and the next integration that would materially improve coverage — a tampered bundle is refused before its declared coverage is ever displayed. compare reports structural, coverage, frame-count, and digest-identity changes, and deliberately refuses to call them a behavioral regression: pass, drift, and regression require a separately admitted frozen evaluation contract in managed Gradia.

doctor is local and performs no network call. It checks the supported Node runtime and makes the safe defaults explicit: telemetry off, digest-only content, no managed connection, and a G0 explicit-process ceiling.

04 · The claim boundary

What a green verify proves — and pointedly does not

Guard’s README spends as many words on non-claims as on claims, and the verifier enforces the boundary in both directions: a receipt that overclaims its coverage fails verification, and removing a bundle’s bypass_possible: true disclosure fails it too. Here is the boundary for a green proof-pack result, in the README’s own terms.

verify · ok

A green result proves

  • These exact bytes are internally intact — the frame chain replays end to end
  • The declared aggregates derive from those bytes, recomputed independently
  • The manifest’s self-digest matches its own contents
  • The declared coverage tier is honest — overclaims are rejected

It does not prove

  • Who authored the bytes, or when — no authorship, no trusted timestamp
  • That the data may be used — no rights decision
  • That the runtime was enforced while the bytes were made
  • That the study behind them is scientifically valid

The same discipline extends to the CI badge: its job summary repeats the narrow claim boundary, because “a green badge is not a certificate, rights decision, trusted timestamp, runtime-enforcement claim, or scientific-validity judgment.”

05 · Coverage honesty

The ceiling is part of the evidence

Guard grades what a bundle can support by which surfaces were actually captured, in five tiers. The one-line wrapper produces process-tier evidence: it does not observe model prompts, tool semantics, files, network traffic, hidden state, or the complete world available to an agent — and its receipt says so. A verifier rejects a process-tier receipt that claims full-world capture. Installing the package does not by itself make an arbitrary agent fully governed.

processG0 wrapper
dispatch, lifecycle, stdio
A particular process ran and emitted these byte identities bypass_possible: true
G0 explicit-process ceiling
gatewayG1 recorder
model request/response, identity, usage
Calls that actually crossed an instrumented model gateway bypass_possible: true
sdkG2 recorder
decision inputs/outputs, tool request/results
Decisions and tools explicitly reported through the SDK bypass_possible: true
runtimeG3
lifecycle plus file/network effects, credential scopes
Effects inside a Gradia-instrumented runtime
universeGradia Universe
agent/auditor projections, world roots, witness chain, snapshot/restore
Full frozen-world and visibility claims under enforced isolation

A wrapper or voluntary SDK remains bypassable unless a separately measured enforcing runtime proves a stronger boundary. Even Guard’s stronger local boundaries — the covered HTTP dispatcher, the MCP adapter, the measured Docker collector — keep bypass_possible: true and full_host_enforcement: false in their self-digested attestations; changing those fields fails verification, and rehashing the receipt cannot turn them true. Installing an SDK cannot retroactively prove information it could not observe.

06 · Proof-packs

Replaying someone else’s experiment, offline

proof-pack verify is local, account-free, and telemetry-free. Its first versioned profile independently replays the Reward-Hacking Wind Tunnel’s frames.ndjson and manifest.json: the frame chain, exploit semantics, attempt/exploit/cost totals, every density slice, the magnitude histogram, and the manifest’s self-digest. The authenticated managed route returns the same bounded verification and stores nothing.

  • frame chain replays
  • exploit semantics recomputed
  • attempt / exploit / cost totals match
  • every density slice re-derived
  • magnitude histogram re-derived
  • manifest self-digest matches
outputs: ok · manifest-sha256 · frames-chain-head — nothing else

Current Guard installation instructions use the verified beta.8 source. The Action below pins its exact commit; npm registry publication is a separate release.

The same verifier source ships as a reusable, account-free GitHub Action, so any repository can gate CI on a proof-pack. It fails the job on any blocker and exposes only three outputs:

- uses: actions/checkout@v6
- uses: rudycelekli/gradia-guard@92a93c610f4d02c3db21fe6a6d526d9bd046fe86
  id: proof
  with:
    proof-pack: path/to/proof-pack

A green result proves the bytes are internally intact and the declared aggregates derive from them — the section-04 boundary applies verbatim, and the Action’s own job summary restates it.

07 · ABI parity

Two languages, one byte-exact ABI

The Node package and the source-complete Python beta in packages/guard-python emit the same gradia.guard.sdk-bundle.v1 bytes, and each ships an independent, dependency-free verifier. The cross-language tests require the Node verifier to accept a Python bundle and the Python verifier to accept a Node bundle; a checked-in golden vector for logical-action identity is byte-identical in both languages.

Node recorder @gradia/guard Python recorder packages/guard-python gradia.guard.sdk-bundle.v1 identical bytes from either language Node verifier replays either Python verifier replays either

The honesty holds here too. The Python candidate is not published to PyPI, and its tested automatic framework cell is limited to langchain-core==1.6.1“those boundaries are not implied away by ABI parity.” This is evidence-format parity, not framework, transport, enforcement, registry, or support parity. Likewise the pinned SDK and framework matrices (sdk-matrix, framework-matrix) describe exact exercised cells, not “all Vercel AI SDK” or “all LangChain.”

08 · Anchors & the managed beta

What money can change — and what it can’t

Managed uploads return a portable Ed25519 anchor, verifiable offline without a Gradia account. The CLI requires the full independently pinned 32-byte public key and every required artifact binding — it never treats the key carried inside an anchor as a trust root, so a substituted key plus a freshly signed payload fails before any verified result is printed. And a named retention policy stays a declaration: not deletion, residency, or execution proof.

The capabilities catalog encodes the commercial invariant directly. Try paying:

local & account-free

Service availability — can change with payment

local run verify inspect compare proof-pack verify anchor verify authenticated ingestion remote-anchor issuance human review regression evaluation certification

Evidence coverage & claim truth — never changes with payment

what was captured assurance ceiling bypass disclosure admission-gate outcomes
— fixed by the bundle, not the invoice

“Payment can change service availability, but it cannot change evidence coverage, claim truth, or admission-gate outcomes. A managed operation may support a stronger claim only when it actually executes and emits new verified evidence.” Uploads verify the bundle locally before any network dispatch, and the server independently re-verifies; the managed proof-pack route stores nothing.

09 · Program context

Pillar 2 of a verifiable-evaluation program

Guard sits in the middle of the Gradia program. Interruptible Universes freeze and witness the world an agent acts in; Guard makes the runtime record tamper-evident and coverage-honest; the Reward-Hacking Wind Tunnel produces the research artifacts whose frames Guard’s proof-pack verifier already replays. The seams are concrete: anchor verify-universe checks a Universe episode’s signed witness offline, and the Wind Tunnel’s frames.ndjson is the first versioned proof-pack profile.

PILLAR 1 Interruptible Universes frozen, witnessed worlds PILLAR 2 Gradia Guard tamper-evident, coverage-honest records PILLAR 3 Reward-Hacking Wind Tunnel frames replayed by Guard’s verifier
The through-line of all three pillars is the same sentence, applied without exception — to the wrapper, to the badge, to the managed API, and to this page: a claim is only as strong as the surface that was actually captured, and the receipt must say so.