Skip to content

ceavinrufus/agentpassport

Repository files navigation

agentpassport

agentpassport logo

PyPI npm License: Apache 2.0 CI

The authorization layer for multi-agent AI systems. Like IAM, but for your agent graph.


The Problem

Agents are delegating to other agents. Nobody's checking the chain.

When Agent A delegates to Agent B, and Agent B delegates to Agent C — how do you know what C was actually authorized to do? Right now, every major framework (LangGraph, CrewAI, AutoGen) answers this question with: trust by convention. No signed proof. No scope enforcement. No way to revoke mid-flight.

That's not authorization. That's hope.

[Python Orchestrator] signs delegation → [TypeScript Agent] verifies before executing
         ↓
    ScopeError: requires [write:db:customers], granted [read:db:customers]  ✅

agentpassport gives every agent a cryptographic identity, signs delegation at every hop, and enforces scope before the handler runs. Revoke a token by JTI and the agent stops cleanly — no process kill, no partial state.

Demo

Cross-SDK trust chain — Python orchestrator delegates to TypeScript agent:

git clone https://github.com/ceavinrufus/agentpassport
cd agentpassport
uv run python -m demo.run_demo
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  agentpassport DEMO — Cross-SDK Trust Chain
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  Orchestrator  did:key:z6MkskpV…pks2  (Python)
  TS Agent      did:key:z6MkoFDL…3TZf  (TypeScript)

[STEP 1] Python signs delegation JWT
  scope  ['read:db:customers']  ttl 3600s

[STEP 2] Python → TS: queryCustomers → 200 ✅
  Auth chain verified, capability executed

[STEP 3] Python → TS: writeCustomer → 403 🛡️
  ScopeError: requires [write:db:customers], granted [read:db:customers]

[STEP 4] Python revokes delegation mid-scenario
  jti revoked → same request fails → 403 🛡️

[STEP 5] Auth chain trace
  hop 0  jti=d77dd09a…  ✅
    iss  z6MkskpV…  (orchestrator)
    sub  z6MkoFDL…  (ts-agent)
    scope  ['read:db:customers']
    exp  2026-05-12T10:22:48Z
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Ownership binding — domain + wallet binding, offline verification, revocation:

uv run python -m demo.binding_demo
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  agentpassport — Ownership Binding Demo
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[STEP 1] Generate agent identity
  DID:               did:key:z6Mkv4kj…
  ✅  Agent identity created

[STEP 2] Bind agent to domain 'agentpassport.fyi'
  ✅  Domain binding created

[STEP 3] Bind agent to Ethereum wallet
  ✅  Wallet binding created

[STEP 4] Assemble binding document
  Document (publish at https://agentpassport.fyi/.well-known/agent-passport.json)

[STEP 5] Verify signatures offline
  ✅  Domain binding signature valid
  ✅  Wallet binding signature valid
  ✅  Tampered signature correctly rejected
  ✅  Expired binding correctly rejected

[STEP 6] Revoke wallet binding
  ✅  Wallet binding is now revoked
  ✅  Domain binding unaffected by wallet revocation

[STEP 7] Final document state
  binding  type=domain [active]
  binding  type=wallet [REVOKED]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Verify domain ownership — live

agentpassport.fyi publishes its own /.well-known/agent-passport.json — you can verify it right now:

$ agentpass identity verify-domain \
    --did did:key:z6Mkh8UwkN88kwynM3mYke8yFXr9ax69jZKv2TCuwG7yPzbw \
    --domain agentpassport.fyi

Output:

Checking https://agentpassport.fyi/.well-known/agent-passport.json ...
✓ Valid domain binding: 'agentpassport.fyi' claims did:key:z6Mkh8UwkN88kwynM3mYke8yFXr9ax69jZKv2TCuwG7yPzbw

Install

# Python
pip install agentpassport

# TypeScript / JavaScript
npm install @agentpassport/core

Why agentpassport?

Problem Without agentpassport With agentpassport
Agent authorization Trust by convention Cryptographic proof
Scope enforcement Ad-hoc checks Declared + verified before execution
Revocation Kill the process Soft-stop by JTI, mid-flight safe
Cross-language Custom per integration Wire-compatible out of the box

How It Works

1. Cryptographic Identity

Every agent has an Ed25519 keypair. Its public key becomes a W3C-standard did:key: DID — no central registry, verifiable by anyone.

from agentpassport import Agent

agent = Agent("my-agent")
print(agent.did)  # did:key:z6Mk...

2. Signed Delegation (Auth Chain)

Trust flows through a chain of signed JWTs. Each hop narrows scope — an agent can never grant more than it has.

from agentpassport import sign_delegation, verify_auth_chain

# Root signs initial grant
token = sign_delegation(
    issuer_private_key=root_priv,
    issuer_did=root_did,
    subject_did=agent.did,
    scope=["read:db:customers"],
    ttl_seconds=3600,
)

# Receiving agent verifies before acting
verify_auth_chain(
    auth_chain=[token],
    expected_subject=agent.did,
    known_public_keys={root_did: root_pub},
)

3. Pre-execution Scope Declaration

Capabilities declare what scope they need. agentpassport checks before the handler runs — fail fast, no partial state.

@agent.capability("query_customers", requires=["read:db:customers"])
async def handle(task: TaskEnvelope) -> dict:
    # Only reached if auth chain grants read:db:customers
    return {"customers": [...]}

4. Revocation

Revoke a delegation by JTI without stopping in-flight work — the agent completes its current action and stops before the next.

from agentpassport import InMemoryRevocationRegistry, SqliteRevocationRegistry

registry = SqliteRevocationRegistry("revocations.db")
registry.revoke(jti)  # all future requests with this token fail

TypeScript SDK

Wire-compatible with Python — cross-language trust chains work out of the box.

import { Agent, InMemoryRevocationRegistry, ScopeError } from "@agentpassport/core"

const agent = new Agent("ts-agent", { privateKey, revocationRegistry })
agent.trustKeys({ [orchestratorDid]: orchestratorPublicKey })

agent.capability("queryCustomers", { requires: ["read:db:customers"] }, async (task) => {
  return { customers: [...] }
})

A Python orchestrator can sign a delegation JWT. A TypeScript agent can verify it. No shared infrastructure needed.

Scope Format

Scopes are action:resource pairs:

["read:db:customers", "write:api:stripe", "send:email:notifications"]

Both parts together make authorization provable. Action-only ("read") is too loose. Resource-only ("db:customers") is incomplete.

Install

pip install agentpassport          # Python SDK
pip install agentpassport[otel]    # + OpenTelemetry sink
cd packages/agentpassport-ts && npm install  # TypeScript SDK

Packages

Package Description
agentpassport PyPI Python trust and authorization layer
@agentpassport/core npm TypeScript SDK (wire-compatible)
agentpassport-registry PyPI Trusted agent registry with signature verification
agentpassport-adapters PyPI MCP, REST, and A2A adapters
agentpassport-cli PyPI CLI — keygen, trace viewer

CLI

# Generate a keypair and DID
agentpass identity keygen --alias myagent

# Inspect an auth chain from a trace
agentpass trace show --id trace_abc --file traces.jsonl

Ownership Binding

Agents can prove real-world ownership by publishing a signed binding document at /.well-known/agent-passport.json.

from agentpassport import (
    generate_keypair, did_from_public_key,
    bind_domain, bind_wallet, BindingDocument,
    verify_binding_attestation,
)

priv, pub = generate_keypair()
did = did_from_public_key(pub)

# Create bindings
domain_binding = bind_domain(priv[:32], did, "agentpassport.fyi")
wallet_binding = bind_wallet(priv[:32], did, "ethereum", "0xYourAddress")

# Assemble and publish
doc = BindingDocument(version="1")
doc.add(domain_binding)
doc.add(wallet_binding)
print(doc.to_json())  # publish at https://agentpassport.fyi/.well-known/agent-passport.json

# Verify offline
ok = verify_binding_attestation(domain_binding)  # True

Or use the CLI:

agentpass identity bind-domain --alias myagent --domain agentpassport.fyi --output ap.json
agentpass identity bind-wallet --alias myagent --chain ethereum --address 0x... --output ap.json
agentpass identity verify-domain --did <DID> --domain agentpassport.fyi

See the Ownership Binding guide for the full flow.

Roadmap

Feature Status
Authorization layer Cryptographic agent identity (did:key:) ✅ Done
Signed delegation chain (JWT) ✅ Done
Scope enforcement + revocation ✅ Done
Python SDK ✅ Done
TypeScript SDK ✅ Done
Cross-language wire compatibility ✅ Done
MCP middleware adapter ✅ Done
A2A protocol adapter (inbound + outbound) ✅ Done
AI Passport Identity revocation ✅ Done
Domain ownership binding ✅ Done
Wallet ownership binding (chain-agnostic) ✅ Done
Decentralized agent discovery 🔜 Planned
Merkle tree revocation (scalable, on-chain ready) 🔜 Planned
Human-readable ownership declaration 🔜 Planned

Development

uv sync --all-packages
uv run pytest                          # Python tests (173)
cd packages/agentpassport-ts && npm test     # TypeScript tests (48)
uv run python -m tests.cross-sdk.generate_fixtures && \
  cd tests/cross-sdk && npx tsx generate_ts_fixtures.ts  # cross-SDK fixtures

Contributing

PRs welcome. See CONTRIBUTING.md for guidelines.

License

Apache-2.0

About

The AI passport layer — cryptographic identity and authorization for AI agents

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors