Metadata-Version: 2.4
Name: agent-authority
Version: 0.1.2
Summary: Authorization for AI agents: verifiable, scoped, revocable capability tokens (mandates) with attenuable delegation, for MCP and A2A. The reference implementation of agent authority — zero-dependency TypeScript & Python.
Project-URL: Homepage, https://github.com/novaai0401-ui/agent-authority
Project-URL: Repository, https://github.com/novaai0401-ui/agent-authority
Project-URL: Issues, https://github.com/novaai0401-ui/agent-authority/issues
License: MIT
Keywords: a2a,agent,agent-authority,agentic,ai-agents,authority,authorization,biscuit,capability,capability-based-security,capability-tokens,delegation,ed25519,least-privilege,llm,macaroons,mandate,mcp,oauth,on-behalf-of,permissions,revocation,spiffe
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Provides-Extra: fast
Requires-Dist: cryptography>=41; extra == 'fast'
Provides-Extra: seal
Requires-Dist: cryptography>=41; extra == 'seal'
Description-Content-Type: text/markdown

# agent-authority (Python)

**Authorization for AI agents** — the reference implementation of **agent
authority** (project name: *Behalf*). Verifiable, scoped, time-bound, revocable
**capability tokens** (mandates) with attenuable, macaroon/biscuit-style
**delegation**, plus MCP and agent-to-agent (A2A) middleware. Capability-based
security, OAuth 2.1 on-behalf-of–style grants, and SPIFFE/SVID-style agent
identity for multi-agent / LLM systems.

Identical API shape to the TypeScript library, **zero dependencies** (standard
library only). The optional `cryptography` extra enables a constant-time Ed25519
backend and sealed credentials:

```bash
pip install agent-authority          # core, dependency-free
pip install "agent-authority[seal]"  # + sealed credentials / hardened crypto
```

## In plain words

Think of a **Mandate** as a **permission slip** for an AI agent.

Imagine you hire an assistant to run errands for you. You don't hand over your
wallet and house keys — you write a note: *"You may read my calendar and spend
up to $50, and only for the next hour."* That note is a Mandate.

The five verbs are just the things you can do with that note:

- **grant** — *write the permission slip.* "This agent may do X, up to this
  limit, until this time."
- **authorize** — *check the slip before acting.* The agent must show the slip
  (and prove it's really theirs) before it's allowed to do something.
- **attenuate** — *make a smaller copy for a helper.* A sub-agent can only get
  the same powers or fewer — never more.
- **revoke** — *tear the slip up.* Cancel it instantly; every copy handed
  downstream stops working too.
- **audit** — *the logbook.* Every check is written down, so you can see exactly
  what happened.

Two things make the slip safe: it **can't be faked or upgraded** (it's signed
with cryptography, and a helper can only shrink the powers), and **holding the
paper isn't enough** — an agent must *prove* it's the rightful holder, so a
stolen copy by itself is useless.

The rest of this page shows how to do each of these in code.

## The five verbs

```python
from agent_authority import create_behalf

b = create_behalf()

# 1. GRANT
mandate = b.grant(
    principal="alice",
    agent="research-agent",
    can=["read:calendar", "spend:usd<=50"],
    expires_in="1h",
)

# 2. AUTHORIZE — raises AuthorizationError if denied
mandate.authorize("spend:usd=20")

# 3. ATTENUATE — narrow for a sub-agent; can only shrink
child = mandate.attenuate(can=["read:calendar"], expires_in="10m")

# 4. REVOKE — kills the mandate and its downstream chain
b.revoke(mandate.id)

# 5. AUDIT — every authorize() wrote a hash-chained record
trail = b.audit(mandate.id)
```

## MCP / A2A middleware

```python
from agent_authority.mcp import with_behalf

server = with_behalf(
    my_tool_server,  # exposes call_tool(name, args, ctx=None)
    policy={
        "send_email": "write:email",
        "read_calendar": "read:calendar",
        "transfer_funds": lambda args: f"spend:usd<={args['amount']}",
    },
    on_denied="throw",  # or "prompt" with on_prompt=...
)

# Pass the caller's mandate on the context:
server.call_tool("read_calendar", {}, {"mandate": mandate})
```

`agent_authority.mcp.behalf_mcp_tools()` returns the three discovery tools
(`request_mandate`, `present_mandate`, `check_authority`).

## Develop

```bash
python3 -m unittest discover -s tests   # 28 tests
```
