Skip to main content

modei-python

PyPI version License: MIT

Python SDK for the Modei REST API. Manage agent passports, gates, and enforcement policies programmatically.

The MCP server (for Claude Desktop, Cursor, etc.) is the separate TypeScript package: modei-mcp on npm.


Installation

pip install modei-python

Usage

from modei import ModeiClient

client = ModeiClient(api_key="mod_live_xxx")

# List all gates
gates = client.list_gates()

# Create a gate
gate = client.create_gate(name="My API", gate_id="gate_my-api")

# Issue a passport
passport = client.issue_passport(
    "gate_my-api",
    agent_id="agent-001",
    permissions=["read", "write"],
    expires_in="7d",
)

# Check authorization
result = client.check_gate("gate_my-api", action="read", passport_id=passport["passport_id"])
print(result["allowed"])  # True

# Enforce with constraints
enforcement = client.enforce_action(
    passport_id=passport["passport_id"],
    action="write",
    cost_cents=500,
)
print(enforcement["decision"])  # "PERMIT"

client.close()

Async Usage

import asyncio
from modei import AsyncModeiClient

async def main():
    async with AsyncModeiClient(api_key="mod_live_xxx") as client:
        gates = await client.list_gates()
        for gate in gates:
            passports = await client.list_passports(gate["gate_id"])
            print(f"{gate['name']}: {len(passports)} passports")

asyncio.run(main())

Both clients support context managers for automatic cleanup:

with ModeiClient(api_key="mod_live_xxx") as client:
    gates = client.list_gates()

API Coverage

Gates

client.list_gates()
client.get_gate("gate_my-api")
client.create_gate(name="My API", gate_id="gate_my-api")
client.update_gate("gate_my-api", name="Updated Name")
client.delete_gate("gate_my-api")

Passports

client.list_passports("gate_my-api")
client.get_passport("gate_my-api", "pp_xxx")
client.issue_passport("gate_my-api", agent_id="agent-001", permissions=["read"])
client.revoke_passport("gate_my-api", "pp_xxx")
client.reissue_passport("pp_xxx", accept_catalog_version=2)

Attestations

client.list_attestations("gate_my-api", limit=50)
client.record_attestation("gate_my-api", passport_id="pp_xxx", permission="read", tool_name="search", result="allowed")

Permission Catalog

client.get_catalog("gate_my-api")
client.create_catalog("gate_my-api", permissions=[...])
client.publish_catalog("gate_my-api", change_summary="Added search permission")
client.list_catalog_versions("gate_my-api")
client.get_catalog_version("gate_my-api", version=1)
client.get_catalog_impact("gate_my-api")

Gate Check

client.check_gate("gate_my-api", action="read", passport_id="pp_xxx")
client.authorize_dry_run(gate_id="gate_my-api", passport={"..."}, requested_permission="read")

Constraints

client.get_constraints("pp_xxx")
client.set_constraints("pp_xxx", {"read": {"core:rate:max_per_minute": 100}})
client.list_constraint_types(category="cost")
client.list_constraint_templates(category="security")
client.apply_constraint_template("pp_xxx", "conservative-agent")
client.create_constraint_template(slug="my-template", name="My Template", constraints={...})

Enforcement (CEL)

client.enforce_action(passport_id="pp_xxx", action="write", cost_cents=500)
client.list_enforcement_attestations("pp_xxx", decision="BLOCK")
client.get_enforcement_attestation("enf_xxx")
client.verify_enforcement_attestation("enf_xxx")

Anonymous Access

client.get_anonymous_policy("gate_my-api")
client.set_anonymous_policy("gate_my-api", enabled=True, allowed_actions=["read"])
client.get_anonymous_log("gate_my-api")

Commerce

client.discover_services("flights:search", max_price_cents=100, sort="price_asc")
client.issue_consumption_attestation(passport_id="pp_xxx", gate_id="gate_my-api", action="flights:search", outcome="success")
client.generate_settlement(gate_id="gate_my-api", period_type="monthly", period_start="2025-01-01", period_end="2025-01-31")
client.list_settlements(gate_id="gate_my-api", status="pending")
client.get_settlement("stl_xxx")
client.update_settlement_status("stl_xxx", "invoiced")
client.get_sla_compliance("gate_my-api", period_start="2025-01-01", period_end="2025-01-31")

Cumulative State

client.get_cumulative_state("pp_xxx")
client.reset_cumulative_state("pp_xxx", window_type="daily")

API Keys

client.list_api_keys()
client.create_api_key(name="My Key", scopes=["gates:read", "passports:write"])
client.revoke_api_key("key_xxx")

Cryptographic Verification

Local verification utilities for Ed25519 signatures and RFC 8785 content hashing:

from modei import verify_attestation_signature, verify_content_hash, compute_content_hash

valid = verify_attestation_signature(
    attestation_json='{"gate_id":"gate_my-api",...}',
    signature_b64="base64-sig...",
    public_key_b64="base64-key...",
)

matches = verify_content_hash(catalog_snapshot, expected_hash)
hash_hex = compute_content_hash({"key": "value"})

Error Handling

from modei import (
    ModeiError,
    AuthenticationError,
    AuthorizationError,
    NotFoundError,
    RateLimitError,
    ValidationError,
    ConflictError,
)

try:
    client.get_gate("gate_nonexistent")
except NotFoundError as e:
    print(f"Not found: {e}")
    print(f"Status: {e.status_code}")  # 404
except RateLimitError as e:
    print(f"Rate limited, retry after: {e.retry_after}s")
except ModeiError as e:
    print(f"API error: {e} (HTTP {e.status_code})")
Exception HTTP Status
AuthenticationError 401
AuthorizationError 403
NotFoundError 404
ConflictError 409
ValidationError 400, 422
RateLimitError 429
ModeiError All other errors

Environment Variables

Variable Required Default Description
MODEI_API_KEY Yes — Your Modei API key
MODEI_API_URL No https://modei.ai API base URL (override for local dev)

You can also pass these directly to the client:

client = ModeiClient(api_key="mod_live_xxx", base_url="http://localhost:3000")

Documentation

Full documentation at modei.ai/docs


License

MIT — Standard Logic Co.

Metadata

Release files for modei-python 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for modei-python 1.0.0
File Size Uploaded
modei_python-1.0.0.tar.gz 23.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for modei-python 1.0.0
File Interpreter ABI Platform
modei_python-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 43.5 kB

Release files / modei_python-1.0.0.tar.gz

Download URL modei_python-1.0.0.tar.gz
Size 23.6 kB
Tags Source
SHA-256 checksum
How to use checksums
2a00742a1b4325f67c4e27372d36a34acdc74069d4eea15b2826ecb9cefae916
BLAKE2b-256 checksum
How to use checksums
6579d7435728e9988368fcb2e2a4f440a902476bac56c19807a1e3705499ed10
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.6

Release files / modei_python-1.0.0-py3-none-any.whl

Download URL modei_python-1.0.0-py3-none-any.whl
Size 19.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b6f5eb560c699fcaa3af71423565e566bea3140b59c9e0e664ef5fce70b93696
BLAKE2b-256 checksum
How to use checksums
78a130dfe593736ed21f6df42e5374bdae75ca327dd844d8a88728f0c3e8f80f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.6

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page