Agreements as evidence, including when the parties are agents.
CAP is an open format and verification protocol for agreements between two
parties. Its artifacts are byte-exact: the terms are unsigned canonical JSON, and the other four
artifacts are signed compact JWS. From them anyone can check what the
two parties agreed, which revision governed a given instant, and whether a signed action named
the revision that governed when it happened, with no central service and without CAP making the call for you.
CAP verifies. It never authorizes.
Each one is a set of bytes you can hand to anyone, and anyone can verify it from those bytes alone.
Artifact
Form
Carries
Party Descriptor
signed JWS (cap+party)
a party’s key history (Ed25519 keys, and ML-DSA keys from protocol revision 3); each change is signed by the previous active key, and a branch in the history is kept as fork evidence
Charter Revision
unsigned canonical JSON
the proposed terms, which become agreed when both parties accept them: the two parties and their roles, the legal-text digest, precedence, the effective window, the termination reasons and exact ABP deployment bindings
Acceptance
signed JWS (cap+acceptance)
one party’s signed assent to the exact revision bytes; a revision is accepted when both parties have signed one
Termination Notice
signed JWS (cap+termination)
a signed notice that closes the charter from its effective instant, when it names the revision governing at that instant
Receipt
signed JWS (cap+receipt)
the issuing party’s signed claim about one action, bound to exact revision coordinates, the deployment digest and a grant reference (a bap reference carries its digest; a host reference may omit it)
What it proves, and what it leaves to you
CAP returns facts about the bytes and a fixed list of things it did not check. Your
application reads the facts and makes every business call itself.
Use CAP for
agreement evidence that two independent parties exchange as bytes and either can re-verify
agent commerce, where one or both parties are software agents
supplier terms, with proof of which revision governed an action
key-history continuity, including post-quantum key rotation
action receipts that anyone can re-verify offline
Do not use CAP for
deciding whether an action is allowed: CAP never authorizes
live revocation checks
evaluating terms: CAP reports term_satisfaction as not verified
legal adjudication
single-party self-attestation
Why the evidence holds
Byte-exact by construction.
Two systems each hold a “version 2”, and nobody can settle the dispute from the bytes.
Strict unpadded base64url, deterministic tagged decoding,
RFC 8785 canonicalization and domain-separated SHA-256. An acceptance binds the exact revision bytes.
Contested views stay contested.
A tool that quietly picks one of two signed branches hides the dispute it found.
When one signer signs two branches, CAP keeps both
as signed evidence and picks no winner. A new revision accepted by both parties repairs the fork when it descends from or supersedes every competing branch.
Two implementations, no shared code.
One implementation checking itself says little about the specification.
A 541-case conformance corpus runs through the Elixir
verifier and an independent, builtins-only TypeScript verifier. A CAP release requires byte-identical reports from both.
The family lifecycle
Three protocols, three kinds of evidence: what the agent is, what the parties agreed, and what each call carried.
Agree the termsCharter revisions bind ABP release digests (abp_bindings); each receipt names the action’s deployment digest and is signed by the issuing party
One protocol in four repositories, in Elixir and TypeScript. The bytes are the same in both
languages, and the TypeScript sites carry live demos.
The protocol · this repository
The Elixir reference implementation: the verifier, the conformance corpus, the specification
and the guides, including the security model’s table of what CAP proves and what it never proves.
Produces signed artifacts in Elixir through a caller-owned key handle ({module, term()});
the TypeScript signer follows its design. Runtime dependencies: this protocol package and telemetry.