Falsifiable claims and deterministic verification for AI agents. Make your agents show their work.
Project description
showwork
Make your AI agents show their work.
Observability tools log what an agent did. showwork verifies what an agent claimed it did — deterministically, against reality — and refuses to bless a "done" that isn't real.
Zero dependencies. Stdlib only. One append-only ledger.
Read the portable spec-v0.1 ledger specification or install the
Claude Code Stop-hook adapter.
The problem
An agent reports "done: I updated the config, logged the decision, and moved the task file." Two of those three things never happened. Your logs show the agent ran. Your traces show what tools it called. Nothing checks whether the outcome it asserted is true.
That gap is why agent pilots die before production, and it's what audit-trail requirements (EU AI Act, HIPAA, SOC 2) actually ask for: not "what did the agent do," but "prove the record is faithful."
The model
- Claims are falsifiable or they're just prose. When an agent (or its harness) reports a completed change, it appends a structured claim to the ledger: a file changed, a path moved, a metric holds, a command passes. Free-form prose is recorded but never counted as proof.
- Verification is deterministic.
showwork verifyre-checks every claim against the filesystem and locked commands. No LLM judges an LLM. - The exit gate refuses false dones.
showwork finish --status okverifies the session's own claims first. If any is RED, the close is refused (exit 2). Fix it, retract it, or close asblocked— the bypass is stamped on the record either way. - The ledger is append-only. Corrections are retraction records that reference the original claim. History is never rewritten.
Quickstart
pip install showwork
# an agent session starts
showwork start --session deploy-fix --agent claude-code
# the agent claims what it did, with a check that can fail
showwork claim --session deploy-fix \
--claim "bumped the API timeout in config" \
--type file_contains --path config/api.yaml --pattern "timeout: 30"
showwork claim --session deploy-fix \
--claim "tests pass" \
--type command --command-arg python --command-arg scripts/run_tests.py
# the close is gated: exit 0 only if every claim verifies
showwork finish --session deploy-fix --status ok
claims: GREEN (2/2 verified)
session.finish recorded: deploy-fix
If a claim doesn't hold:
claims: RED (1/2 verified)
REFUSED: a clean close requires this session's claims to verify.
Audit any day or any session after the fact:
showwork verify --date 2026-07-09 # exit 0 GREEN, 3 YELLOW, 2 RED
showwork verify --session deploy-fix --json
Check types
| type | asserts |
|---|---|
file_exists |
a file is present |
file_contains |
a regex matches (or is absent from) a file |
path_moved |
source is gone, destination exists |
frontmatter |
a YAML frontmatter field equals a value |
glob_count |
a glob's match count satisfies == >= <= > < |
command |
a locked command exits as expected (python <script under project root> only — no shell, no metacharacters, no escape) |
Vacuous checks are rejected, not blessed: a regex that matches the empty string, or a glob count that's always true (>= 0), returns an error instead of a pass. A checker that lets an agent record a bogus "done" is worse than no checker.
Python API
from showwork import record_claim, verify_session, resolve_root
root = resolve_root()
record_claim(root, session="nightly", claim="report written",
check={"type": "file_exists", "path": "reports/2026-07-09.md"})
state = verify_session(root=root, session="nightly")
assert state["verdict"] == "GREEN"
Provenance
This isn't a spec written on a whiteboard. It's extracted from the verification layer that runs a real one-person, AI-operated company. The system began after one agent confidently reported three completed actions and two were not real. The resulting production ledger now supplies the receipts behind the package.
Read the sanitized case study and reproduce its aggregate metrics.
The sanitized snapshot contains 2,158 claims from 842 sessions. Deterministic checks back 2,152 claims. The ledger preserves 152 retractions and surfaced one malformed line instead of dropping it. Its captured audit was RED at 54/60 verified, because failed proof remains visible rather than becoming a green marketing number.
What showwork is not
- Not observability. Traces show what happened; showwork proves what was claimed to have happened.
- Not agent testing. Test frameworks check behavior pre-deployment; showwork verifies outcomes at runtime, every session.
- Not an LLM judge. Every check is deterministic and reproducible — which is what makes the record audit-grade.
Roadmap
- More coding-agent adapters
- Event stream + point-in-time replay
- More check types (HTTP probe, git state)
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file showwork-0.1.0.tar.gz.
File metadata
- Download URL: showwork-0.1.0.tar.gz
- Upload date:
- Size: 20.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
914a77de4c66a5f84c3116f221a699399cff6bdd16c5503e2a068a48f2098dac
|
|
| MD5 |
cc35b7b63375ffec1f4c8ed4b011a0c7
|
|
| BLAKE2b-256 |
c23070a0ab8ce011e450e9c5b73cd3254ef84574854a8b3469e770614f31c9e2
|
Provenance
The following attestation bundles were made for showwork-0.1.0.tar.gz:
Publisher:
publish.yml on bmdhodl/showwork
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
showwork-0.1.0.tar.gz -
Subject digest:
914a77de4c66a5f84c3116f221a699399cff6bdd16c5503e2a068a48f2098dac - Sigstore transparency entry: 2176902949
- Sigstore integration time:
-
Permalink:
bmdhodl/showwork@16c56716421c1a6f44028d763975686d16b6a0cd -
Branch / Tag:
refs/heads/main - Owner: https://github.com/bmdhodl
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@16c56716421c1a6f44028d763975686d16b6a0cd -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file showwork-0.1.0-py3-none-any.whl.
File metadata
- Download URL: showwork-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4548e90e55742f4f03f121e0e3e55110e8b865186ce72a5c65196bc075f4d656
|
|
| MD5 |
c1e5e64188a7e37ae39010a1ded70e25
|
|
| BLAKE2b-256 |
c3c823deee283a0d7a46d4dfbc5e35b3bba33f9adca7aef9d60cc268f3edab28
|
Provenance
The following attestation bundles were made for showwork-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on bmdhodl/showwork
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
showwork-0.1.0-py3-none-any.whl -
Subject digest:
4548e90e55742f4f03f121e0e3e55110e8b865186ce72a5c65196bc075f4d656 - Sigstore transparency entry: 2176903360
- Sigstore integration time:
-
Permalink:
bmdhodl/showwork@16c56716421c1a6f44028d763975686d16b6a0cd -
Branch / Tag:
refs/heads/main - Owner: https://github.com/bmdhodl
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@16c56716421c1a6f44028d763975686d16b6a0cd -
Trigger Event:
workflow_dispatch
-
Statement type: