Metadata-Version: 2.4
Name: agentscore-gate
Version: 1.8.0
Summary: Trust-gating middleware for Python web frameworks using AgentScore
Project-URL: Homepage, https://agentscore.sh
Project-URL: Repository, https://github.com/agentscore/python-gate
Project-URL: Issues, https://github.com/agentscore/python-gate/issues
License-Expression: MIT
License-File: LICENSE
Keywords: agent,agentic-payments,agentscore,ai-agent,aiohttp,blockchain,django,erc-8004,fastapi,flask,gate,middleware,reputation,sanic,starlette,trust,wallet,x402
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: AsyncIO
Classifier: Framework :: Django
Classifier: Framework :: FastAPI
Classifier: Framework :: Flask
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.11
Requires-Dist: httpx<1.0.0,>=0.25.0
Provides-Extra: aiohttp
Requires-Dist: aiohttp>=3.8.0; extra == 'aiohttp'
Provides-Extra: django
Requires-Dist: django>=4.0; extra == 'django'
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.100.0; extra == 'fastapi'
Provides-Extra: flask
Requires-Dist: flask>=2.0.0; extra == 'flask'
Provides-Extra: sanic
Requires-Dist: sanic>=23.0.0; extra == 'sanic'
Provides-Extra: starlette
Requires-Dist: starlette>=0.27.0; extra == 'starlette'
Description-Content-Type: text/markdown

# agentscore-gate

[![PyPI version](https://img.shields.io/pypi/v/agentscore-gate.svg)](https://pypi.org/project/agentscore-gate/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

Identity-gating middleware for Python web frameworks using [AgentScore](https://agentscore.sh). Native adapters for FastAPI, Flask, Django, AIOHTTP, and Sanic; generic ASGI middleware for Starlette / Litestar / Quart.

## Install

```bash
pip install agentscore-gate
```

## Quick Start

### FastAPI (native `Depends()`)

```python
from fastapi import Depends, FastAPI
from agentscore_gate.fastapi import AgentScoreGate, get_assess_data

app = FastAPI()
gate = AgentScoreGate(api_key="as_live_...", require_kyc=True, min_age=21)

@app.post("/purchase", dependencies=[Depends(gate)])
async def purchase(assess = Depends(get_assess_data)):
    # `assess` is the raw /v1/assess response (or None if fail_open)
    ...
```

### Starlette / other ASGI (FastAPI users can use this too)

```python
from starlette.applications import Starlette
from agentscore_gate import AgentScoreGate

app = Starlette()
app.add_middleware(AgentScoreGate, api_key="as_live_...", require_kyc=True)
```

### Flask

```python
from flask import Flask
from agentscore_gate.flask import agentscore_gate

app = Flask(__name__)
agentscore_gate(app, api_key="as_live_...", require_kyc=True)
```

### Django

```python
# settings.py
MIDDLEWARE = ["agentscore_gate.django.AgentScoreMiddleware"]
AGENTSCORE_GATE = {
    "api_key": "as_live_...",
    "require_kyc": True,
}
```

### AIOHTTP

```python
from aiohttp import web
from agentscore_gate.aiohttp import agentscore_gate_middleware

app = web.Application()
app.middlewares.append(agentscore_gate_middleware(api_key="as_live_...", require_kyc=True))
```

### Sanic

```python
from sanic import Sanic
from agentscore_gate.sanic import agentscore_gate

app = Sanic("myapp")
agentscore_gate(app, api_key="as_live_...", require_kyc=True)
```

## Options

| Parameter | Type | Default | Description |
|---|---|---|---|
| `api_key` | `str` | *required* | API key |
| `require_kyc` | `bool` | `None` | Require KYC verification |
| `require_sanctions_clear` | `bool` | `None` | Require clean sanctions status |
| `min_age` | `int` | `None` | Minimum age bracket (18 or 21) |
| `blocked_jurisdictions` | `list[str]` | `None` | ISO country codes to block |
| `allowed_jurisdictions` | `list[str]` | `None` | ISO country codes to allow |
| `fail_open` | `bool` | `False` | Allow requests when API unreachable |
| `cache_seconds` | `int` | `300` | Cache TTL |
| `user_agent` | `str` | `None` | Prepended to the default `User-Agent` as `"{user_agent} (agentscore-gate/{version})"`. Use to attribute API calls to your app. |
| `extract_identity` | `callable` | Reads headers | Custom identity extractor |
| `create_session_on_missing` | `CreateSessionOnMissing` | `None` | Auto-create verification session when no identity is found (all adapters) |

## Identity

Checks `X-Operator-Token` first, then `X-Wallet-Address`:

```python
from agentscore_gate import AgentIdentity

app.add_middleware(
    AgentScoreGate,
    api_key="as_live_...",
    extract_identity=lambda req: AgentIdentity(
        operator_token=req.headers.get("x-operator-token"),
        address=req.headers.get("x-wallet-address"),
    ),
)
```

### Auto-Create Session

Works on every adapter (ASGI, FastAPI, Flask, Django, AIOHTTP, Sanic).

```python
from agentscore_gate.sessions import CreateSessionOnMissing

app.add_middleware(
    AgentScoreGate,
    api_key="as_live_...",
    create_session_on_missing=CreateSessionOnMissing(api_key="as_live_..."),
)
# 403 includes: verify_url, session_id, poll_secret, poll_url, agent_instructions
```

### Per-request hooks

For per-product session context or pre-session side effects (e.g. pre-creating a pending order):

```python
async def wine_name(request):
    body = await request.json()
    product = await lookup_product(body["product_id"])
    return {"product_name": product.name}

async def create_pending(request, session):
    body = await request.json()
    order_id = await db.insert_pending_order(body["product_id"], session["session_id"])
    return {"order_id": order_id}  # merged into DenialReason.extra → surfaces in the 403 body

create_session_on_missing=CreateSessionOnMissing(
    api_key="as_live_...",
    get_session_options=wine_name,
    on_before_session=create_pending,
)
```

Hooks can be sync or `async def`. Flask and Django (sync adapters) accept only sync hooks — async hooks are skipped with a warning.

## Capture the wallet after payment

After a successful payment, report the signer wallet back to AgentScore so it can build a cross-merchant credential↔wallet profile. Each adapter exposes a `capture_wallet` helper that reads the operator_token the gate already extracted.

### FastAPI (native `Depends()`)

```python
from fastapi import Depends, Request
from agentscore_gate.fastapi import AgentScoreGate, capture_wallet, get_assess_data

@app.post("/purchase", dependencies=[Depends(gate)])
async def purchase(request: Request, assess = Depends(get_assess_data)):
    # ... run payment, recover signer wallet from the payload ...
    await capture_wallet(request, signer, "evm", idempotency_key=payment_intent_id)
    return {"ok": True}
```

### Starlette / other ASGI

```python
from agentscore_gate.middleware import capture_wallet

@app.post("/purchase")
async def purchase(request: Request):
    await capture_wallet(request, signer, "evm", idempotency_key=payment_intent_id)
    return {"ok": True}
```

### Flask

```python
from agentscore_gate.flask import capture_wallet

@app.post("/purchase")
def purchase():
    capture_wallet(signer, "evm", idempotency_key=payment_intent_id)
    return {"ok": True}
```

### Django

```python
from agentscore_gate.django import capture_wallet

def purchase(request):
    capture_wallet(request, signer, "evm", idempotency_key=payment_intent_id)
    return JsonResponse({"ok": True})
```

### AIOHTTP

```python
from agentscore_gate.aiohttp import capture_wallet

async def purchase(request):
    await capture_wallet(request, signer, "evm", idempotency_key=payment_intent_id)
    return web.json_response({"ok": True})
```

### Sanic

```python
from agentscore_gate.sanic import capture_wallet

@app.post("/purchase")
async def purchase(request):
    await capture_wallet(request, signer, "evm", idempotency_key=payment_intent_id)
    return response.json({"ok": True})
```

Fire-and-forget by design: silently no-ops if the request was wallet-authenticated (no operator_token), the gate didn't run, or the API call fails. `idempotency_key` (payment intent id, tx hash, …) prevents agent retries of the same payment from inflating `transaction_count` server-side.

## Documentation

- [API Reference](https://docs.agentscore.sh)

## License

[MIT](LICENSE)
