For LangGraph agents · docketproof.dev

Put your agent on the record.

DocketProof pauses risky tool calls for approval before they run — then files a signed, chained entry for every decision. Anyone can verify the docket later, offline, without trusting us.

Every entry is evidence — approved or denied.

$ pip install docketproof
See it catch a tamper →

Tamper with one entry. Watch the whole docket after it fall.

This is a real, in-browser SHA-256 hash chain — not an animation. Each entry references the hash of the one before it, the same principle the real docket uses with ed25519 signatures. Alter entry № 0002 below and re-verify: notice that entry itself fails, and every entry filed after it becomes unverifiable too — even though nothing about them changed. That's what a chain buys you over a pile of individually signed documents.

THE DOCKET · 5 entries, chain intact

Click the pencil on any entry's resource_id to edit it, then Re-verify the docket. Nothing leaves this tab — every hash is computed locally with the browser's own SHA-256. The full docket uses ed25519 signatures over an RFC 8785-canonicalized payload; see the format spec for the exact bytes.

Four steps, all on your machine.

No hosted service is required for the core mechanism. Nothing about your agent's data leaves your process unless you turn on the hosted dashboard.

i.

Agent calls a guarded tool

Wrap any LangGraph tool with one decorator. Nothing else about your graph changes.

ii.

LangGraph pauses, natively

Uses LangGraph's own documented interrupt mechanism — no forking, no internals.

iii.

The decision is filed

Allow, deny, or hold for review. Both outcomes get signed — a denial is evidence too.

iv.

Anyone verifies, offline

ed25519 signature, hash-chained. Verify with the open CLI — no account, no API key.

One decorator. No graph rewrite.

agent.py
# pip install docketproof

from docketproof import guarded_tool, Policy

policy = Policy.from_file("policy.yaml")

@guarded_tool(policy=policy, docket_path="./docket.jsonl")
def delete_resource(resource_id: str) -> str:
    # your existing tool, unchanged
    ...

What an entry proves — and what it doesn't.

✓ What it proves

  • This exact tool call, with this exact input, was evaluated at this exact time.
  • The named policy produced this named verdict — allow, deny, or review.
  • If allowed, this is the exact call that proceeded — nothing was altered after filing.
  • The entry has not been modified since it was signed. Any edit breaks verification.

✗ What it doesn't prove

  • That the policy itself was correct or well-designed.
  • That the agent's underlying intent was safe, legal, or sensible.
  • Anything about actions outside this specific docket.
  • That the person who approved it should have.

Free forever, self-hosted. Paid for the parts you'd rather not build.

The SDK, the policy engine, and the verifier are open source and MIT-licensed — that stays true regardless of plan, and self-hosted really is unlimited: nothing touches our servers, so there's no artificial cap on the free tier like you'll find on hosted-only tools. Paid tiers meter entries synced to the hosted dashboard — not seats, not local usage. The hosted dashboard runs on EU-based infrastructure — docket data for hosted plans does not leave the EU, which matters if you're building evidence for EU data-residency or AI Act requirements.

Open Source
$0

Self-hosted, genuinely unlimited — it never reaches our infrastructure.

  • pip install docketproof
  • Local policy engine, no usage cap
  • Signed, chained entries on disk
  • Independent open-source verifier
  • Community support (GitHub issues)
pip install →
Business
$199/month

50,000 hosted entries/mo included, then $2 per 1,000.

  • Everything in Team
  • SSO
  • Unlimited retention
  • Signed audit export bundles
  • Priority support
Start 14-day trial →

Enterprise (on-prem/VPC, dedicated support): custom pricing. Pricing anchored to comparable open-core dev tools (Langfuse, LangSmith) as of August 2026 — not final, subject to what the market actually tells us.