agent-mandates
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:
- Mandate — signed by a principal, granting one named agent a scope, a ceiling and an expiry. An agent may pass authority on, but only narrowed: a delegated grant can never widen what it received.
- Action receipt — signed by the agent when it acts, bound by hash to the mandate it acted under.
- Outcome attestation — signed later and bound by hash to that receipt. What actually happened: completed, disputed, refunded, reversed, and any loss.
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.
Install
pip install agent-mandates
Python 3.11+. Depends on pydantic and cryptography, nothing else.
Issue a grant, act under it, attest the outcome
# 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.
Verify
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.
What it does not do
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 format
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.
Development
python -m pip install -e ".[dev]"
python -m pytest
Contributions welcome — see CONTRIBUTING.md. Security reports: SECURITY.md.
License
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.
Metadata
Release files for agent-mandates 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| agent_mandates-0.1.0.tar.gz | 70.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agent_mandates-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 102.8 kB
Release files / agent_mandates-0.1.0.tar.gz
| Download URL | agent_mandates-0.1.0.tar.gz |
|---|---|
| Size | 70.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
aab57ca798287c18576d8ad5785f8defdcb3cf5f1df9ecb181a5830e94ad1c7c
|
|
BLAKE2b-256 checksum How to use checksums |
4f65fb4bb82bf901df27a10cdb0da7242a29dde045152b61bf5ad09d95c77283
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.
Transparency logRelease files / agent_mandates-0.1.0-py3-none-any.whl
| Download URL | agent_mandates-0.1.0-py3-none-any.whl |
|---|---|
| Size | 32.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1998113badf9240e095e656f63360471deb6a024f3c27c33d4598994a129c05c
|
|
BLAKE2b-256 checksum How to use checksums |
f380408bfc0e0ffb5a3668f35c624e99de491528c8035e96c6dd12e0fde78c67
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.
Transparency log