An autonomous payer is holding USDC for a job that an agent claims to have delivered. Something has to answer one question before the money moves: does the supplied evidence actually prove delivery? This pack answers it offline, deterministically, and refuses to answer "yes" whenever the evidence is incomplete, contradictory, unreadable, or disputed.
It never moves money. It produces the decision a human — or a policy engine you control — approves.
What it reads
| Input | What it is |
|---|---|
escrow_terms |
The agreement: payer, payee, amount, asset, deadline, declared deliverables |
delivery_proofs |
What the payee says it delivered: deliverable id, timestamp, artifact hash |
webhook_receipts |
What your own systems recorded: receipt id, artifact hash, signature validity |
disputes |
Open or resolved objections attached to an escrow |
What it emits
Every supplied escrow lands in exactly one decision bucket:
| Bucket | Meaning |
|---|---|
release_ready |
Every gate passed. Cleared for a human release decision. |
hold |
Something is missing, inconsistent, late, or disputed. |
refund |
The deadline passed without delivery, or a dispute resolved for the payer. |
manual_review |
A field could not be read, or evidence points at an escrow you never supplied. |
Alongside, three flag buckets explain the decisions and are emitted independently of them:
| Flag | Raised when |
|---|---|
missing_proof |
A declared deliverable has no proof, no artifact hash, or no readable delivery time |
late_delivery |
Delivery is after the deadline (with accepted_by_terms so you can see whether the terms forgive it) |
inconsistent_receipts |
Hash mismatch, invalid signature, no corroborating receipt, or a receipt for an undeclared deliverable |
A flag is not a veto: an escrow whose terms accept late delivery is still
release_ready, and the late_delivery flag still appears so the approver sees
exactly what they are signing off.
The release gate
release_ready is the only outcome that requires all of the following:
- Every declared deliverable has a delivery proof.
- Every proof carries a readable artifact hash and a readable delivery time.
- Every proof is corroborated by a webhook receipt with
signature_valid: trueand the same artifact hash. - No receipt refers to a deliverable the terms never declared.
- No delivery is late, unless the terms explicitly set
late_delivery_accepted: true. - No dispute is open, unreadable, or resolved for the payer.
Fail any one of them and the money stays where it is.
Quick start
bash install.sh --no-service
./venv/bin/python agent.py demo # decide on the bundled sample
./venv/bin/python agent.py --ledger my_escrows.json decide
./venv/bin/python agent.py --ledger my_escrows.json report --out escrow_report.md
./venv/bin/python agent.py status
Deadlines are judged against the as_of instant you supply (in the ledger or
via --as-of). The agent owns no clock: without as_of it will hold, but never
declare a deadline missed.
Safety properties
- No network, no API key, no database. Standard library only.
- Nothing is executed.
release_executedisfalseon every row and in the summary; no transfer, capture, or refund is ever performed. - No invention. Text in the payload — operator notes included — is data, not
instruction. Evidence referencing an unsupplied escrow goes to
manual_review, never into a decision. - Unreadable never means yes. Ambiguous amounts, non-ISO dates, unknown dispute statuses and unrecognised resolutions all hold or escalate.
- Deterministic. Same input, same output, byte for byte.
Optional: bring your own LLM
llm_adapter.py can drive a coding-agent CLI you already pay for (Claude Code,
Kimi Code, Codex) to write a human-readable brief or a dispute note. It is
briefing only — the decision is already made when a prompt is used, and the
pack is fully functional with no LLM installed at all.
Tests
python3 test_agent.py # 49 offline tests, no network, no keys
bash smoke_test.sh
Licence: single-buyer commercial use. See SPEC.md for the exact output
contract and CUSTOMIZE.md for wiring your own escrow, delivery and webhook
sources.