HTTPS proves a site. Code signing proves software. AgentPass proves an agent.
Free Ed25519 identity keys, a public key directory, and one-call verification for any website.
Pick a handle, get an Ed25519 key pair and a key ID. Your public key is published in the directory instantly.
Your agent adds three headers to each HTTP request: Signature-Agent, Signature-Input, Signature. SDK: Python, PHP.
Any site checks the signature against the directory, locally or via one API call, and gets the agent's identity and track record.
/demoThe demo endpoint verifies the incoming request itself and answers 200 with your identity, or 401. Python SDK (needs pip install cryptography):
curl -sO https://agentpass.semalt.ai/sdk/agentpass_sign.py python3 agentpass_sign.py --key <SEED> --kid <KID> GET https://agentpass.semalt.ai/demo
Or from your own Python code:
from agentpass_sign import sign_headers
import requests
headers = sign_headers("GET", "https://example.com/page", SEED, KID)
requests.get("https://example.com/page", headers=headers)
PHP: agentpass.php · AgentPass\sign($ctx, $seed, $kid) / AgentPass\verify($ctx, AgentPass\directory_resolver())
Paste the request line and the three signature headers. The check runs against the live directory.
Two ways. Local (no external calls on the hot path, keys cached):
require 'agentpass.php';
$r = AgentPass\verify(AgentPass\ctx_from_server(), AgentPass\directory_resolver());
if ($r['ok']) { /* $r['kid'] identifies the agent; look it up at /api/v1/keys/{kid} */ }
else { /* unsigned or invalid: treat as anonymous traffic, rate-limit, or 401 */ }
Remote (any language, one POST):
POST https://agentpass.semalt.ai/api/v1/verify
{"method":"GET","authority":"example.com","path":"/page",
"headers":{"signature-agent":"...","signature-input":"...","signature":"..."}}
→ {"ok":true,"reason":"valid","agent":{"handle":"my-crawler","operator":"Acme Inc.","verified_ok":1234,...}}
Unsigned requests are not blocked by anything here. AgentPass only tells you who a signed request is from; the policy (allow, throttle, charge) stays yours.
| GET /.well-known/http-message-signatures-directory | JWKS with every active agent key. Response is signed with the AgentPass platform key (kid -x30YmeuqcJUy0mMdq7asmL59DnBk0akAY_Jdz8dQiM). |
|---|---|
| POST /api/v1/agents | Register. JSON or form: handle, name, kind, operator, homepage, contact_email, description, public_key (optional). Returns agent, owner_token and, if generated, the private key once. |
| GET /api/v1/agents[?q=&limit=&offset=] | List agents. |
| GET /api/v1/agents/{handle} | Agent card (identity, key, reputation counters). |
| GET /api/v1/keys/{kid} | Resolve a key ID to a key and its agent. Cacheable, 5 min. |
| POST /api/v1/verify | Verify Web Bot Auth headers for a request you received: method, authority (or url), path, query, headers{signature-agent, signature-input, signature}. |
| ANY /demo | Protected endpoint for testing your signer: 200 + identity, or 401. |
| GET /api/v1/stats | Counters. |
RFC 9421 HTTP Message Signatures, algorithm ed25519, tag web-bot-auth, covered components @method @authority @path signature-agent, parameters created expires keyid alg tag nonce. keyid is the RFC 7638 JWK thumbprint of the public key. Signatures expire in 5 minutes by default; the verifier requires @authority to be covered so a signature cannot be replayed against another host.