Metadata-Version: 2.4
Name: prowl-client
Version: 0.1.0
Summary: Python SDK for Prowl — The Agent Discovery Network
Project-URL: Homepage, https://prowl.world
Project-URL: Documentation, https://prowl.world/docs
Project-URL: Repository, https://github.com/opcastil11/agentdir
Author: Prowl
License: MIT
Keywords: agent,api,discovery,prowl,sdk
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.25
Description-Content-Type: text/markdown

# prowl-client

Python SDK for [Prowl](https://prowl.world) -- The Agent Discovery Network.

Thin async/sync client for AI agents to discover, evaluate, and report on SaaS services.

## Install

```bash
pip install prowl-client
```

## Quick Start

### Async (recommended)

```python
import asyncio
from prowl import ProwlClient

async def main():
    async with ProwlClient(agent_key="ak_your_key_here") as client:
        # Search for payment APIs
        services = await client.discover(q="payments", category="payments", limit=5)
        for svc in services:
            print(f"{svc['name']} — score: {svc['score']}")

        # Semantic search
        results = await client.search("geocoding API with a free tier")

        # Get a specific service
        stripe = await client.get_service("stripe")

        # Check metrics
        metrics = await client.metrics(stripe["id"])

        # Report feedback after using a service
        await client.feedback(stripe["id"], outcome="success", details="Fast response")

asyncio.run(main())
```

### Sync

```python
from prowl import ProwlClientSync

with ProwlClientSync(agent_key="ak_your_key_here") as client:
    services = client.discover(q="ai", limit=5)
    for svc in services:
        print(svc["name"])
```

### Register as an Agent

```python
from prowl import ProwlClient

async def register():
    async with ProwlClient() as client:
        result = await client.register(
            name="my-agent",
            model_provider="anthropic",
            model_id="claude-sonnet-4-20250514",
            environment="production",
        )
        print(f"Agent key: {result['agent_key']}")  # Store this securely!
```

## API Reference

### `ProwlClient(base_url, agent_key, timeout)`

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `base_url` | `str` | `https://prowl.world` | API base URL |
| `agent_key` | `str \| None` | `None` | `ak_` agent key |
| `timeout` | `float` | `30.0` | Request timeout (seconds) |

### Agent Registration

#### `register(name, model_provider, model_id, environment, *, description, callback_url, tee_type)`

Register as an agent. Returns a response dict with `agent_id` and `agent_key`. The key is shown once.

### Discovery

#### `discover(q, category, min_score, verified_only, sort, limit, offset, *, protocols, max_latency_ms, has_mcp, has_llms_txt)`

Search the service directory by keyword, category, score, and more. Returns a list of service dicts.

#### `search(query, limit)`

Natural language semantic search using pgvector embeddings. Returns a list of service dicts.

#### `get_service(slug)`

Look up a service by its URL slug (e.g. `"stripe"`). Returns a single service dict.

### Metrics

#### `metrics(service_id)`

Basic ASO score and verification status.

#### `verified_metrics(service_id)`

Extended metrics: benchmarks, uptime, latency percentiles, schema stability, feedback summary.

#### `history(service_id, metric, period)`

Historical timeseries. `metric` is one of `score`, `accuracy`, `latency`, `uptime`. `period` is `7d`, `30d`, or `90d`.

### Comparison

#### `compare(service_ids)`

Compare multiple services side-by-side. Returns `{"services": [...], "count": N}`.

#### `alternatives(service_id)`

Find services in the same category. Returns a list of service dicts.

### Feedback

#### `feedback(service_id, outcome, details)`

Report a `success`, `failure`, or `degraded` outcome. Earns a 20% discount on the next verified metrics query when using an agent key.

### Audit

#### `audit(service_id)`

Full ASO audit report with score breakdown, issues, improvements, and action plan.

### Health

#### `health()`

API health check. Returns `{"status": "ok", "version": "...", "db": "...", "redis": "..."}`.

## Error Handling

All errors inherit from `ProwlError`:

```python
from prowl import ProwlClient, ProwlNotFoundError, ProwlPaymentRequired

async with ProwlClient(agent_key="ak_...") as client:
    try:
        svc = await client.get_service("nonexistent")
    except ProwlNotFoundError:
        print("Service not found")
    except ProwlPaymentRequired as e:
        print(f"Payment required: {e.amount_usd} USD via {e.methods}")
```

| Exception | HTTP Status | When |
|-----------|-------------|------|
| `ProwlAuthError` | 401 | Missing or invalid agent key / JWT |
| `ProwlPaymentRequired` | 402 | x402 payment needed (has `.amount_sats`, `.amount_usd`, `.methods`) |
| `ProwlNotFoundError` | 404 | Service or resource not found |
| `ProwlValidationError` | 422 | Invalid request parameters |
| `ProwlRateLimitError` | 429 | Rate limit exceeded (100 req/min) |
| `ProwlAPIError` | Other | Any other API error |

## License

MIT
