Deus Witness

Quickstart | Concepts | API | Verify | Coverage | Teams | Anchors | Recovery | Human approval in CI | Verifiable audit log | Unattended runs | Approval when unattended | Hooks vs deny

Audit log for AI agent actions you can verify offline

An agent runs tools for hours without you. Later someone asks: what did it do, and who allowed it? A plain log file answers only "what the logger says". This guide explains what a log must have to be checked by a third party without trusting its author, then shows how Deus Witness packs it and how to verify a real pack offline.

What a trustworthy log needs

Logging in Claude Code itself is useful but is a record on the same machine as the agent. Its hook events, for example, give you PreToolUse and PostToolUse inputs (Hooks reference), which you can write to a file. For an audit you want more properties than a file has:

A signed ledger and receipts

Deus Witness (a service plus a hook, pip install deus-witness) judges every tool call of an agent against a mandate you signed with a passkey. Each decision (allow, deny or defer) is appended to a hash-chained ledger and answered with a receipt: a signed statement "this call, this verdict, this ledger position". The hook only lets a call run after it has verified the receipt. Periodically the ledger gets a signed checkpoint, and every hour a Merkle root of new checkpoints goes to OpenTimestamps calendars, which commit to Bitcoin.

From the dashboard you export an evidence pack, a zip with the ledger, checkpoints, receipts, the registry of keys, anchor files and a signed manifest.

Verify a pack offline

Install the checker (Python 3.10 or newer). It comes from the package, not from the pack, so a doctored pack cannot bring its own checker:

python3 -m venv ~/dw && ~/dw/bin/pip install deus-witness
curl -sLO https://witness.sipkigroup.com/demo/deus-witness-demo-pack.zip
~/dw/bin/deus-witness-verify-pack deus-witness-demo-pack.zip --offline

That is a public demo pack (its key is public, it is not a real account). I ran exactly this with deus-witness 0.2.26. Output, shortened:

manifest: signed by the witness key
complete as of 2026-10-19 03:14:26 UTC (seq 24)
ledger: valid (26 entries)
receipts: 6/6 included
anchor ...: pending (inclusion in batch root proven; not stamped)
anchors: NONE stamped ... the history is vouched for by the witness alone
trust: verdicts: the witness's allow/deny/defer decisions are NOT replayed here ...
RESULT: VALID

The exit code is 0 for RESULT: VALID, 1 for INVALID. Now change one byte of ledger/ledger.cose inside the zip and run it again: the lines become manifest: MISMATCH ledger/ledger.cose, ledger: invalid ... and RESULT: INVALID, exit 1. Add --require-anchors and a pack without a stamped anchor is INVALID too, which is the setting to use when the operator is not you.

Two flags make the check independent of the pack: --witness-kid=<hex> (the key id you fetched yourself from /v1/witness) and --owner-kid=<hex> (a key your Devices page shows). A mismatch is INVALID. Without them the checker reads the keys from the pack and prints a trust: line saying so.

Limits (read the trust lines)

Full option list and older pack versions: Verify. How the receipts are made: Concepts. To produce such a log from Claude Code in CI: Require human approval for Claude Code tool calls, and to try it yourself, Quickstart. The browser demo at /demo/ builds the same kind of pack in about a minute.