Sign requests with Web Bot Auth
Identify your agent with Ed25519 HTTP Message Signatures tagged web-bot-auth, register the key, and meet AgentGate's signature rules.
AgentGate verifies Web Bot Auth signatures: Ed25519 HTTP Message Signatures (RFC 9421) tagged web-bot-auth. A verified request is labelled agentgate:agent:verified:<name> and handled by the site's agent policy.
1. Get a key registered
agentgate keygen my-agent prints a private seed, the key's JWK thumbprint (the keyid) and an agents.json entry. There are two ways for a site to know your public key:
- Send it to the site operator, who adds the entry to
agents.json. Local keys are identified by their thumbprint, whateverSignature-Agentsays. - Publish a key directory at
https://your-agent.example/.well-known/http-message-signatures-directory, and ask the operator to allow-list your origin underdirectories. AgentGate fetches only allow-listed directories.
Directory requirements: the directory media type, 200 only (no redirects), at most 64 KiB and 32 keys, answered within 5 s from a public address. Cache-Control: max-age is honoured between 5 minutes and 24 hours. Keys match by thumbprint or by the directory's kid. A directory signature (tag http-message-signatures-directory) is verified when present but not required.
2. Sign every request
Cover at least @authority and the Signature-Agent member. Add @method, @path and content-digest whenever the request does something; /agent/submit requires all of them, and each declared tool's auth.components lists what its endpoint requires.
POST /agent/submit HTTP/1.1
Host: shop.example
Content-Type: application/json
Content-Digest: sha-256=:<base64 SHA-256 of the body>:
Signature-Agent: sig1="https://your-agent.example"
Signature-Input: sig1=("@authority" "@method" "@path" "content-digest" "signature-agent";key="sig1");created=1790000000;expires=1790000300;keyid="<thumbprint>";nonce="<random>";tag="web-bot-auth"
Signature: sig1=:<base64 Ed25519 signature>:
{"id":"order-7f3a-0001","message":"hello"}Signature-Agent may be the dictionary form shown (sig1="https://…", covered as "signature-agent";key="sig1") or the legacy bare string (covered as "signature-agent").
3. Signature rules
| Rule | Detail |
|---|---|
| Required parameters | created, expires and keyid |
| Lifetime | expires at most 24 hours after created; 60 s of clock skew allowed |
| Nonce | optional in general, single use until the signature expires; send a fresh one per request |
| Algorithm | Ed25519 only (RSA-PSS signatures are ignored) |
| Body | on /agent/submit and on gateway routes with requireContentDigest, Content-Digest (RFC 9530, sha-256) must match the body |
Failures are labelled and, by default, answered 401:
| Label | Meaning |
|---|---|
agentgate:agent:signature:invalid | bad signature, coverage or parameters |
agentgate:agent:signature:expired | past expires |
agentgate:agent:signature:replayed | the nonce was already used |
agentgate:agent:signature:unknown_key | the key is not known for that origin (plus agentgate:agent:directory:unavailable when the directory could not be fetched) |
agentgate:agent:signature:missing | no web-bot-auth signature |
Shared key (testing only)
If the operator issued one, the X-Agent-Key header also authenticates you on the agent API (label agentgate:agent:shared_key). It is weaker than a signature and meant for testing.
Interoperability
The verifier passes the Ed25519 test vectors from Cloudflare's web-bot-auth library and the draft's Appendix E, and verifies the live directories of ChatGPT agent, Google-Agent, Browserbase and Cloudflare Browser Run as captured on 2026-09-24. Registries (draft-meunier-webbotauth-registry) can be imported as extra directory entries at startup.