Rightshold™ Sign up

Answers · AI crawlers

How do I sign my own AI agent's HTTP requests with Web Bot Auth so websites can verify it?

Last updated

TL;DR: Give the agent its own Ed25519 key, publish the public half as a JSON Web Key Set at /.well-known/http-message-signatures-directory on a domain you control (HTTPS, media type application/http-message-signatures-directory+json, and sign that response with the key so nobody can mirror your directory), then sign every outgoing request with HTTP Message Signatures (RFC 9421). Each request carries three headers: Signature-Agent (where your keys are), Signature-Input (covering at least @authority and signature-agent, with tag="web-bot-auth", keyid set to the key's JWK thumbprint, created and a short expires) and Signature. Sites that check can then tell your agent from anything borrowing its user-agent string. Two details trip people up. Cloudflare's docs (updated Oct 8, 2026) say its verifier fails a request that sends the newer dictionary form of Signature-Agent (sig1="https://...") and wants a quoted bare string, while the working-group draft published October 29, 2026 (draft-ietf-webbotauth-httpsig-protocol-01) says signers MUST send the dictionary form and verifiers MAY still accept the old one. And Cloudflare only trusts your key after you register the directory through its bot submission form. Test against each verifier you care about before rollout; gate_check verifies either header form for free.

What should I check, step by step?

1. Generate a dedicated Ed25519 key for the agent (Cloudflare's docs use openssl genpkey -algorithm ed25519). Keep the private key in a secret store, one key per agent or environment, and never reuse a TLS or code-signing key.

  1. Publish a JWKS with the public key (kty OKP, crv Ed25519, x) at https://<your domain>/.well-known/http-message-signatures-directory, served with Content-Type application/http-message-signatures-directory+json. Never include the private d parameter.
  2. Sign the directory response itself: one signature per key, tag="http-message-signatures-directory", keyid = that key's thumbprint, covering "@authority";req. Cloudflare says this stops anyone mirroring your directory and registering it as theirs.
  3. Compute the keyid as the base64url JWK SHA-256 thumbprint (RFC 7638; for Ed25519 the OKP form in RFC 8037). If you put a kid in the JWKS, the draft says it must equal that thumbprint.
  4. On each request, cover at least @authority and signature-agent, plus @method and @path if you want the signature to fit one request only. Set created, a short expires (Cloudflare suggests a minute is often enough; the draft recommends no more than 24 hours) and a fresh nonce.
  5. Choose the Signature-Agent form per verifier: a quoted string such as "https://agent.example.com" for Cloudflare today, the dictionary form sig1="https://..." for verifiers that follow the current draft. Don't add parameters to dictionary members; the draft says verifiers must ignore a member that carries them.
  6. Sign only ASCII components, and don't sign Content-Digest if a proxy might change the body. Cloudflare fails @query-params, @status and the sf, bs, key and req parameters on request components.
  7. Register with the verifiers you need (Cloudflare: BotBase submission form, Verification Method = Request Signature, your directory URL), then test: crawltest.com/cdn-cgi/web-bot-auth returns 401 for a well-formed request with an unknown key, 200 when the key is known and the signature verifies, 400 otherwise.
  8. Rotate by publishing the new key next to the old one, switching signing, then removing the old key once in-flight signatures have expired.

What does a Web Bot Auth signature prove to a website about an AI agent?

A user-agent string is text anyone can send. A valid Web Bot Auth signature shows the request was signed by a key published at the Signature-Agent URL, so a site can allowlist, rate limit or block that signer without relying on IP ranges. Cloudflare's verified bots page says signed agents have been counted as Verified since July 1, 2026, labelled Direct (one operator) or Intermediary (a service many end users drive).

What is the status of the Web Bot Auth standard and its Signature-Agent header format?

The IETF webbotauth working group adopted the protocol as draft-ietf-webbotauth-httpsig-protocol (revision 01, October 29, 2026). It replaced the individual drafts Cloudflare's docs still cite, and it is still a draft, so details can change.

How do I test that my AI agent's signed requests verify before rollout?

Capture one real outgoing request (method, URL and the three signature headers exactly as sent) and run it through each verifier you care about: Cloudflare's crawltest endpoint, your own middleware, and gate_check.

How do I ask Rightshold about this (free, no key)?

Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code, then ask: “Here is one request my agent just sent, with its Web Bot Auth headers exactly as sent. Does the signature verify against my published key directory for this site, and would a site that only allows my signer let it through?”

One-click setup

{
  "tool": "gate_check",
  "arguments": {
    "policy": {
      "domain": "shop.example.com",
      "require_web_bot_auth": true,
      "allowed_signature_agents": [
        "agent.example.com"
      ]
    },
    "request": {
      "method": "GET",
      "url": "https://shop.example.com/products/123",
      "headers": {
        "user-agent": "ExampleAgent/1.0 (+https://agent.example.com/bot)",
        "signature-agent": "<as sent>",
        "signature-input": "<as sent>",
        "signature": "<as sent>"
      }
    }
  }
}

Rightshold verifies a signed request you send it against a policy and returns allow or deny with reasons. It doesn't generate or store your private key, sign requests for you, register your agent with Cloudflare or anyone else, or guarantee any site will let your agent in. Passing gate_check doesn't mean Cloudflare's verifier accepts the same request; test each one. Not legal advice.

What are the sources?

Related

Not legal advice. JSON · Markdown · All answers

Get a free API key in one call

No card and no email needed. 100 free credits; the license and policy checks stay free without a key.

curl -s -X POST https://www.rightshold.com/v1/accounts/signup -H "Content-Type: application/json" -d '{"accept_terms":true}'
export RIGHTSHOLD_API_KEY=rs_...   # the api_key from the reply (shown once)
curl -s https://www.rightshold.com/v1/licenses/check -H "Authorization: Bearer $RIGHTSHOLD_API_KEY" \
  -H "Content-Type: application/json" -d '{"license":"MIT","intended_use":{"commercial_use":true}}'