Catalog PyPI
PACKAGE EXPLORERView in registry

agent-mandates

PyPI

Who authorized an AI agent to act, whether it stayed inside those bounds, and what it cost when it did not.

agentic-commerceai-agentsaudit-traildelegationed25519rfc8785verifiable-credentials
Versions collected1
Direct dependencies7From release 0.1.0
Last observed20 Oct, 22:39 UTC

README

Version 0.1.0 documentation

agent-mandates

PyPI CI Python License

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.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.023 Sept 20267

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
oluwatemmy/agent-mandates

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 22:39 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:232485dd68f0bb05d3121ab51cd98f576fdbb6f6ef4f135189d1f6fc8e40bb81