Skip to main content

Python SDK for the Modei REST API — manage agent passports, gates, and enforcement policies.

Project description

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

modei_python-1.0.0.tar.gz (23.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

modei_python-1.0.0-py3-none-any.whl (19.9 kB view details)

Uploaded Python 3

File details

Details for the file modei_python-1.0.0.tar.gz.

File metadata

  • Download URL: modei_python-1.0.0.tar.gz
  • Upload date:
  • Size: 23.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for modei_python-1.0.0.tar.gz
Algorithm Hash digest
SHA256 2a00742a1b4325f67c4e27372d36a34acdc74069d4eea15b2826ecb9cefae916
MD5 fdef35775a5334e3c3299a8bdc3562aa
BLAKE2b-256 6579d7435728e9988368fcb2e2a4f440a902476bac56c19807a1e3705499ed10

See more details on using hashes here.

File details

Details for the file modei_python-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: modei_python-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 19.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for modei_python-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b6f5eb560c699fcaa3af71423565e566bea3140b59c9e0e664ef5fce70b93696
MD5 9b843318bfca33062d695e76b0aa8bc2
BLAKE2b-256 78a130dfe593736ed21f6df42e5374bdae75ca327dd844d8a88728f0c3e8f80f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page