User-Agent: GPTBot from their laptop. The Bluesky edge middleware treats a matching user-agent as a first filter only, then verifies the request’s source IP against the vendor’s published CIDR ranges. Only requests that pass a real verification check are ever served the optimized artifact.
Why user-agent alone isn’t enough
A user-agent string is a plain-text header. There is nothing stopping a bad actor — or a curious developer — from sending a request withUser-Agent: PerplexityBot from any IP address. (Cloudflare delisted PerplexityBot for exactly this kind of stealth crawling — the canonical proof that a UA token alone is worthless.) If Bluesky served the optimized variant to every request that looked like a known bot, you’d be handing your AEO content to anyone who asked.
The middleware therefore treats UA matching as a necessary first step, not a sufficient one:
- The UA is scanned for a known bot token — if nothing matches, the request is ignored entirely (passthrough, no telemetry).
- If a bot token matches, the request’s source IP is checked against that bot’s published CIDR ranges.
- Only requests that verify at step 2 are eligible for the variant.
Verification tiers
The AEN core arranges verification into ascending-trust tiers. The four that bear on serving are below; onlySIGNED and IP_VERIFIED are treated as verified and are ever eligible to receive the variant.
UA_ONLY
The user-agent matched a known bot pattern, but the source IP is not inside any of the vendor’s published CIDR ranges. This is the lowest tier and is treated as unverified.
Result: The request always receives your normal page. UA_ONLY hits are still logged so you can see them in Agent Analytics, but they are never served the optimized artifact.
IP_VERIFIED
The user-agent matched and the source IP falls within one of the vendor’s published CIDR ranges. This is the tier the shipped drop-in middleware produces for verified traffic. The drop-in itself is test-grade — it fetches config and artifacts from the control plane on every request (the productized edge caches those calls), so treat it as a working starting point rather than a tuned production deployment.
Result: Eligible to receive the optimized variant, subject to serve mode and purpose class.
DNS_VERIFIED
Forward-confirmed reverse DNS (rDNS → forward DNS) on the source IP. This tier is defined in the core but is resolved engine-side / asynchronously — it is deliberately kept off the edge hot path because it adds latency. The drop-in middleware does not perform rDNS, and the edge serve rule does not treat DNS_VERIFIED as serve-eligible.
SIGNED
The request carries a valid Web Bot Auth signature (RFC 9421 HTTP Message Signatures, Ed25519 profile), verified against the vendor’s pinned public keys. This is the strongest tier — the signature is cryptographically bound to the request and is the only method that survives shared-cloud or residential-proxy IPs.
Result: Eligible to receive the optimized variant, subject to serve mode and purpose class.
Web Bot Auth (
SIGNED) verification lives in the AEN core (webbotauth.ts) and runs in adapters that wire it in. The shipped drop-in Next.js middleware is IP-only — it verifies by published CIDR ranges and emits either IP_VERIFIED or UA_ONLY. Signature-based SIGNED and reverse-DNS DNS_VERIFIED are core/engine capabilities not exercised by the IP-only drop-in.How IP verification works (drop-in middleware)
The middleware fetches the current bot configuration (including CIDR ranges) from Bluesky’s control plane viaGET /api/v1/edge/botset and caches it for one hour:
x-forwarded-for (or x-real-ip) and tested against each CIDR in the matched bot’s range list:
IP_VERIFIED. CIDR ranges refresh from the control plane on the next cache cycle, so your deployed middleware picks up vendor changes without a redeploy.
The drop-in matcher is IPv4-only (it skips any IPv6 address or CIDR). The portable AEN core (
botset.ts) implements full IPv4 and IPv6 bit-prefix matching, and — like the drop-in — fails closed on any malformed or ambiguous input.How bot matching works
The middleware scans the incoming user-agent for a known token using a word-boundary check. When multiple bot definitions match, the one with the longest token wins — this prevents a short token from incorrectly matching a more specific agent (e.g. a hypotheticalClaude never masks Claude-SearchBot):
GPTBot/1.3 still matches GPTBot. The list of known tokens and their metadata is maintained by Bluesky and delivered via GET /api/v1/edge/botset; you don’t manage bot definitions yourself.
Purpose classes
Every matched bot carries a purpose class describing why it is fetching your page:| Purpose | Served? | Description |
|---|---|---|
USER_TRIGGERED | Yes | A user asked an AI assistant to browse your page in real time (e.g. ChatGPT-User, Perplexity-User) |
RETRIEVAL | Yes | An answer engine fetching to build or refresh its index (e.g. OAI-SearchBot, Claude-SearchBot, PerplexityBot) |
TRAINING | No | Corpus / training crawlers (e.g. GPTBot, ClaudeBot, CCBot) |
SEARCH_INDEX | No | Classic search crawlers — always passthrough (see cloaking firewall below) |
UNKNOWN | No | No token matched |
IP_VERIFIED or SIGNED) and in an enabled purpose class to be eligible for the variant. Training crawlers and unknown agents are never served, even when their IP verifies.
The cloaking firewall
Before any verification or serve-mode logic runs, the middleware checks whether the matched bot is a classic search crawler:Googlebot, Bingbot, and Applebot are the only entries flagged isSearchIndex: true. They are passed through unconditionally — no variant is considered and no telemetry is logged. This is a hard safeguard that cannot be overridden by serve mode or the enabled-purpose set.
The answer-engine agents Bluesky does serve — OAI-SearchBot, Claude-SearchBot, PerplexityBot, ChatGPT-User, and similar — are distinct from the search-index crawlers. They power AI-generated answers, not organic search results, so varying the response format for them is not cloaking.
Content parity
Even for fully verified, eligible requests, the optimized artifact holds strict content parity with your original page. The Bluesky generator produces answer-first markdown andArticle / FAQPage JSON-LD by extracting and restructuring your existing page — it never fabricates claims that aren’t in the source. Artifacts are generated offline and cached, so there is no model call on the request path. Same substance, different form — an additional guarantee against any reading of cloaking.
Verification in Agent Analytics
Every logged hit records the verification tier alongside the bot name, path, purpose class, and served status, so you can filter to verified traffic or reviewUA_ONLY hits to spot crawlers operating from unregistered IPs.
Related
Serve modes
off / shadow / canary / default — how the verified-and-eligible decision turns into an actual served response.
Quickstart
Provision a domain, get your edge token, and drop the middleware into your Next.js app.