PACT Passport — agent ID. Self-certifying identity, holder-bound capabilities, audit receipts.
Project description
PACT Passport
The agent ID.
Self-certifying identity, holder-bound capabilities, and unilateral audit receipts for agent-to-agent systems. Two message types — REQ and RES. Everything else is built at the edges.
Status: v0.2.0 — security hardening complete. The three critical authorization-bypass paths (issues #2, #3, #8) tracked in v0.1.x are now closed. Remaining v0.2 issues are durability and operational hardening. Suitable for use within a single trust domain (your own machines on a LAN). Production deployment across trust boundaries should still wait until issue #4 (rotation) and #5 (durable idempotency) land.
Breaking changes vs v0.1.x:
holder_proofis now mandatory whencap_idis present (issue #3)- REQs from unknown peers are rejected unless they include an inline
identity_docfor trust-on-first-use (issue #2)verify_capabilityfails closed when delegation chain keys are missing (issue #8)
What is PACT Passport?
If MCP and A2A are how agents talk, PACT Passport is how they prove who they are. Each agent gets a self-certifying identity (Ed25519 keypair, agent_id derived from the public key). Authority is granted via holder-bound capability tokens that can only be tightened down a delegation chain, never widened. Every exchange produces signed audit receipts on both sides — independently verifiable, no central registry required.
PACT (Protocol for Agent Capability and Trust) sits below orchestration protocols like MCP and A2A as the trust substrate — the layer where identity is self-certifying, authority is holder-bound and attenuable, ordering is causal, and failure is explicit.
Three Primitives
-
Agent Identity — Ed25519 keypair with self-certifying agent ID and pre-rotation key commitment. Identity survives key rotation without a central registry.
-
Capability Token — Signed, holder-bound proof of authority with delegation chains. Caveats can only restrict, never expand. Stolen tokens are useless without the holder's private key.
-
Message — Two types: REQ (request with capability proof) and RES (result or error). Message references form a causal DAG. Deadlines and idempotency keys are mandatory.
Plus: unilateral audit receipts — each agent signs their own view, no cooperation required.
Install
pip install pact-passport
Or directly from this repo:
pip install git+https://github.com/bene-art/pact-passport.git
Optional extras:
pip install pact-passport[cbor] # CBOR encoding support
pip install pact-passport[fast] # Async uvicorn server
pip install pact-passport[lak] # local-agent-kit integration
The Python module is pact regardless of the distribution name — from pact import PACTAgent works either way.
Quick Start
CLI
# Terminal 1: Create and serve an agent
pact init alice
pact serve --agent alice --capabilities get_weather
# Terminal 2: Create another agent, discover, and ask
pact init bob
pact discover
pact ask alice get_weather '{"city": "Chicago"}'
pact receipts
Python API
from pact import PACTAgent
agent = PACTAgent("alice", capabilities=["get_weather"])
@agent.handle("get_weather")
def weather(payload):
return {"temp": 72, "condition": "clear"}
agent.serve()
Demo
python examples/demo.py
Runs two agents in-process, exchanges a capability-scoped task, and verifies receipts.
CLI Commands
| Command | Purpose |
|---|---|
pact init <name> |
Create agent identity with pre-rotation key commitment |
pact serve |
Start HTTP server + mDNS broadcast |
pact discover |
Find agents on local network |
pact ask <target> <action> [payload] |
Send a task (auto-handshake on first contact) |
pact grant <holder> <action> |
Issue a capability token |
pact revoke <cap_id> |
Revoke a capability |
pact caps |
List issued capabilities |
pact rotate |
Rotate keys using pre-rotation |
pact doctor |
Validate keys, event log, permissions |
pact trace <msg_id> |
Walk the causal message DAG |
pact receipts |
List audit receipts |
pact identity |
Show public identity document |
pact peers |
List known peers |
Architecture
crypto.py All PyNaCl in one file (post-quantum swap = one file change)
identity.py Ed25519 identity, agent_id, key event log, rotation
capability.py Token issue, attenuate, verify, delegation chains
message.py REQ/RES builder, signer, verifier
receipt.py Unilateral signed audit receipts
store.py Filesystem storage (~/.pact/)
transport/
server.py HTTP server with CBOR content negotiation
async_server.py Optional async server via uvicorn
client.py HTTP client with CBOR support
discovery.py mDNS via zeroconf
agent.py PACTAgent high-level API
cli.py `pact` command (13 subcommands)
contrib/
lak_channel.py local-agent-kit integration
Features by Phase
| Phase | Feature | Status |
|---|---|---|
| 1 | Identity, capabilities, REQ/RES, receipts, mDNS, CLI | Done |
| 2 | Capability attenuation (A→B→C), explicit grants, idempotency, DAG traversal | Done |
| 3 | Key rotation, rate limiting (max_invocations), pact doctor |
Done |
| 4 | Formal spec (spec/PACT_v1.md), deterministic test vectors, interop suite |
Done |
| 5 | CBOR encoding, async uvicorn server, local-agent-kit integration | Done |
Tests
pip install -e ".[dev,cbor,fast]"
pytest -v
118 tests + 1 documented xfail covering: crypto, identity, capabilities, attenuation, messages, receipts, storage, HTTP transport, CBOR content negotiation, async server, key rotation, rate limiting, doctor validation, test vector verification, two-agent integration, three-agent delegation chain, determinism, and 5 race-condition scenarios under concurrent dispatch.
Platform support
| Platform | Status |
|---|---|
| macOS (Darwin) | 131 passed |
| Linux (Alpine on WSL2) | 131 passed |
| Windows 11 | 127 passed, 4 skipped (POSIX-only checks) |
Rotation peer-cache-staleness (formerly tracked as the only xfail) was fixed in v0.3.1. See #4.
Concurrency stress mode
Set PACT_CHAOS=1 to inject random delays at race-prone code paths. Useful for catching idempotency / rate-limit races that would otherwise surface 1-in-1000:
PACT_CHAOS=1 pytest -v
Specification
- Concept document: docs/PACT_Specification.md
- Formal v1 spec: spec/PACT_v1.md — sufficient for independent implementation
- Test vectors: tests/vectors/pact_v1_vectors.json — deterministic, reproducible
- Case study (v0.1.3): docs/EXPERIMENTS.md — what 23 stress experiments found, including 5 real bugs in this implementation
Theoretical Foundations
| Paper | Contribution |
|---|---|
| Saltzer, Reed, Clark — End-to-End Arguments (1984) | Push verification to agents, not transport |
| Waldo et al. — A Note on Distributed Computing (1994) | Failure is explicit, never abstracted away |
| Lamport — Time, Clocks, and the Ordering of Events (1978) | Causal ordering via message DAG |
| Birgisson et al. — Macaroons (2014) | Attenuable, context-bound capability tokens |
| Smith — KERI (2019) | Self-certifying identity with pre-rotation |
| Miller — Robust Composition (2006) | Capability discipline, no ambient authority |
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pact_passport-0.3.1.tar.gz.
File metadata
- Download URL: pact_passport-0.3.1.tar.gz
- Upload date:
- Size: 48.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
400e7a8fe6210bc86e188c9b1c837a61aa510beb61bc1d02944d8ba280509226
|
|
| MD5 |
2339d1201de8b4a26e8d731d2ed09e18
|
|
| BLAKE2b-256 |
f4bf312d66611a11d1eb29601595bd504c2879437208d6d54e26019581d7eba6
|
File details
Details for the file pact_passport-0.3.1-py3-none-any.whl.
File metadata
- Download URL: pact_passport-0.3.1-py3-none-any.whl
- Upload date:
- Size: 40.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea581e905d928b8173411446f1b86b5cee65ea3ec76a1a2f3b76ef9930b5764f
|
|
| MD5 |
34ff19d0f920bcd380ec4ae50cb08b68
|
|
| BLAKE2b-256 |
367130bfe1b2d4da77773ebe03ce7c6cd8c78b0426e925b55230345e8d8ee592
|