Metadata-Version: 2.4
Name: vexis-sdk
Version: 0.0.1
Summary: Python SDK for Vexis — cryptographic identity and trust infrastructure for AI agents
License-Expression: MIT
Keywords: agents,ai,cryptography,identity,passport,sdk,trust
Requires-Python: >=3.9
Requires-Dist: httpx>=0.25.0
Requires-Dist: typing-extensions>=4.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Description-Content-Type: text/markdown

# vexis-sdk

Python SDK for [Vexis](https://vexis-api.vexis.workers.dev) — cryptographic identity and trust infrastructure for AI agents.

Agents get passports (signed credentials), receiving systems verify them, and every interaction feeds a trust graph that scores agent reputation over time.

## Installation

```bash
pip install vexis-sdk
```

Requires Python 3.9+ and `httpx`.

## Quick Start

```python
from vexis import Vexis

client = Vexis(api_key="your-api-key")

# Issue a passport for your AI agent
passport = client.issue(
    agent_name="my-agent",
    agent_type="worker",
    capabilities=[{"name": "data:read", "scope": "org"}],
    ttl=3600,  # 1 hour
)
token = passport["token"]
passport_id = passport["id"]

# Verify a passport (no auth required — call this on the receiving side)
result = client.verify(token=token)
if result["valid"]:
    print(f"Agent: {result['agentName']}, Trust score: {result['trustScore']}")
else:
    print(f"Invalid: {result['reason']}")

# Attest an interaction
client.attest(
    passport_id=passport_id,
    action="data:read",
    target_system="crm",
    outcome="success",
    duration_ms=120,
)
```

## Async Usage

```python
import asyncio
from vexis import AsyncVexis

async def main():
    async with AsyncVexis(api_key="your-api-key") as client:
        passport = await client.issue(
            agent_name="my-agent",
            agent_type="worker",
            capabilities=[{"name": "data:read", "scope": "org"}],
        )
        result = await client.verify(token=passport["token"])
        print(result)

asyncio.run(main())
```

## Context Manager

Both `Vexis` and `AsyncVexis` support context managers that automatically close the underlying HTTP connection:

```python
with Vexis(api_key="your-api-key") as client:
    passport = client.issue(...)
```

## API Reference

### `Vexis(api_key, base_url?)`

Constructor. Raises `ValueError` if `api_key` is empty.

- `api_key` — your Vexis API key (required)
- `base_url` — API base URL (default: `https://vexis-api.vexis.workers.dev`)

### `issue(*, agent_name, agent_type, capabilities, ttl?, bound_to?, metadata?)`

Issue a new passport for an AI agent. Returns passport data including `id` and `token`.

### `verify(*, token, required_capabilities?, bound_to?)`

Verify a passport token. Does **not** require authentication — call this on the receiving side.

Returns `{"valid": True, ...}` or `{"valid": False, "reason": "...", ...}`.

### `attest(*, passport_id, action, target_system, outcome, target_org?, duration_ms?)`

Record an interaction taken by an agent. `outcome` is one of `"success"`, `"failure"`, `"partial"`, `"denied"`.

### `revoke(passport_id, reason?)`

Revoke a passport by ID.

### `bulk_revoke(agent_type?, reason?)`

Revoke all passports, optionally filtered by agent type.

### `lookup(passport_id, *, limit?, offset?, since?)`

Look up a passport with its trust score, attestations, and verification history.

### `trust(*, org_id?, agent_name?, agent_type?, target_org_id?)`

Query trust scores. Pass `agent_name` + `agent_type` for agent trust, `org_id` alone for org trust, `org_id` + `target_org_id` for relationship trust.

### `close()`

Close the underlying HTTP client. Called automatically when using as a context manager.

## Error Handling

```python
from vexis import VexisApiError

try:
    client.lookup("nonexistent-passport-id")
except VexisApiError as e:
    print(e.code)        # e.g. "PASSPORT_NOT_FOUND"
    print(e.message)     # human-readable message with hint
    print(e.http_status) # HTTP status code (0 for network errors)
    print(e.details)     # additional error details, if any
```

Common error codes: `INVALID_API_KEY`, `RATE_LIMITED`, `PASSPORT_NOT_FOUND`, `NETWORK_ERROR`.
