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, 5-factor biometric-verified 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": [...], "verified_human": av.human_name}

# 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 biometric verification (email, phone, cross-verification, Face ID / Touch ID, 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
human_name str | None Pro plan only
five_factor "y" | "n" | None Pro plan only
age_over_18 "y" | "n" | "null" | None Pro plan only
age_over_21 "y" | "n" | "null" | None Pro plan only
multiple_agents_authorized "y" | "n" | None Pro plan only
verifications_today int | None Pro plan only
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.0.tar.gz (9.9 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.0-py3-none-any.whl (10.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: agentvisa_fastapi-0.1.0.tar.gz
  • Upload date:
  • Size: 9.9 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.0.tar.gz
Algorithm Hash digest
SHA256 a816c0f81b0732cfcf6846bd328e36ac764678ab63c4865948041087693580f9
MD5 c35b57f6368680733b54287ae43befe1
BLAKE2b-256 84f11e548c2abe9be23115d98d3b15ad4c6ec189ef963a985e88592ec3f14cf4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for agentvisa_fastapi-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4a0160c52631f32bbd7e71336e9c1381418e714b1d74b4391322fcb881fdb83b
MD5 9ba18ab5ecd383ded08c4c5508909d5e
BLAKE2b-256 242e58639fe2f16a97fcea23ca828ccff12dba81b3d26f115535b29588fd3fe7

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