Skip to content

Quickstart

Five minutes from nothing to a verified receipt. No API key, no account, no network — the demo provider is scripted and local, so this works on a plane.

1. Install

Install from PyPI:

# Requires: Python 3.11+, pip, and network access to pypi.org.
python3 -m pip install docket-ai
docket --version

To keep the package out of your project virtualenv, install it into its own isolated environment instead:

# Requires: Python 3.11+, pipx, and network access to pypi.org.
pipx install docket-ai

To install from a clone, which tracks main instead of a pinned version:

# Requires: Python 3.11+, pip, git, and network access to github.com.
git clone https://github.com/docket-dev-org/docket && cd docket
python3 -m pip install .          # or: pipx install .  (keeps it out of a project venv)
docket --version

No install at all also works, from inside the clone:

PYTHONPATH=src python3 -m docket demo

[!NOTE] The distribution is named docket-ai because PyPI administratively prohibits the bare name docket. Everything else is docket: the import, the console script, and the command you type. See Publishing for the reason and the evidence.

Nothing above needs an account, an API key, or the network after the download; the demo provider is scripted and local.

2. Watch a runaway agent get stopped (20 seconds)

docket demo

You will see an agent loop on an expensive model, cross a $2.00 cap, get refused at the boundary, and be terminated (exit 42). Docket then prints findings — the loop, the deny-write violation, the uncached context — and verifies the receipt it just wrote.

Then:

docket demo --tamper      # edits one byte of the ledger; verification fails at that event
docket demo --keep        # keep the workspace and print the path so you can poke at the files

3. Bound a real agent

cd ~/your-project
docket init                                   # writes docket.toml (commented, edit freely)
docket run --max-usd 5 -- claude -p "fix the failing test in src/parser.py"

Or with any command, in any language:

docket run --max-usd 5 -- ./your-agent --flag value
docket run --max-usd 5 --http-proxy -- ./build.sh     # everything through the boundary

What you get back is one line per run (numbers from your run, not this page):

docket: DKT-20261013-A03507 completed · $0.004510 of $5.00 cap · 3 calls · receipt .docket/receipts/DKT-20261013-A03507.receipt.json

A run that crosses a cap ends the same way, with a different verb:

docket: DKT-20261013-746EF4 stopped by policy (max_usd) · $2.00 of $2.00 cap · 15 calls · receipt .docket/receipts/DKT-20261013-746EF4.receipt.json

(Exit code 42 in that case — see cli.md.)

4. Read what happened

docket report                 # human summary of the newest run
docket report --markdown      # the same, as markdown for a ticket or a client
docket explain                # findings: where the money went, with evidence
docket explain --json         # the same as data

Each finding names the ledger events it rests on, and says whether it is deterministic (arithmetic over events) or heuristic (a model of what could have happened).

5. Verify the receipt offline

docket verify .docket/receipts/DKT-*.receipt.json --ledger .docket/runs/*.jsonl

Exits 0 if it checks out, 1 if it does not — usable in CI directly.

To prove the point that the format is not this tool, verify with the independent Node implementation instead (standard library only, no dependencies). It ships inside the wheel, so this works from an installation and not only from a clone:

docket verify --impl node .docket/receipts/DKT-*.receipt.json

Both implementations are bound to the same committed conformance vectors, which also ship inside the wheel. If you are writing a verifier in another language, start at ../spec/docket-receipt-1.md §8 and use those vectors as your test suite.

6. Record your own agent's work (optional)

If you write the agent, you can add business-level events that Docket cannot observe on its own — which tool did what, how big the result was, when a phase began:

import docket

with docket.Session(max_usd=2.00) as s:
    s.record_model_call(model="claude-sonnet-5", input_tokens=1200, output_tokens=340)
    s.record_tool("search", {"q": "invoice totals"}, result_bytes=41_000)
    s.record_note("phase 2: writing files")

Any language, over HTTP:

curl -X POST "$DOCKET_PROXY_URL/docket/tool/call" \
     -d '{"name":"search","args_digest":"9f86d081884c7d659a2feaa0c55ad015","result_bytes":41000}'

Tool arguments are stored as digests by default — evidence without a second copy of your data.

A worked example with files

examples/ contains a runnable end-to-end scenario: a tiny agent, a policy, a CI recipe, and the expected receipt, including how to run it with no network at all.

Where to go next