Skip to main content

FastAPI middleware for AgentVisa AI agent verification

Project description

agentvisa-fastapi

FastAPI middleware for AgentVisa — verify that incoming AI agents were authorized by a real, biometrically authenticated human before granting access.

Install

pip install agentvisa-fastapi

Quick start

from fastapi import FastAPI, Depends
from agentvisa_fastapi import AgentVisaConfig, AgentVisaMiddleware, require_agentvisa

app = FastAPI()

config = AgentVisaConfig(
    api_key=os.environ["AGENTVISA_API_KEY"],   # your Widget Holder API key — server-side only
    widget_id=os.environ["AGENTVISA_WIDGET_ID"],  # from your AgentVisa dashboard
)

# Add middleware — enriches every request with request.state.agentvisa
app.add_middleware(AgentVisaMiddleware, config=config)

# Protected route — agents without a valid AgentVisa token get 401
@app.get("/api/orders")
async def get_orders(av=Depends(require_agentvisa(config))):
    return {"orders": [...], "plan": av.plan}

# Unprotected route — check manually if you want soft enforcement
@app.get("/api/public")
async def public(request: Request):
    av = request.state.agentvisa
    if av.valid:
        return {"message": "Hello, verified agent!", "plan": av.plan}
    return {"message": "Hello — consider getting an AgentVisa for full access."}

How it works

When an AI agent hits your site, AgentVisa requires a two-step handshake:

  1. Your server returns 401 with X-AgentVisa-Required: your_widget_id — this middleware does that automatically via require_agentvisa.
  2. The agent calls AgentVisa to get a short-lived TemporaryToken scoped to your site.
  3. The agent retries with X-AgentVisa-Token: tmp_... in the header.
  4. This middleware calls /v1/verify with your API key and returns the result.

The human behind the agent completed 5-factor verification (email, phone, cross-verification, biometric authentication, and a human assertion) when they got their AgentVisa.

Configuration

AgentVisaConfig(
    api_key="wk_...",            # required — your Widget Holder API key
    widget_id="wgt_...",         # required — your widget ID
    api_base="https://api.agentvisa.ai",  # optional — override for self-hosted
    timeout=5.0,                 # optional — /v1/verify timeout in seconds
)

Security note: Never expose api_key in client-side code, environment variables that get bundled, or logs. Treat it like a database password.

AgentVisaResult fields

Field Type Description
valid bool Whether the agent is verified
reason str "ok", "invalid", "expired", "revoked", "reverification_required", "token_not_present"
plan str "basic" or "pro"
widget_id str Your widget ID
verified_at datetime | None When the token was issued
expires_at datetime | None When the token expires
domain_verified bool | None Whether the widget's registered domain is verified
age_over_18 "y" | "n" | "null" | None Pro plan only — AVS-style flag, no raw DOB
age_over_21 "y" | "n" | "null" | None Pro plan only — AVS-style flag
multiple_agents_authorized "y" | "n" | None Pro plan only
web_bot_auth_bound bool | None Pro plan — token covered by RFC 9421 Signature-Input
skipped bool True when no token was in the request

Using without the middleware

If you don't want to add middleware, use the dependency standalone — it will call /v1/verify directly:

from agentvisa_fastapi import AgentVisaConfig, require_agentvisa

config = AgentVisaConfig(api_key="...", widget_id="...")

@app.post("/checkout")
async def checkout(av=Depends(require_agentvisa(config))):
    # verified agents only
    ...

Using get_agentvisa for soft enforcement

from agentvisa_fastapi import AgentVisaConfig, get_agentvisa, AgentVisaResult

config = AgentVisaConfig(api_key="...", widget_id="...")

@app.get("/search")
async def search(av: AgentVisaResult = Depends(get_agentvisa(config))):
    results = perform_search()
    if not av.valid:
        # Return limited results for unverified agents
        return {"results": results[:3], "note": "Get an AgentVisa for full results"}
    return {"results": results}

Reverification

When an agent's daily verification limit is hit, /v1/verify returns reason: "reverification_required". This middleware propagates that reason in the 401 response so your users know to check their email.

The require_agentvisa dependency returns:

HTTP 401
X-AgentVisa-Required: your_widget_id
{"detail": "AgentVisa reverification required — check email"}

The AgentVisa MCP server handles this automatically — it calls POST /v1/holder/reverify to trigger the re-verification email without the human needing to intervene.

License

MIT

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

agentvisa_fastapi-0.1.1.tar.gz (10.2 kB view details)

Uploaded Source

Built Distribution

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

agentvisa_fastapi-0.1.1-py3-none-any.whl (10.3 kB view details)

Uploaded Python 3

File details

Details for the file agentvisa_fastapi-0.1.1.tar.gz.

File metadata

  • Download URL: agentvisa_fastapi-0.1.1.tar.gz
  • Upload date:
  • Size: 10.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for agentvisa_fastapi-0.1.1.tar.gz
Algorithm Hash digest
SHA256 6f6b3be85dffb669af09a3577452a828bfacb2f6ac1cb3c46e5ce479345649c0
MD5 11703d87388fba8951040ff10c2d5fe2
BLAKE2b-256 0f6cdac50f9571d7fd4cb3afa189f8a6bc5169358ece1c01afdb009c8dcc10c6

See more details on using hashes here.

File details

Details for the file agentvisa_fastapi-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for agentvisa_fastapi-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b538255ad1f8cd8882cbbdc207736554e676f3dcaab1bf7ae70fb8804aec3d4b
MD5 6674b65f045748748564b6d570beca1e
BLAKE2b-256 a6bd283b6fa826c4430c7c0251ef2b2a7f1dc9bf5e8700000ca6ce8af2a840f0

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