FastAPI middleware for verifying agent requests using the Agentis identity platform
Project description
agentis-verify
agentis-verify is a Python middleware package for FastAPI that verifies incoming agent requests against the Agentis identity platform. When an agent makes an HTTP request signed with proveyouragent, this library fetches the agent's public key and verification metadata from Agentis, validates the DPoP signature on the request, and either passes the request through with verified agent details attached, or rejects it with a clear error response. It handles caching of agent lookups, configurable verification tier requirements, and per-capability access control.
Install
pip install agentis-verify
Quickstart
a. Middleware for all routes
Apply AgentisMiddleware once and every route is protected automatically. The verified agent is available at request.state.agent.
from fastapi import FastAPI, Request
from agentis_verify import AgentisMiddleware, AgentisConfig
app = FastAPI()
app.add_middleware(
AgentisMiddleware,
config=AgentisConfig(min_verification_tier=2),
exclude_paths=["/health", "/docs", "/openapi.json"],
)
@app.get("/invoices")
async def list_invoices(request: Request):
agent = request.state.agent
return {"agent": agent.verified_name, "invoices": []}
b. verify_agent() per route
Use verify_agent() when you need per-route control or want to check a specific capability inline.
from fastapi import FastAPI, Request
from agentis_verify import verify_agent
app = FastAPI()
@app.get("/invoices")
async def list_invoices(request: Request):
agent = await verify_agent(request)
return {"agent": agent.verified_name, "invoices": []}
@app.post("/payments")
async def process_payment(request: Request):
agent = await verify_agent(request, required_capability="payments:write")
return {"processed_by": agent.did}
c. @require_capability() decorator
Protect a route with a single decorator. Returns 403 if the agent lacks the capability, 401 if verification fails.
from fastapi import FastAPI, Request
from agentis_verify import require_capability
app = FastAPI()
@app.get("/payments")
@require_capability("payments:write")
async def process_payment(request: Request):
agent = request.state.agent
return {"processed_by": agent.did}
Capabilities
Capabilities are returned as strings for agents registered directly, and as structured objects for agents registered with an A2A Agent Card. agentis-verify handles both formats transparently.
# plain string format (direct registration)
agent.capabilities # ["invoices:read", "payments:write"]
# structured object format (A2A Agent Card registration)
agent.capabilities # [{"id": "invoices:read", "description": "Read and list invoices"}]
# use has_capability() to check either format
agent.has_capability("invoices:read") # True in both cases
Configuration
AgentisConfig controls how the middleware behaves:
| Option | Default | Description |
|---|---|---|
base_url |
"https://agentis-id.vercel.app" |
Base URL of the Agentis API |
cache_ttl_seconds |
60 |
How long to cache agent lookups |
timeout_seconds |
10 |
HTTP timeout for Agentis API calls |
min_verification_tier |
1 |
Minimum verification tier required |
from agentis_verify import AgentisConfig
config = AgentisConfig(
base_url="https://agentis-id.vercel.app",
cache_ttl_seconds=120,
timeout_seconds=5,
min_verification_tier=2,
)
Error handling
| Exception | HTTP status | Meaning |
|---|---|---|
AgentisVerificationError |
401 (or 403 for capability) | Verification failed. The reason attribute describes what went wrong. |
AgentisUnavailableError |
503 | The Agentis API could not be reached. |
When using the middleware, these are caught automatically and returned as JSON:
{"detail": "Agent is not active (status: suspended)"}
When calling verify_agent() directly, catch them yourself:
from agentis_verify import AgentisVerificationError, AgentisUnavailableError
try:
agent = await verify_agent(request)
except AgentisVerificationError as e:
# e.reason has the message, e.status_code is 401 or 403
raise HTTPException(status_code=e.status_code, detail=e.reason)
except AgentisUnavailableError:
raise HTTPException(status_code=503, detail="Identity service unavailable")
How it connects to proveyouragent and Agentis
Agents register on Agentis and receive an Ed25519 keypair and a DID (did:web:agentis.dev:agents:abc123). When making HTTP requests, they use proveyouragent to attach two headers:
X-Agent-Statement: a JWT software statement containing the agent's DIDX-Agent-DPoP: a DPoP proof binding the request to the agent's key
agentis-verify extracts the DID from the statement, fetches the agent's public key from the Agentis API at GET /api/agents/[did], checks that the agent is active and meets the minimum verification tier, then calls proveyouragent.verify_agent_request() to validate the DPoP proof against the public key. If everything passes, the verified agent is attached to request.state.agent and the request proceeds.
Links
- Agentis platform: https://agentis-id.vercel.app
- Agentis source: https://github.com/lujainkhalil/Agentis
- proveyouragent on PyPI: https://pypi.org/project/proveyouragent
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentis_verify-0.1.0.tar.gz.
File metadata
- Download URL: agentis_verify-0.1.0.tar.gz
- Upload date:
- Size: 7.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1e2f6b08d0ec02a3d299445d1f3a2d8e1ddc3b8248f24b79c67d7307a31de6c
|
|
| MD5 |
effd3f4ad646078b9c4a4e2b3ca253d8
|
|
| BLAKE2b-256 |
0f2a9a33362357192b1e76952527a34f9cd4af884e757b6517e4d36e83758669
|
File details
Details for the file agentis_verify-0.1.0-py3-none-any.whl.
File metadata
- Download URL: agentis_verify-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f1fee51eb226fdc778680b1365b8c3cd0d7dafe122ebbd94d78b3d91025fa1e6
|
|
| MD5 |
9c06663e785881c14d601901e335a345
|
|
| BLAKE2b-256 |
a46853125fb824ef8b4b1066d89184f354d5a19a33e3687c42d691be1cbdfc7e
|