Observed since 20 Oct, 22:39 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Who authorized an AI agent to act, whether it stayed inside those bounds, and what it cost when it did not.
Who authorized an AI agent to do something, whether it stayed inside those bounds, and what it cost when it did not.
Three linked documents, each signed by the party actually making the claim:
Because a grant is signed by whoever granted it rather than whoever used it, a verifier checks an agent's authority against its principal instead of taking the agent's word for it. Verification needs only the published public keys, never access to the issuer.
pip install agent-mandates
Python 3.11+. Depends on pydantic and cryptography, nothing else.
# Alice grants her shopping agent authority to charge up to 200 USD.
mandate = Mandate(
id=new_mandate_id(),
issued_at=now,
principal=alice,
agent=shopper,
scope=("payment.charge",),
expires_at=now + timedelta(days=30),
max_value=Money(amount=Decimal("200.00"), currency="USD"),
)
# The agent charges 79.99. receipt_under commits to the grant by hash, so the
# binding cannot be mistyped.
receipt = receipt_under(
mandate,
action=Action(
type="payment.charge",
target="https://shop.example.com/v1/orders",
params_hash=...,
value=Money(amount=Decimal("79.99"), currency="USD"),
),
decision=Decision(outcome=DecisionOutcome.ALLOW),
issued_at=now + timedelta(minutes=2),
)
# Two days later the merchant attests what happened.
outcome = outcome_for(receipt, status=OutcomeStatus.COMPLETED, issued_at=now + timedelta(days=2))
envelope = sign(mandate, "alice", alice_key)
examples/walkthrough.py is the whole flow, runnable.
The test suite executes it, so it cannot drift from the library.
Anyone holding the published keys can check the chain:
$ mandates verify outcome.json --keys jwks.json \
--receipt receipt.json --mandate mandate.json
document outc_70744f1f3219436cb220f281817fee60 (outcome attestation)
status completed
signed by merchant
receipt rcpt_1614b59b188b4e8b8cffe7d14be710db signed by shopper
binding OK
mandate mndt_5533e1521b474eb5a62f310837f472a5 granted by alice
chain OK, answering to user:alice (human)
scope OK
result VERIFIED
Exit codes are 0 verified, 1 not verified, 2 bad input, so the three cases
can be told apart in a script. --require KEY_ID fails unless a particular key
signed. Repeat --mandate, root first, to check a delegation chain.
It verifies documents, not the world they describe. An agent signs its own account of what it did, and nothing here compares that account to reality. A receipt saying an agent charged 79.99 is evidence that the agent claimed that, under authority its principal did grant. It is not evidence the charge happened.
Key management is deliberately out of scope: generating, storing, rotating and revoking private keys is left to you.
The wire format is specified in FORMAT.md — canonicalization,
signing boundary, binding, attenuation — and pinned by golden vectors in
tests/vectors/, which carry fixed key seeds so an
implementation in another language can reproduce the same signature bytes.
Verified on Linux, macOS and Windows across Python 3.11, 3.12 and 3.13, which ship different Unicode tables and must still agree on canonical bytes.
python -m pip install -e ".[dev]"
python -m pytest
Contributions welcome — see CONTRIBUTING.md. Security reports: SECURITY.md.
Copyright 2026 Ajayi Oluwaseyi Temitope.
Apache-2.0 rather than MIT for its explicit patent grant: this format is meant to be implemented by other parties, who need assurance that no patent claim will be asserted over it later.
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.0 | 23 Sept 2026 | 7 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 22:39 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:232485dd68f0bb05d3121ab51cd98f576fdbb6f6ef4f135189d1f6fc8e40bb81