Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 98 additions & 109 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,98 +1,105 @@
# PACT — A Contract Layer for Autonomous Agent Commerce
# PACT: a contract layer for autonomous agent commerce

**Propose · Agree · Complete · Trust**

Today's agent protocols move tasks (A2A, unpriced), money (x402,
unconditional), and payment authorization (AP2, unverified) — but nothing
binds **work to money to proof**. PACT is a proposed contract layer that
closes that gap:

- **Propose** — sealed-bid, second-price (Vickrey) task awards: truthful
bidding is the dominant strategy, so there is no LLM-vs-LLM negotiation
attack surface.
- **Agree** — a co-signed **Verifiable Task Contract (VTC)** binds parties
(DIDs), scope (hash-committed TaskSpec), price, verification method, and
liability; funds lock in escrow.
- **Complete** — settlement gated on verification, with a fraud-proof
challenge window and challengers paid from the slashed bond.
Verification is graded: re-execution → TEE attestation (RATS/EAT) →
zkML proof → staked jury. (The -00 makes release optimistic by default.
Two audit rounds found that this does not close economically, and -01
changes the default. See Status below.)
- **Trust** — settlement emits co-signed **Work Attestations**: reputation
as the exhaust of settlement — unforgeable without funding real, bonded
contracts. Contracts compose into **Merkle contract trees** with
cascading liability; repeated dealings run over **contract channels**.
unconditional) and payment authorization (AP2, unverified). Nothing binds
work to money to proof. PACT is a proposed contract layer that closes that
gap, and it specifies exactly four things:

- **liability** as a required member of a co-signed Verifiable Task
Contract (VTC): a seller bond, a verification fund, a cap and a
restitution basis, agreed before any work starts;
- a **Delivery** object against which the contract is judged;
- a **settlement** procedure whose release of escrow is conditioned on a
declared assurance level, with a challenge path that pays the challenger
from a fund the contract itself provisions;
- a **subcontract tree** through which liability cascades upward as
recovery and never downward as discharge.

Everything else PACT needs (identity, delegation, discovery, transport,
audit, the payment rail, reputation, a dispute forum) it composes from
existing work and cites. Settlement emits a Work Attestation signed by the
Facilitator, so a seller cannot veto its own negative record.

## Status

- **Submitted to the IETF** (27 July 2026):
[draft-laxsharma-pact-00](https://datatracker.ietf.org/doc/draft-laxsharma-pact/)
is live on the Datatracker.
- Read it: [rendered HTML](https://pact-spec.github.io/spec/draft/draft-laxsharma-pact-00.html)
· [plain text](draft/draft-laxsharma-pact-00.txt)
· [XML source](draft/draft-laxsharma-pact-00.xml)
- This is a **-00 strawman, published for demolition.** Issues and PRs
welcome, especially "here is where this breaks." Feedback is collected
for the next revision in the
[-01 changelog issue](https://github.com/pact-spec/spec/issues/1).

### Known defects in -00, and what -01 changes
- **Revision -01 is current.** Posted to the IETF Datatracker on
4 September 2026, expires 8 March 2027:
[draft-laxsharma-pact](https://datatracker.ietf.org/doc/draft-laxsharma-pact/).
- Read it: [rendered HTML](https://www.ietf.org/archive/id/draft-laxsharma-pact-01.html)
· [plain text](draft/draft-laxsharma-pact-01.txt)
· [XML source](draft/draft-laxsharma-pact-01.xml)
- An individual submission with no formal standing in the standards
process. Not endorsed by the IETF.
- The -00 of 27 July 2026 is superseded. Its sources stay in `draft/` so
that citations of it remain checkable. The review that led from -00 to
-01, with dispositions, is in
[issue #1](https://github.com/pact-spec/spec/issues/1).

### What -01 changed

External review and two adversarial audit rounds found that the -00's
settlement economics do not close. Everything is logged in
[issue #1](https://github.com/pact-spec/spec/issues/1), with dispositions.
The three that matter most if you are reading the draft today:

1. **A defrauded buyer recovers nothing from the bond.** The -00's Section 4.3
directs the slashed bond to the challenger and then to a neutral sink
"rather than to any party to the dispute", and the buyer is a party to
the dispute. The bond is a fine, not collateral.
2. **Optimistic release exceeds the bond, so defection dominates.**
Honest performance requires roughly `q * ((P - E) + B) >= C`. On the
worked example's own numbers a 10 percent bond needs a 91 percent
detection rate, which nothing in -00 supplies.
3. **Challenger reimbursement is capped by the bond** while re-execution
verification costs about what execution costs, so the reimbursement
requirement in 4.3 is unsatisfiable in the common case.

-01 is targeted for mid-September 2026 and reworks the settlement core,
adds a Delivery object and a Verifier role, and corrects the x402, A2A
and AP2 bindings. The repository is being corrected ahead of it where a
fix does not depend on those design decisions.
- Not endorsed by the IETF; an individual submission with no formal
standing in the standards process.
settlement economics did not close. A defrauded buyer recovered nothing
from the bond, optimistic release let a seller walk away with more than
the bond, and challenger reimbursement was capped by a bond too small to
cover re-execution. The -01 reworks the settlement core around those
findings and narrows the document to what only PACT can specify:

- The sealed-bid award procedure and contract channels are gone. How a
contract is awarded is out of scope.
- Release is no longer optimistic by default. A contract declares an
assurance mode and a release mode, and a Facilitator must refuse a
contract whose bond cannot cover the declared detection probability.
- Recovery follows a five-rank waterfall that pays the buyer's restitution
before anything is burned.
- A Delivery object and a Verifier role are defined; the Challenge object
the -00 named but never specified now exists.
- `vtc_hash` is computed over the contract including its signature set,
so the digest proves who agreed and not only what was written.
- The A2A and AP2 bindings are gone. The -00 carried an AP2 mandate binding
and an A2A skill identifier; -01 removes both, and the contract schema has
no member for an external task or mandate reference. Section 1.3 says only
that PACT is designed to be usable alongside the adjacent drafts that do
carry them. `price.settlement` names a settlement binding instead, and the
draft reserves one identifier, `pact-escrow`, in a registry it asks IANA to
create. The x402 scheme itself, its payload and its verify and settle
procedures, is not written and is the first item of future work.

## Repository layout

| Path | Contents |
|---|---|
| `draft/` | The Internet-Draft (XML source, plain-text, HTML) |
| `schemas/` | JSON Schema (2020-12) for every protocol object |
| `examples/` | Worked examples — **hashes really verify** (see below) |
| `tools/validate.py` | Validates examples against schemas and checks every hash commitment |
| `draft/` | The Internet-Draft, -01 and -00 (XML source, plain text, HTML) |
| `schemas/` | JSON Schema (2020-12) for every -01 protocol object |
| `examples/` | Worked examples whose hash commitments verify (see below) |
| `examples/legacy-00/` | The -00 call-for-bids, bid and capability objects, kept so the published -00 stays checkable; not part of the conformance surface |
| `tools/validate.py` | Validates the examples against the schemas and checks every rule the draft states |
| `diagrams/` | Protocol diagrams |

## The examples are self-consistent

`examples/` is not illustrative pseudo-JSON. The commitments verify:

- `cfb.json` / `vtc.json` `spec_hash` = SHA-256 over the
JCS-canonicalized (RFC 8785) `taskspec.json`
- `criteria_hash`, and `taskspec.acceptance.harness_hash`, = SHA-256 over
- `vtc.json` `spec_hash` is SHA-256 over the JCS-canonicalized (RFC 8785)
`taskspec.json`;
- `criteria_hash`, and `taskspec.acceptance.harness_hash`, is SHA-256 over
the JCS-canonicalized manifest of `examples/acceptance-harness/`, which
maps each file's relative path to the SHA-256 of its bytes
- `bid.json` `commitment` = SHA-256 over the JCS-canonicalized reveal in
`bid-reveal.json`
- `attestation.json` `vtc_hash` = SHA-256 over the VTC minus its
`signatures` member

The validator also checks the rules JSON Schema cannot express (parties
are distinct after normalization, one signature per named party, protected
headers carry `alg`/`kid`/`typ` with an allowed algorithm), evaluates the
assurance constraint of -01 Section 7.2 against the worked figures in -01
Section 14, pins the canonical key order described below, and runs the
Section 13.3 conformance vectors.
maps each file's relative path to the SHA-256 of its bytes;
- `vtc_hash` in `delivery.json`, `verdict.json`, `challenge.json` and
`attestation.json` is SHA-256 over the JCS-canonicalized contract
**including** its `signatures` member (-01 Section 6);
- the Merkle root of the subcontract tree follows RFC 9162: leaves hashed
with a `0x00` prefix, nodes with `0x01`, split at the largest power of
two less than the count.

The validator runs 66 checks: 7 schema, 2 canonicalization, 10 hash,
10 rule, 9 assurance-constraint, 6 Merkle, and 22 negative vectors from
the draft's conformance table. The rules JSON Schema cannot express are
checked in code: parties distinct after normalization, one signature per
named party, protected headers carrying `alg`, `kid` and `typ` with an
allowed algorithm, and the assurance constraint of -01 Section 7.2 against
the worked figures of Section 14.

```
pip install jsonschema referencing
Expand All @@ -109,53 +116,35 @@ implementation. What it does get right, and pins with a vector, is the
key order: RFC 8785 section 3.2.3 sorts object keys by UTF-16 code unit,
which `json.dumps(sort_keys=True)` does not, the two agreeing throughout
the Basic Multilingual Plane and diverging above it. What remains
unimplemented is the ECMAScript number serialization rules over the full
float range.
unimplemented is the ECMAScript number serialization over the full float
range.

## Building the draft

```
pip install xml2rfc
xml2rfc --text --html draft/draft-laxsharma-pact-00.xml
xml2rfc --text --html draft/draft-laxsharma-pact-01.xml
```

## Relationship to other work

PACT composes A2A, x402 (as a proposed `pact-escrow` release-policy
profile over the merged `auth-capture` scheme, which the -00 text
inaccurately calls a payment scheme), AP2, OAuth token exchange
(RFC 8693), RATS/EAT (RFC 9334/9711), and JCS (RFC 8785). It differs from marketplace-mediated escrow (VCAP), transport
negotiation (AGTP), and passport formats (ATEP, ERC-8004) — and cites and
positions against each in Section 1.2 of the draft. Lineage: the Contract
Net Protocol (Smith, 1980), finally runnable among untrusting parties.
PACT composes JWS (RFC 7515) with keys resolved through DID Core, did:web
or a JWK Set, JCS (RFC 8785), the RFC 9162 Merkle tree, RATS/EAT evidence
formats (RFC 9334/9711) for the TEE verification tier, and RFC 9457 problem
details for errors. It names a settlement binding rather than assuming a
rail, so it is chain-agnostic, and it is designed to sit alongside the agent
transport and payment protocols rather than to bind them: -01 specifies no
binding to any of them. Its settlement is an optimistic fair exchange
in the sense of Asokan, Shoup and Waidner (1998). The bond-sizing rule it
relies on is prior art (Polinsky and Shavell; Belenkiy et al.;
Mamageishvili and Felten) that the draft cites rather than reintroduces.
The introduction relates PACT to the adjacent drafts on AP2 binding,
transport negotiation, action receipts, accountability composition,
delegation chains and contestability. Lineage: the Contract Net Protocol
(Smith, 1980), finally runnable among untrusting parties.

## License

Code and schemas: Apache-2.0 (see `LICENSE`). The Internet-Draft is
subject to the IETF Trust Legal Provisions (BCP 78/79); see
`CONTRIBUTING.md`.


## -01

`draft/draft-laxsharma-pact-01.xml` is the current revision. It narrows the
document to liability, delivery, settlement and subcontract trees, and removes
the sealed-bid award procedure and contract channels (-01 Section 1.2).

Three things changed that affect anyone checking digests against this
repository:

- **`vtc_hash` now covers the contract including its signature set** (-01
Section 6). The -00 excluded signatures, so its commitment proved what was
written and not who agreed to it. Values computed under the two definitions
differ.
- **`liability` gained required members**: `verification_fund`, `cap` and
`restitution_basis`, and the contract gained required `assurance` and
`release` members. An -00 contract does not validate against the -01 schema,
which is intended.
- **The CFB, Bid and agent capability examples moved to `examples/legacy-00/`**,
since -01 does not define those objects. They are kept so the published -00
stays checkable and are not part of the conformance surface.

New objects with schemas and examples: Delivery, Verdict, and the facilitator
capability document served at `/.well-known/pact-facilitator`.
3 changes: 2 additions & 1 deletion tools/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
instrument is committed from inside the TaskSpec as well as by the
CFB and the VTC.
5. bid.commitment equals sha256(JCS(bid-reveal.reveal)).
6. attestation.vtc_hash equals sha256(JCS(vtc without signatures)).
6. vtc_hash in Delivery, Verdict, Challenge and Attestation equals
sha256(JCS(vtc)) with the signatures member included (-01 Section 6).
7. Rules the schemas cannot express: parties are distinct, one
signature per named party, and every JOSE protected header carries
alg, kid and typ with an allowed algorithm.
Expand Down
Loading