aporthq-sdk-python


Nameaporthq-sdk-python JSON
Version 0.1.0 PyPI version JSON
download
home_pageNone
SummaryPython SDK for The Passport for AI Agents
upload_time2025-10-26 02:27:32
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords agent-passport ai authentication verification aport mcp middleware
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Agent Passport Python SDK

A production-grade thin Python SDK for The Passport for AI Agents, providing easy integration with agent authentication and policy verification via API calls. All policy logic, counters, and enforcement happen on the server side.

## Features

- ✅ **Thin Client Architecture** - No policy logic, no Cloudflare imports, no counters
- ✅ **Production Ready** - Timeouts, retries, proper error handling, Server-Timing support
- ✅ **Type Safe** - Full type hints with comprehensive type definitions
- ✅ **Idempotency Support** - Both header and body idempotency key support
- ✅ **Local Token Validation** - JWKS support for local decision token validation
- ✅ **Multiple Environments** - Production, sandbox, and self-hosted enterprise support
- ✅ **Async/Await** - Modern async Python with aiohttp
- ✅ **Context Manager** - Proper resource management with async context managers

## Installation

```bash
pip install aporthq-sdk-python
```

**Requirements:** Python 3.8 or higher

## Quick Start

```python
import asyncio
from aporthq_sdk_python import APortClient, APortClientOptions, PolicyVerifier, AportError

async def main():
    # Initialize client for production
    client = APortClient(APortClientOptions(
        base_url="https://api.aport.io",  # Production API
        api_key="your-api-key",  # Optional
        timeout_ms=800  # Optional: Request timeout (default: 800ms)
    ))

    # Or for sandbox/testing
    sandbox_client = APortClient(APortClientOptions(
        base_url="https://sandbox-api.aport.io",  # Sandbox API
        api_key="your-sandbox-key"
    ))

    # Or for self-hosted enterprise
    enterprise_client = APortClient(APortClientOptions(
        base_url="https://your-company.aport.io",  # Your self-hosted instance
        api_key="your-enterprise-key"
    ))

    # Create a policy verifier for convenience
    verifier = PolicyVerifier(client)

    # Verify a refund policy with proper error handling
    try:
        decision = await verifier.verify_refund(
            "your-agent-id",
            {
                "amount": 1000,
                "currency": "USD",
                "order_id": "order_123",
                "reason": "defective"
            },
            "unique-key-123"  # idempotency key
        )

        if decision.allow:
            print("✅ Refund approved!")
            print(f"Decision ID: {decision.decision_id}")
            print(f"Assurance Level: {decision.assurance_level}")
        else:
            print("❌ Refund denied!")
            for reason in decision.reasons or []:
                print(f"  - [{reason.get('severity', 'info')}] {reason['code']}: {reason['message']}")
    except AportError as error:
        print(f"API Error {error.status}: {error}")
        print(f"Reasons: {error.reasons}")
        print(f"Decision ID: {error.decision_id}")
    except Exception as error:
        print(f"Policy verification failed: {error}")

if __name__ == "__main__":
    asyncio.run(main())
```

## Environments

The SDK supports different environments through the `base_url` parameter:

- **Production**: `https://api.aport.io` - The main APort API
- **Sandbox**: `https://sandbox-api.aport.io` - Testing environment with mock data
- **Self-hosted**: `https://your-domain.com` - Your own APort instance

You can also host your own APort service for complete control over policy verification and data privacy.

## API Reference

### `APortClient`

The core client for interacting with the APort API endpoints.

#### `__init__(options: APortClientOptions)`
Initializes the APort client.
- `options.base_url` (str): The base URL of your APort API (e.g., `https://api.aport.io`).
- `options.api_key` (str, optional): Your API Key for authenticated requests.
- `options.timeout_ms` (int, optional): Request timeout in milliseconds (default: 800ms).

#### `async verify_policy(agent_id: str, policy_id: str, context: Dict[str, Any] = None, idempotency_key: str = None) -> PolicyVerificationResponse`
Verifies a policy against an agent by calling the `/api/verify/policy/:pack_id` endpoint.
- `agent_id` (str): The ID of the agent.
- `policy_id` (str): The ID of the policy pack (e.g., `finance.payment.refund.v1`, `code.release.publish.v1`).
- `context` (Dict[str, Any], optional): The policy-specific context data.
- `idempotency_key` (str, optional): An optional idempotency key for the request.

#### `async get_decision_token(agent_id: str, policy_id: str, context: Dict[str, Any] = None) -> str`
Retrieves a short-lived decision token for near-zero latency local validation. Calls `/api/verify/token/:pack_id`.

#### `async validate_decision_token(token: str) -> PolicyVerificationResponse`
Validates a decision token via server (for debugging). Calls `/api/verify/token/validate`.

#### `async validate_decision_token_local(token: str) -> PolicyVerificationResponse`
Validates a decision token locally using JWKS (recommended for production). Falls back to server validation if JWKS unavailable.

#### `async get_passport_view(agent_id: str) -> Dict[str, Any]`
Retrieves a small, cacheable view of an agent's passport (limits, assurance, status) for display purposes (e.g., about pages, debugging). Calls `/api/passports/:id/verify_view`.

#### `async get_jwks() -> Jwks`
Retrieves the JSON Web Key Set for local token validation. Cached for 5 minutes.

### `PolicyVerifier`

A convenience class that wraps `APortClient` to provide policy-specific verification methods.

#### `__init__(client: APortClient)`
Initializes the PolicyVerifier with an `APortClient` instance.

#### `async verify_refund(agent_id: str, context: Dict[str, Any], idempotency_key: str = None) -> PolicyVerificationResponse`
Verifies the `finance.payment.refund.v1` policy.

#### `async verify_repository(agent_id: str, context: Dict[str, Any], idempotency_key: str = None) -> PolicyVerificationResponse`
Verifies the `code.repository.merge.v1` policy.

#### Additional Policy Methods
The `PolicyVerifier` also includes convenience methods for other policies:
- `verify_release()` - Verifies the `code.release.publish.v1` policy
- `verify_data_export()` - Verifies the `data.export.create.v1` policy  
- `verify_messaging()` - Verifies the `messaging.message.send.v1` policy

These methods follow the same pattern as `verify_refund()` and `verify_repository()`.

## Error Handling

The SDK raises `AportError` for API request failures with detailed error information.

```python
from aporthq_sdk_python import AportError

try:
    await client.verify_policy("invalid-agent", "finance.payment.refund.v1", {})
except AportError as error:
    print(f"Status: {error.status}")
    print(f"Message: {error}")
    print(f"Reasons: {error.reasons}")
    print(f"Decision ID: {error.decision_id}")
    print(f"Server Timing: {error.server_timing}")
except Exception as error:
    print(f"Unexpected error: {error}")
```

### Error Types

- **`AportError`**: API request failures with status codes, reasons, and decision IDs
- **Timeout Errors**: 408 status with `TIMEOUT` reason code
- **Network Errors**: 0 status with `NETWORK_ERROR` reason code

## Production Features

### Idempotency Support
The SDK supports idempotency keys in both the request body and the `Idempotency-Key` header (header takes precedence).

```python
decision = await client.verify_policy(
    "agent-123",
    "finance.payment.refund.v1",
    {"amount": 100, "currency": "USD"},
    "unique-idempotency-key"  # Sent in both header and body
)
```

### Server-Timing Support
The SDK automatically captures and exposes Server-Timing headers for performance monitoring.

```python
decision = await client.verify_policy("agent-123", "finance.payment.refund.v1", {})
print("Server timing:", decision._meta.get("serverTiming"))
# Example: "cache;dur=5,db;dur=12"
```

### Local Token Validation
For high-performance scenarios, use local token validation with JWKS:

```python
# Get JWKS (cached for 5 minutes)
jwks = await client.get_jwks()

# Validate token locally (no server round-trip)
decision = await client.validate_decision_token_local(token)
```

### Async Context Manager
Use the client as an async context manager for proper resource management:

```python
async with APortClient(options) as client:
    decision = await client.verify_policy("agent-123", "finance.payment.refund.v1", {})
    # Session is automatically closed
```

### Timeout and Retry Configuration
Configure timeouts and retry behavior:

```python
client = APortClient(APortClientOptions(
    base_url="https://api.aport.io",
    api_key="your-key",
    timeout_ms=500  # 500ms timeout
))
```

## Type Hints

The SDK includes full type hints for all classes, methods, and types.

```python
from aporthq_sdk_python import APortClient, APortClientOptions, PolicyVerificationResponse

options: APortClientOptions = APortClientOptions(
    base_url='https://api.aport.io',
    api_key='my-secret-key',
    timeout_ms=800
)

client: APortClient = APortClient(options)

decision: PolicyVerificationResponse = await client.verify_policy(
    "agent_123", 
    "finance.payment.refund.v1", 
    {"amount": 500, "currency": "EUR"}
)
```

## License

MIT

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "aporthq-sdk-python",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "agent-passport, ai, authentication, verification, aport, mcp, middleware",
    "author": null,
    "author_email": "APort Team <team@aport.io>",
    "download_url": "https://files.pythonhosted.org/packages/63/45/befea352c8c014bd79149624137de753cac5819d45c4008448ef85c8ef9b/aporthq_sdk_python-0.1.0.tar.gz",
    "platform": null,
    "description": "# Agent Passport Python SDK\n\nA production-grade thin Python SDK for The Passport for AI Agents, providing easy integration with agent authentication and policy verification via API calls. All policy logic, counters, and enforcement happen on the server side.\n\n## Features\n\n- \u2705 **Thin Client Architecture** - No policy logic, no Cloudflare imports, no counters\n- \u2705 **Production Ready** - Timeouts, retries, proper error handling, Server-Timing support\n- \u2705 **Type Safe** - Full type hints with comprehensive type definitions\n- \u2705 **Idempotency Support** - Both header and body idempotency key support\n- \u2705 **Local Token Validation** - JWKS support for local decision token validation\n- \u2705 **Multiple Environments** - Production, sandbox, and self-hosted enterprise support\n- \u2705 **Async/Await** - Modern async Python with aiohttp\n- \u2705 **Context Manager** - Proper resource management with async context managers\n\n## Installation\n\n```bash\npip install aporthq-sdk-python\n```\n\n**Requirements:** Python 3.8 or higher\n\n## Quick Start\n\n```python\nimport asyncio\nfrom aporthq_sdk_python import APortClient, APortClientOptions, PolicyVerifier, AportError\n\nasync def main():\n    # Initialize client for production\n    client = APortClient(APortClientOptions(\n        base_url=\"https://api.aport.io\",  # Production API\n        api_key=\"your-api-key\",  # Optional\n        timeout_ms=800  # Optional: Request timeout (default: 800ms)\n    ))\n\n    # Or for sandbox/testing\n    sandbox_client = APortClient(APortClientOptions(\n        base_url=\"https://sandbox-api.aport.io\",  # Sandbox API\n        api_key=\"your-sandbox-key\"\n    ))\n\n    # Or for self-hosted enterprise\n    enterprise_client = APortClient(APortClientOptions(\n        base_url=\"https://your-company.aport.io\",  # Your self-hosted instance\n        api_key=\"your-enterprise-key\"\n    ))\n\n    # Create a policy verifier for convenience\n    verifier = PolicyVerifier(client)\n\n    # Verify a refund policy with proper error handling\n    try:\n        decision = await verifier.verify_refund(\n            \"your-agent-id\",\n            {\n                \"amount\": 1000,\n                \"currency\": \"USD\",\n                \"order_id\": \"order_123\",\n                \"reason\": \"defective\"\n            },\n            \"unique-key-123\"  # idempotency key\n        )\n\n        if decision.allow:\n            print(\"\u2705 Refund approved!\")\n            print(f\"Decision ID: {decision.decision_id}\")\n            print(f\"Assurance Level: {decision.assurance_level}\")\n        else:\n            print(\"\u274c Refund denied!\")\n            for reason in decision.reasons or []:\n                print(f\"  - [{reason.get('severity', 'info')}] {reason['code']}: {reason['message']}\")\n    except AportError as error:\n        print(f\"API Error {error.status}: {error}\")\n        print(f\"Reasons: {error.reasons}\")\n        print(f\"Decision ID: {error.decision_id}\")\n    except Exception as error:\n        print(f\"Policy verification failed: {error}\")\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\n## Environments\n\nThe SDK supports different environments through the `base_url` parameter:\n\n- **Production**: `https://api.aport.io` - The main APort API\n- **Sandbox**: `https://sandbox-api.aport.io` - Testing environment with mock data\n- **Self-hosted**: `https://your-domain.com` - Your own APort instance\n\nYou can also host your own APort service for complete control over policy verification and data privacy.\n\n## API Reference\n\n### `APortClient`\n\nThe core client for interacting with the APort API endpoints.\n\n#### `__init__(options: APortClientOptions)`\nInitializes the APort client.\n- `options.base_url` (str): The base URL of your APort API (e.g., `https://api.aport.io`).\n- `options.api_key` (str, optional): Your API Key for authenticated requests.\n- `options.timeout_ms` (int, optional): Request timeout in milliseconds (default: 800ms).\n\n#### `async verify_policy(agent_id: str, policy_id: str, context: Dict[str, Any] = None, idempotency_key: str = None) -> PolicyVerificationResponse`\nVerifies a policy against an agent by calling the `/api/verify/policy/:pack_id` endpoint.\n- `agent_id` (str): The ID of the agent.\n- `policy_id` (str): The ID of the policy pack (e.g., `finance.payment.refund.v1`, `code.release.publish.v1`).\n- `context` (Dict[str, Any], optional): The policy-specific context data.\n- `idempotency_key` (str, optional): An optional idempotency key for the request.\n\n#### `async get_decision_token(agent_id: str, policy_id: str, context: Dict[str, Any] = None) -> str`\nRetrieves a short-lived decision token for near-zero latency local validation. Calls `/api/verify/token/:pack_id`.\n\n#### `async validate_decision_token(token: str) -> PolicyVerificationResponse`\nValidates a decision token via server (for debugging). Calls `/api/verify/token/validate`.\n\n#### `async validate_decision_token_local(token: str) -> PolicyVerificationResponse`\nValidates a decision token locally using JWKS (recommended for production). Falls back to server validation if JWKS unavailable.\n\n#### `async get_passport_view(agent_id: str) -> Dict[str, Any]`\nRetrieves a small, cacheable view of an agent's passport (limits, assurance, status) for display purposes (e.g., about pages, debugging). Calls `/api/passports/:id/verify_view`.\n\n#### `async get_jwks() -> Jwks`\nRetrieves the JSON Web Key Set for local token validation. Cached for 5 minutes.\n\n### `PolicyVerifier`\n\nA convenience class that wraps `APortClient` to provide policy-specific verification methods.\n\n#### `__init__(client: APortClient)`\nInitializes the PolicyVerifier with an `APortClient` instance.\n\n#### `async verify_refund(agent_id: str, context: Dict[str, Any], idempotency_key: str = None) -> PolicyVerificationResponse`\nVerifies the `finance.payment.refund.v1` policy.\n\n#### `async verify_repository(agent_id: str, context: Dict[str, Any], idempotency_key: str = None) -> PolicyVerificationResponse`\nVerifies the `code.repository.merge.v1` policy.\n\n#### Additional Policy Methods\nThe `PolicyVerifier` also includes convenience methods for other policies:\n- `verify_release()` - Verifies the `code.release.publish.v1` policy\n- `verify_data_export()` - Verifies the `data.export.create.v1` policy  \n- `verify_messaging()` - Verifies the `messaging.message.send.v1` policy\n\nThese methods follow the same pattern as `verify_refund()` and `verify_repository()`.\n\n## Error Handling\n\nThe SDK raises `AportError` for API request failures with detailed error information.\n\n```python\nfrom aporthq_sdk_python import AportError\n\ntry:\n    await client.verify_policy(\"invalid-agent\", \"finance.payment.refund.v1\", {})\nexcept AportError as error:\n    print(f\"Status: {error.status}\")\n    print(f\"Message: {error}\")\n    print(f\"Reasons: {error.reasons}\")\n    print(f\"Decision ID: {error.decision_id}\")\n    print(f\"Server Timing: {error.server_timing}\")\nexcept Exception as error:\n    print(f\"Unexpected error: {error}\")\n```\n\n### Error Types\n\n- **`AportError`**: API request failures with status codes, reasons, and decision IDs\n- **Timeout Errors**: 408 status with `TIMEOUT` reason code\n- **Network Errors**: 0 status with `NETWORK_ERROR` reason code\n\n## Production Features\n\n### Idempotency Support\nThe SDK supports idempotency keys in both the request body and the `Idempotency-Key` header (header takes precedence).\n\n```python\ndecision = await client.verify_policy(\n    \"agent-123\",\n    \"finance.payment.refund.v1\",\n    {\"amount\": 100, \"currency\": \"USD\"},\n    \"unique-idempotency-key\"  # Sent in both header and body\n)\n```\n\n### Server-Timing Support\nThe SDK automatically captures and exposes Server-Timing headers for performance monitoring.\n\n```python\ndecision = await client.verify_policy(\"agent-123\", \"finance.payment.refund.v1\", {})\nprint(\"Server timing:\", decision._meta.get(\"serverTiming\"))\n# Example: \"cache;dur=5,db;dur=12\"\n```\n\n### Local Token Validation\nFor high-performance scenarios, use local token validation with JWKS:\n\n```python\n# Get JWKS (cached for 5 minutes)\njwks = await client.get_jwks()\n\n# Validate token locally (no server round-trip)\ndecision = await client.validate_decision_token_local(token)\n```\n\n### Async Context Manager\nUse the client as an async context manager for proper resource management:\n\n```python\nasync with APortClient(options) as client:\n    decision = await client.verify_policy(\"agent-123\", \"finance.payment.refund.v1\", {})\n    # Session is automatically closed\n```\n\n### Timeout and Retry Configuration\nConfigure timeouts and retry behavior:\n\n```python\nclient = APortClient(APortClientOptions(\n    base_url=\"https://api.aport.io\",\n    api_key=\"your-key\",\n    timeout_ms=500  # 500ms timeout\n))\n```\n\n## Type Hints\n\nThe SDK includes full type hints for all classes, methods, and types.\n\n```python\nfrom aporthq_sdk_python import APortClient, APortClientOptions, PolicyVerificationResponse\n\noptions: APortClientOptions = APortClientOptions(\n    base_url='https://api.aport.io',\n    api_key='my-secret-key',\n    timeout_ms=800\n)\n\nclient: APortClient = APortClient(options)\n\ndecision: PolicyVerificationResponse = await client.verify_policy(\n    \"agent_123\", \n    \"finance.payment.refund.v1\", \n    {\"amount\": 500, \"currency\": \"EUR\"}\n)\n```\n\n## License\n\nMIT\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python SDK for The Passport for AI Agents",
    "version": "0.1.0",
    "project_urls": {
        "Documentation": "https://aport.io/docs",
        "Homepage": "https://aport.io",
        "Issues": "https://github.com/aporthq/agent-passport/issues",
        "Repository": "https://github.com/aporthq/agent-passport"
    },
    "split_keywords": [
        "agent-passport",
        " ai",
        " authentication",
        " verification",
        " aport",
        " mcp",
        " middleware"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "0851825318dde8fa1a1a1eda9f44fa206401926c3af51b95f272ba2824e048ae",
                "md5": "c55a63f22601157ec3f91853b872a6d6",
                "sha256": "d6b032d0d9457784389cbbc5fe79279c1a94a8634d523c44a713c5a9e1570c25"
            },
            "downloads": -1,
            "filename": "aporthq_sdk_python-0.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "c55a63f22601157ec3f91853b872a6d6",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 11439,
            "upload_time": "2025-10-26T02:27:30",
            "upload_time_iso_8601": "2025-10-26T02:27:30.663900Z",
            "url": "https://files.pythonhosted.org/packages/08/51/825318dde8fa1a1a1eda9f44fa206401926c3af51b95f272ba2824e048ae/aporthq_sdk_python-0.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "6345befea352c8c014bd79149624137de753cac5819d45c4008448ef85c8ef9b",
                "md5": "42a718c6b26813551e39284bc433bd62",
                "sha256": "9fc368b664f4c51767a552a1d1739edbc6ad16451efdff3759c625ff85f39bd3"
            },
            "downloads": -1,
            "filename": "aporthq_sdk_python-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "42a718c6b26813551e39284bc433bd62",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 14483,
            "upload_time": "2025-10-26T02:27:32",
            "upload_time_iso_8601": "2025-10-26T02:27:32.005955Z",
            "url": "https://files.pythonhosted.org/packages/63/45/befea352c8c014bd79149624137de753cac5819d45c4008448ef85c8ef9b/aporthq_sdk_python-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-26 02:27:32",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "aporthq",
    "github_project": "agent-passport",
    "github_not_found": true,
    "lcname": "aporthq-sdk-python"
}
        
Elapsed time: 1.73982s