DEV Community

Ross
Ross

Posted on

My AI agent now hands me signed receipts proving its work actually ran

Like everyone, I've been reviewing AI-generated code that compiles, passes its own tests, and doesn't run. So I built the thing I wanted: when an agent (or a human) claims work is done, the claim arrives as a receipt, the app was actually booted, supervised, and observed answering HTTP, and the evidence is written into an ed25519-signed attestation you can verify independently on any machine with npx bootproof verify. No account, no platform, no dashboard.

The problem
Every developer knows this loop:

git clone some/reponpm installnpm run dev
Then reality appears. Wrong Node version. Wrong pnpm version. Missing Java. Docker is running but the service is not healthy. The app starts but nothing responds. An AI agent confidently says "done" because a process started.

That is not proof.

A README can be useful, but it is not proof. A terminal command can be useful, but it is not proof. A model response can be useful, but it is not proof.

What BootProof does
BootProof separates activity from evidence.

Weak signal
What BootProof wants instead
command exited observed health
process started reachable endpoint
container running service actually responds
README says it works repo evidence + runtime proof
AI says it is done signed attestation

A failed run is still useful if it tells the truth:

✗ NOT VERIFIED — package_manager_version_mismatch

What happened:
The repository requires pnpm 10.24.0, but this environment has pnpm 9.15.4.

Why BootProof refused:
The dependency install cannot be trusted with the wrong package manager version.

Safe next step:
Run corepack enable && corepack prepare pnpm@10.24.0 --activate, then rerun BootProof.

Evidence:
.bootproof/attestation.json

Try the Living Receipt
The Living Receipt is the same evidence as the JSON attestation, rendered as a single self-contained HTML file that re-verifies its own ed25519 signature in your browser with zero network calls.

Download it, open it locally, then click Tamper with signature to watch the verdict collapse:

curl -sL https://github.com/bootproof/bootproof/raw/main/assets/living-receipt.html -o proof.bootproof.html
open proof.bootproof.html

If a single byte of the signed message is altered, the verdict collapses with the signature. That is the whole point: a green check that survives tampering would defeat the entire premise.

Receipt Gate: block AI PRs that don't run
Receipt Gate is a GitHub Action that blocks PR merges unless BootProof observes a real boot. No proof, no merge.

  • uses: bootproof/receipt-gate@v1 with: path: . require-health: 'true'

Gate your AI agent directly — in .claude/settings.json, make the agent hand you a receipt every time it claims done:

json

{
"hooks": {
"Stop": [{
"hooks": [{
"type": "command",
"command": "npx -y bootproof@0.4.1 up . --provider local --unsafe-local --json --timeout 60000 > .bootproof-last.json; node -e \"const r=require('./.bootproof-last.json'); console.log(r.booted && r.healthVerified ? '✅ RECEIPT: work boots and answers' : '❌ NO RECEIPT: ' + (r.failureClass||'boot not observed'));\""
}]
}]
}
}

The agent finishes; the receipt (or its absence) prints before you review a single line.

The composed trust story
The tool that signs runtime proofs is itself published with signed build provenance. Build provenance from Sigstore covers how it was built; runtime proof from BootProof covers that it runs. Verify both ends.

npm view bootproof@0.4.1 dist.attestations

What it refuses to claim
The part I care most about is what it refuses to claim. No observed signal → no green check. A local receipt proves integrity-since-signing, not that the signing machine was honest — that's stated in the artifact itself, with a documented trust ladder (local_developer_signed → ci_oidc_signed → neutral_runner_signed → transparency_logged) as the upgrade path. A trust tool that overclaims is worse than no tool, so this one is deliberately conservative.

It's open source (Apache-2.0), and I'd genuinely value having it broken by this crowd.

Links:

GitHub: https://github.com/bootproof/bootproof
Receipt Gate on the GitHub Actions Marketplace: https://github.com/marketplace/actions/receipt-gate
npm: https://www.npmjs.com/package/bootproof

Top comments (5)

Collapse
 
theuniverseson profile image
Andrii Krugliak

The activity vs evidence cut is the right one, and runtime attestation is a real gap. The part it can't close for me is correct vs merely-ran: a service that boots, answers HTTP, and confidently returns the wrong answer passes every health check you listed. What worked for us was one human who'll act on the output signing off, since "it responded" and "it's right" break in different places.

Collapse
 
rbuckley_ profile image
Ross

You're right, and I want to be precise about what BootProof claims and doesn't claim.

The attestation proves "it ran and answered", not "it answered correctly." A service that returns the wrong answer with HTTP 200 passes BootProof's health check. That's a real gap, and closing it isn't something the proof layer can do alone, correctness requires either behavioral tests (which the author writes, with the author's blind spots) or human review (which is the sign-off you're describing).

The honesty contract states this explicitly: the attestation can prove "HTTP 200 was observed at localhost:3000/" and cannot prove "every feature works" or "every dependency is production-ready." The receipt says "this ran" so that the human reviewer's sign-off is about correctness, not about whether the thing even started.

The layering I'm aiming for:

  1. BootProof: did it run? (runtime evidence)
  2. Tests: did it behave? (behavioral evidence)
  3. Human sign-off: is it right? (judgment)

Each layer breaks in different places, like you said. The agent-PR problem is that layers 1 and 2 are often skipped, the agent says "done" and the human jumps to layer 3 without verifying the thing even runs. BootProof forces layer 1 before layer 3 is meaningful.

What I'm not trying to do is replace layer 3. The human who'll act on the output is the last line of defense, and the attestation is there to make their sign-off better-informed, not to substitute for it.

Collapse
 
theuniverseson profile image
Andrii Krugliak

That ordering is the real product: making "did it run" come before "is it right" is what stops the human from rubber-stamping a corpse. We got to the same place from the other side, we just moved the sign-off to the buyer instead of the author, since the author has the same blind spot the agent does.

Collapse
 
raju_dandigam profile image
Raju Dandigam

Separating activity from evidence is exactly the bar more coding-agent workflows need. “Process started” and “tests passed” are weak signals on their own, and your signed attestation framing is a good way to force the system to prove it actually booted, answered HTTP, and produced runtime evidence instead of just sounding confident. I also like that this treats human and agent claims the same way, because the verification layer should not care who made the claim. This is very aligned with the execution-trace side of agent-inspect: the goal is to make completion auditable instead of anecdotal. I’d be curious how far you think attestations should go for local dev workflows before the proof layer becomes too heavy for the iteration loop.

Collapse
 
rbuckley_ profile image
Ross

Thanks for this, and for the agent-inspect reference, I hadn't seen that work. The alignment on "auditable instead of anecdotal" is exactly the framing I was after.

On the weight question, my honest answer is: the proof layer should be opt-in per claim, not per run. The attestation is always written (it's cheap, a JSON file with an ed25519 signature), but the heavy artifacts, the Living Receipt HTML, the CI gate, the --require-known-signer verification, are all opt-in flags. Local dev iteration doesn't touch
them.

Concretely, the weight ladder I've settled on:

  1. Local iteration: no proof layer. npm run dev is fast feedback. BootProof isn't in the loop.

  2. Local "did I break it?": bootproof up . --provider local --unsafe- local — runs in ~5-10 seconds, writes a signed attestation, gives you a human verdict. Cheap enough to run before pushing.

  3. CI advisory: the BootProof Action runs on PRs, posts a sticky comment with the verdict + evidence. Doesn't block. Teams live with this for a month to build trust in the signal.

  4. CI enforcement: Receipt Gate blocks merges without observed health. Opt-in when the team is ready.

  5. Receipt-as-proof: --receipt generates the self-verifying HTML for sharing externally (outreach, audit, compliance). Only when you need to convince someone else.

The key design constraint: the proof layer should never slow down the inner loop. It enters at the boundary, before push, on PR, at merge, where the cost of a false "done" is higher than the cost of a 10-second verification.

The open question I'm still sitting with: where does the proof layer belong for agent loops specifically? A Stop-hook that runs BootProof on every agent "done" claim adds ~10 seconds per claim, which feels right for review workflows but wrong for autonomous loops. Curious whether agent-inspect has landed on a threshold there.