Edge routing for AI agents

Technical white paper

One URL, two audiences. AI agents get structured, machine-readable data at your own web address. Humans and search engines get your origin, byte for byte, untouched. This paper sets out exactly how it works, and answers the questions a security review asks.

Never divertedGooglebotBingbotApplebotDuckDuckBotBaiduspiderYandexSlurp
Served on requestGPTBotClaudeBotPerplexityBotMeta-ExternalAgent

One URL, two audiences

GET example.com/products/widget
Human in a browserand every traditional search crawler
GooglebotBingbotApplebotDuckDuckBotBaiduspiderYandexSlurp
AI crawlerverified, and enabled by you
GPTBotClaudeBotPerplexityBotMeta-ExternalAgent
NORG worker, at your CDN edgeOne ordered sequence of ten gates, cheap and safe exits first
Fails open to your origin
1–4 · method & kill switch, entitlement, assets, skip list5 · search-crawler exit6 · ?agent=true inspection7–10 · agent match · enabled · IP verified · serve
Runs on
Cloudflare Workers0.11.7AWS CloudFront0.6.0Fastly Compute0.2.0Bunny Edge Scripting0.2.0Azure Front Door0.0.4-protoAkamaiVercel
Solid: shipped adapters, versioned independently from one shared core. Dashed: scoped, not yet implemented.
Your marketing site: origin, unmodified

Byte for byte. Nothing rewritten, not reported by default, and no NORG header on the response.

X-Norg-Edgestructured technical depth, same URL, 200
# Widget · Product"@type": "Product", "sku": "W-114""brand": → Organisation/acme"isPartOf": → Collection/industrial"offers": price, currency, availability"sameAs": 3 verified referencesspecs: 14 attributes, SHACL-validedges: 9 typed relationshipsmcp: search · related · graph

Derived entity data from a validated graph, with no JavaScript, no layout to interpret, and a live endpoint it can query.

Both panes are the same address. Anyone can see the right-hand one by appending ?agent=true in an ordinary browser.

Terms this page uses
origin
Your own web server, or whatever your CDN already points at. "Your origin" is the response your site would have given with nothing of ours installed.
mirror
The agent-facing copy of a page NORG builds from your site: structured, derived data served at the page’s own URL. A "mirrored URL" is one that has such a copy.
passthrough
The worker returning your origin’s response untouched: no rewrite, no redirect, no NORG header. Most requests are passthroughs.
policy feed
The per-site list the worker fetches from NORG and caches for up to an hour: which crawler patterns to recognise, which operators you have enabled, their published address ranges, and your skip list. A "policy refresh" is the worker fetching it again.
entitlement
Whether NORG currently authorises this install to divert at all, decided by its site key when the policy feed is fetched. An unentitled install passes everything through and is otherwise indistinguishable from one that is not there.
source verification
Checking that a request claiming to be a crawler arrives from an address that crawler’s operator has published, so a copied user agent from anywhere else gets your origin.
kill switch
A setting on your own platform that puts every request back on the passthrough path with the code still deployed. Where it lives and how fast it acts differs per platform.
skip list
Paths you exclude from mirroring on a live install; requests to them pass through. Editable, and a change reaches the edge within the hour.
heartbeat
A periodic call from the edge to NORG reporting the adapter version, so an install with no traffic is still visibly alive.
NORG content service (the receptionist)
The NORG endpoint the worker fetches mirrored pages from, which also records a visit each time it serves one.
instance
One warm copy of the edge code; a platform runs many at once. Each keeps its own small cache, so "once per instance" means once per warm copy, not once per site. Cloudflare calls these isolates, Lambda calls them containers.
cache miss
A request the CDN’s own cache cannot answer and so passes onward. Every page request is one on every platform, because no adapter caches the page at the edge; on Bunny, where the script runs only on a miss, that is what the install’s edge rule guarantees.

What this does

AI assistants increasingly answer questions about your business without sending anyone to your website. They read it instead. But a marketing site is built for people, its meaning lives in layout, imagery and JavaScript, and a crawler reading the HTML gets a poor, lossy version of what you actually offer.

The edge decision: human vs AI crawler

Same URL, same request path. The only thing that differs is who is asking, and what they are given.

Caller A
A person in a browser

…or a traditional search crawler, checked before any classification runs.

GooglebotBingbotApplebotDuckDuckBotBaiduspiderYandexSlurp
Caller B
A verified AI agent

Pattern matched, operator enabled by you, and arriving from that operator's published address ranges.

GPTBotClaudeBotPerplexityBotMeta-ExternalAgent
NORG worker, at your CDN edge
One ordered sequence of ten gates, cheap and safe exits first (How the routing works)
ResultYour origin, byte for byte

No redirect, no rewrite, no NORG header on the response, and not reported by default. What Google indexes is what it indexed before the worker existed.

no X-Norg-Edge
ResultNORG structured content, same URL

HTTP 200 at the URL that was asked for. Entity data from a validated graph, no JavaScript, marked private so no shared cache can replay it to a human.

X-Norg-Edge

Anyone can stand in Caller B's shoes: append ?agent=true to any mirrored URL in any browser and you get precisely what a verified agent gets.

NORG puts a small piece of code at your CDN edge. When a verified AI agent requests one of your pages, it receives structured, machine-readable content at that same URL, with a normal HTTP 200 and no redirect. Everyone else gets your origin response.

Who is askingWhat they getResponse header
A person in a browserYour origin, unmodifiednone
Googlebot, Bingbot, Applebot, DuckDuckBot, Baiduspider, Yandex, SlurpYour origin, unmodifiednone
A verified AI agent you have enabledNORG structured content, same URL, HTTP 200X-Norg-Edge
Something claiming to be an AI agent, from an unverified addressYour origin, unmodifiednone
Any request that is not a GET (forms, checkout, login, APIs)Your origin, unmodifiednone
Images, CSS, JS, fonts, video and other static assetsYour origin, unmodifiednone

Read that table as a whole and the shape is clear: the overwhelming majority of traffic to your site is a passthrough. The worker exists to change one row.

Two rules are built into the worker and are not configurable
  1. It must never break your site. Every failure path (NORG unreachable, storage unreachable, anything unexpected at the edge) falls back to your origin response.
  2. Search engines see exactly what humans see. Serving Googlebot different content to a visitor is cloaking and would put your rankings at risk, so traditional search crawlers are always passed straight through.
Applies to all CDNs, with these notes
Cloudflare Workers

Any failure inside the worker returns your origin. The one exit that sits above the worker is the Workers free plan's account-wide request cap, which fails closed by default: the API-token install sets the route to fail open, and a Deploy-button install needs that toggled in the dashboard, which we walk you through.

AWS CloudFront

Failure inside the function returns your origin, and a twenty-second watchdog sits under the platform's own limit so a slow call can never become a 502. The one exit above the function is the regional Lambda@Edge concurrency quota: past it CloudFront answers 503 on every page request in that region, so the install prints the quota in every region and enables rate limiting by default.

Fastly Compute

Failure returns your origin. A backend that will not answer produces the same 503 a Fastly service without Compute would, never an invented error.

Bunny Edge Scripting

Failure inside the script returns your origin, with a fifteen-second watchdog. One platform behaviour to know: a script that throws at startup makes the pull zone answer 400 for everything, which is why the middleware registers only the origin-request hook and the build refuses the others.

Azure Front Door

The platform terminates the action on any failure and serves your origin without it. Two design differences on this platform: there is no entitlement check and no source verification yet, so classification is by user agent alone and a matching user agent from any address is served the mirror; and a health probe on the origin group would silently drop the NORG content service (the receptionist) from the switch, so probes are disabled at install.

How the routing works

Every request the code sees runs the same sequence. The order matters more than any individual check: the cheap, safe exits come first, so most traffic leaves before the worker has done anything at all. The last column shows how each gate holds per platform; the list beneath it gives each reason in full.

#CheckResultBy platform
1The kill switch is set, the loop guard header is present, the request is a protocol upgrade, or the method is not GET (or a HEAD for one of NORG’s own paths)Origin, untouched. This is the kill switch and the write-traffic floor; the one relay is a POST to an MCP path.
2The site is not entitled: NORG returned 401 or 403 for this site keyOrigin, untouched. An unentitled worker is indistinguishable from no worker.
3The path is a static asset: one of 49 suffixes covering images, CSS, JS, fonts, media, archivesOrigin, untouched. Never mirrored, never rewritten, not reported.
4The path is on your skip listOrigin, untouched. Per-route opt-out you control.
5The user agent is a traditional search crawlerOrigin, untouched. Runs before classification, so no later rule can reach it; only NORG’s own discovery paths, identical for every caller, are answered ahead of it.
6The URL carries ?agent=trueThe mirror for that path, stamped X-Norg-Edge and counted like any agent visit; your origin if no mirror exists. This is the inspection lever, not an exposure: it skips the three agent gates by design, serves only what a verified agent would already get at that URL, and is marked private, no-store so no shared cache can hold it.
7The user agent matches no known AI agent patternOrigin, untouched.
8The matched agent is not enabled for diversionOrigin, untouched. The database default for every operator is never divert, so this is opt-in.
9The source address is not verified against that operator’s published rangesOrigin, untouched, and no NORG header is stamped at all. This is what a spoofed user agent hits.
10All of the above passedNORG structured content at the same URL, HTTP 200, stamped X-Norg-Edge.

Where a gate differs by platform

  • AWS CloudFront 1: the kill switch is a distribution update of five to fifteen minutes.
  • Fastly Compute 1: an MCP POST goes to your origin rather than being relayed.
  • Bunny Edge Scripting 6: reaches the router on a cache miss only, so test an uncached URL or turn the cache bypass on.
  • Azure Front Door 1: no switch in the action; disabling is a control-plane change of thirteen to twenty-five minutes, and every method is classified; 2: no entitlement check; the operator list is built into the script; 3: a shorter list of 25 suffixes, and a decision header is stamped; 4: no skip list; a change is a redeploy; 7: the pattern list is built into the script rather than fed; 8: no per-site enablement; every listed operator diverts; 9: no source verification; a matching user agent from any address is served; 10: served by switching origin group rather than in place.
A verified agent visit, end to end

GPTBot requests /products/widget from an address OpenAI publishes. It clears gates 1 to 5 because it is a GET on an entitled install, not an asset, not skipped and not a search engine; carries no ?agent=true; matches the GPTBot pattern; OpenAI is enabled for your site; and the address is in the published range. The worker fetches the mirror for that path from the NORG content service, serves it as a 200 at the same URL stamped X-Norg-Edge, and records one analytics event.

If no mirror exists for the path yet, the agent gets your origin instead, and where lazy rendering is on the worker asks NORG to build one for next time. If the mirror comes back with fewer than 120 visible words, the origin is served too. Neither case produces an error.

Why no page is cached at the edge on any platform

A page cached at the edge is a page an agent can be served without the worker running, and a cache key that separates agents from people is one more thing to get wrong. So no adapter caches the page: on CloudFront the default behaviour has caching disabled; on Fastly page requests pass to your origin with a cache bypass; on Bunny, where the script runs only on a cache miss, the install adds an edge rule that stops the pull zone caching HTML, verified on a live zone; on Cloudflare the worker runs before the cache. Assets keep their cache everywhere.

A user agent alone is never enough

Rows 7 to 9 are three separate gates, and a request must clear all of them. Matching a pattern is not sufficient; the operator must be enabled for diversion, and the request must arrive from an address that operator has published. Running curl -H "User-Agent: GPTBot" against a mirrored URL from your own laptop returns your origin, with no NORG header on the response, on Cloudflare, CloudFront, Fastly and Bunny. That is the test we would run first in your position. Azure Front Door does not yet verify the source address, so on that platform the same test returns the mirror; the marks on row 9 say so.

Headers you can observe

X-Norg-Edge

Stamped only on a response NORG served, so its absence is the signal that a request was a passthrough. Azure Front Door stamps a decision header on every response instead; its note under Your human traffic says which.

Cache-Control: private, no-store

Set on every mirrored response so it can never enter a shared cache and be replayed to a human.

CDN-Cache-Control: private, no-store

The same guarantee at the CDN layer. What actually keeps a mirrored response out of the shared cache differs by platform: Cloudflare and Fastly run the code before the cache and generate the response, CloudFront does not cache pages at all, Bunny only ever runs on a cache miss, and Azure keeps caching off on the route.

What the worker never does

  • Mediate any non-GET request. Forms, checkout, login and API writes pass through, the sole exception being a POST to an MCP path.
  • Read, act on or transmit cookies or authorization headers. It reads the user agent, the visitor IP for verification, and two internal guard headers; the one request it relays to NORG carries an allowlist of JSON-RPC headers only.
  • Redirect. Every NORG-served response is a 200 at the URL that was requested; a passthrough returns exactly what your origin returned.
  • Rewrite or intercept any request to your origin. Every origin call preserves the original method and body.
  • Serve a thin page. If cleaned content falls under 120 visible words, the unmodified origin is returned instead.
  • Process static assets. Images, stylesheets, scripts, fonts and media are returned on a fast path with no lookup.
  • Recurse into itself. A loop-guard header on every fetch to NORG and to your origin makes that structurally impossible.

On Cloudflare and CloudFront, whole path prefixes can also be carved out at the routing layer so the code is not invoked for them at all, see Trying it on one page. The worker also records one analytics event per agent visit: the path, the user agent, the classification, what was served, the response status, and whatever network context the platform exposes. The Data protection group under Questions we get asked lists the fields per platform, and says on which platforms delivery has been verified live.

Applies to all CDNs

How we ensure your human traffic is unaffected

This is the first rule the worker is built to, and every other capability is subordinate to it. It is not a policy we apply carefully, it is the shape of the code: a human request exits before there is anything left to go wrong, and we would rather you verified that than believed it.

A person in a browser is never divertedDiversion requires a positive match against a known agent pattern. A browser matches none, so a human request leaves on the ordinary passthrough path and is answered by your origin.
Nothing a person submits is ever mediatedOnly GET requests are considered, plus a HEAD for one of NORG’s own paths. Forms, checkout, login and API writes leave at the first check, before anything else runs; the one relay is a POST to an MCP path.
The response is your origin, byte for byteA passthrough is not rewritten, not redirected and carries no NORG header, and it returns whatever status your origin returned. A NORG-served page is a 200 at the URL that was asked for.
Agent content can never reach a personEvery mirrored response is marked private, no-store, at the browser layer and, where the platform honours it, at the CDN layer too, so no shared cache can hold one and replay it to a visitor.
Your assets are not touchedImages, stylesheets, scripts, fonts and media return on a fast path with no lookup. On Cloudflare and CloudFront, whole path prefixes can also be carved out at the routing layer, where the code is not invoked at all.
Sessions are not visible to itThe worker reads no cookies and no authorization headers, and transmits neither. A signed-in visitor is indistinguishable from any other passthrough.
What it costs a real visitor

On the passthrough path the worker makes no network call of its own, so a visitor waits on your origin exactly as before, plus a few milliseconds of edge runtime: the classification is a pattern match against a list already held in memory, in the same data centre the request had already reached.

The one exception is the first request a cold instance sees. Before it can decide anything it fetches the policy feed once, bounded by a five-second timeout and falling back to your origin if that expires. The feed is then cached for up to an hour, so this is one lookup per instance rather than per request, and a human request can be the one that pays it. On CloudFront a human request never does: the browser check runs before any lookup, and only a bot-shaped request fetches the site key and then the feed.

Analytics never hold a human response. On Cloudflare the worker records each visit through the platform's own deferred-work primitive after the response has been sent. On CloudFront, Fastly and Bunny the router sends nothing for an agent visit: the visit travels as a header on the mirror fetch and the NORG content service records it after answering, through its own deferred-work primitive. The opt-in human passthrough event is handed to the platform's keep-alive where one exists.

And if something is wrong at our end

Every path out of the worker ends at your origin. If NORG cannot be reached the worker keeps serving from its last known-good policy; if content cannot be fetched, or comes back too thin to be worth serving, your origin is returned instead. Where the platform has a request cap, the route is set to fail open so a breached cap bypasses the worker and serves your site, which is the opposite of the platform default.

You also hold a switch of your own; the panel below sets out the two ways to stop it and how fast each is, per platform.

The two ways to stop it, and how fast each is

The kill switch is yours. It puts every request back on the passthrough path with the code still deployed. Cloudflare: a Worker variable, immediate. Fastly: a Config Store key, immediate. Bunny: a script variable, on republish. CloudFront: an origin custom header, so a distribution update of five to fifteen minutes. Azure Front Door: no switch in the action itself; disabling is a control-plane change of thirteen to twenty-five minutes.

Revocation is ours, and slower. Pausing the site or revoking its key makes the install unentitled, but the worker only learns of that at its next policy refresh, up to an hour away by default, because it serves from its cached feed in between. So the kill switch is the emergency lever and revocation the permanent one. On CloudFront, if the secret in your own account is what changed, the fifteen-minute secret cache applies on top.

Cloudflare Workers

Every guarantee above, as written. The kill switch is the EDGE_DISABLED Worker variable, immediate.

AWS CloudFront

Your origin sees its own hostname rather than the visitor's on every request, a platform requirement. No human page is cached at the edge: your origin answers every page request, and a human request makes no lookup at all. The kill switch is a distribution update, five to fifteen minutes.

Fastly Compute

Every request invokes the service, assets included, though assets leave on the in-code fast path and an ordinary browser is answered before any lookup. No page is cached at the edge: page requests pass to your origin with a cache bypass while assets keep Fastly's cache. The kill switch is a Config Store key, immediate.

Bunny Edge Scripting

The router runs on a cache miss only, so the install stops the pull zone caching HTML; every page request then reaches the script, and an ordinary browser is answered before any lookup. Assets keep their cache. The kill switch is a script variable, immediate on republish.

Azure Front Door

Every HTTP method is classified, so a POST from a matching user agent is origin-switched rather than passed through. Every response, including a human passthrough, carries x-norg-edge-decision and x-norg-edge-version. A divert forwards the visitor's headers to NORG, cookies included. There is no switch in the action itself; disabling is a control-plane change that takes thirteen to twenty-five minutes to reach the edge.

What we serve

What an agent receives here is derived data, not a reformatted copy of your page. The distinction matters, and this section is the evidence for it.

The content NORG serves is derived from a knowledge base built for your business from publicly available, relevant information, together with anything you supply. Republishing your crawled page body alongside it is a per-site option and is off by default, so in the normal configuration an agent receives structured, derived data rather than a copy of your page.

Why the data is different

Entities are records, not markup

Each entity (a product, an organisation, a service, an event) is a versioned record with its own identity and history, not a fragment of markup glued to a page. Every change is recorded with its origin, and can be rolled back.

Validated against a shape graph

Entities are checked with SHACL, the W3C constraint language for RDF, on the write path. That is a stronger guarantee than emitting well-formed JSON-LD: it means a document that fails the shape for its type is caught rather than published.

A graph, not a taxonomy

Entities are joined by typed, directed edges, each carrying its schema.org property and its inverse, constrained by which entity types may legitimately be joined, with cycle detection on hierarchical relationships. Around twenty-two relationship types are in use: brand, hasPart/isPartOf, about/subjectOf, sameAs, isRelatedTo and others.

Four independent ways of finding a relationship

Edges are proposed by a per-entity language-model pass, by algorithmic tag similarity with no model involved, by deterministic type-affinity rules, and by structural graph analysis: centrality, community detection and common-neighbour gap detection. Proposals are then verified by a separate chain-of-verification pass against confidence thresholds, and are reviewable by an operator.

The edges travel inside the data

Relationships are embedded back into each entity document as inline references, so the published graph can actually be traversed by a consumer rather than read as a flat list.

A queryable surface, not just files

Beyond the documents, a live MCP endpoint lets an agent search your published content by retrieval over the knowledge base and ask for related items, which come back with a score and the specific shared attributes that produced it. That is information an agent cannot derive by reading your HTML.

Why the pages are fast to crawl

The second half of the argument is the delivery. A marketing page is an expensive thing for a crawler to read: scripts to execute, images to fetch, and meaning buried in presentation. The documents NORG serves are built for the opposite job.

No JavaScript

Nothing has to be executed or rendered to read the content. A crawler that does not run scripts (which is most of them) loses nothing.

Minimal graphics

Almost nothing to download beyond the document itself, so a fetch completes in a fraction of the bytes a marketing page costs.

Small, flat documents

Fast to return and cheap to parse, so a crawler working to a budget gets through more of your site in the same allowance.

Meaning, not layout

The structure carries what things are and how they relate, rather than how they should be positioned on a screen.

Alongside the pages, a site publishes discovery artifacts an agent can start from rather than guess at: a plain-text index of the site, a full-text companion, a machine-readable site tree, the entity graph as a single document, and a capability description stating which protocols and endpoints are available.

Applies to all CDNs

Trying it on one page

You do not have to decide about your whole site to evaluate this. There are three ways to start small, and the first one puts nothing on your infrastructure at all.

A single page, hosted by NORG

Nothing installed on your infrastructure. Your domain untouched.

NORG builds and serves one page, typically your homepage, on its own hostname. No worker, no routes and no credentials on your side, and no change to your DNS. You get to see the content, the structured data and the agent-facing surfaces, and judge the quality of the output before anything of ours goes anywhere near your site. This is the smallest possible commitment and it is where we suggest most reviews start.

A scoped install on your own domain

The adapter for your CDN, limited to the paths you name where the platform can bind it that narrowly.

You name the routes (one path, a section, or a handful). On Cloudflare and CloudFront the code is bound only to those, so everything else on the domain does not invoke it at all: not merely unmodified, untouched. On Fastly, Bunny and Azure the code attaches to the whole service, zone or route, and the skip list is what narrows it. Crawling and mirroring are limited to the same scope either way, so a narrow trial costs proportionally less. Reserved paths for the machine-readable discovery surfaces are added alongside your scope, and they are listed for you before anything is created.

A staging hostname

A full install, on a hostname that is not production.

Install against staging as its own workspace, with its own credentials and its own mirror. Useful when you want to exercise the whole thing end to end without production traffic in the picture. It is not time-limited and does not expire.

How a scoped install proceeds on Cloudflare

The Cloudflare install has a fully automated preflight, preview and confirm sequence, so it is the one worth seeing step by step. What each other platform's install actually is, step by step, is in the notes at the end of this section.

  1. Preflight. Verifies the credential, resolves the zone, checks that DNS is proxied and scans for a conflicting route. Changes nothing.
  2. Preview. Returns exactly what would be created: the scope, the reserved paths, the effective exclusions and every warning together with a confirmation token. Still changes nothing.
  3. Confirm. Only an explicit human confirmation carrying that token proceeds. The scope is bound into the token, so an install that differs from what you previewed is refused rather than applied.

Getting back out

  • From your side: the kill switch. Everything passes through, code still deployed. Immediate on Cloudflare and Fastly; on republish on Bunny; a distribution update of five to fifteen minutes on CloudFront; a control-plane change of thirteen to twenty-five minutes on Azure. Your human traffic has the detail per platform.
  • One route: exclude it. Allow up to an hour to reach the edge, so this is a tidy-up lever rather than an emergency one.
  • The whole install, from our side: pausing the site or revoking its key unentitles the worker at its next policy refresh, up to an hour by default, on the four adapters that check entitlement. That is slower than your kill switch, so it is the permanent lever rather than the emergency one.
  • Completely: on Cloudflare, uninstalling removes the routes and the script from your account, revokes any stored credential and clears the recorded scope; on the other platforms it is the reversal named in that platform's note. Purging additionally deletes the rendered content, on every platform.

Worth deciding the scope up front

The include scope, the set of routes the worker is attached to, is fixed at install time, and widening past it is a reinstall rather than an edit. What is mirrored inside that scope is not fixed: the skip list is editable on a live install and reaches the edge within the hour. So the approach we recommend, and will set up with you, is to install across the scope you expect to reach eventually and use skips to control what is live today. The NORG-hosted option avoids the question entirely.

Applies to all CDNs, with these notes
Cloudflare Workers

The scoped install as described: the worker is bound only to the routes you name, everything else does not invoke it, and the preflight, preview and confirm sequence applies.

AWS CloudFront

Scope is a set of cache behaviours; paths outside them never invoke the function.

Fastly Compute

A Compute service runs on every request to it, so scope is the skip list rather than route binding.

Bunny Edge Scripting

The middleware is zone-wide, so scope is the skip list rather than route binding.

Azure Front Door

The action runs on every request to the route and there is no skip list yet, so scope is by hostname.

Questions we get asked

Everything below is either a mechanism documented above or a stated limitation. Where the honest answer is “no” or “not yet”, it says so. Each group ends with its platform coverage: a pill where every answer holds on all five CDNs, or a note per platform where one differs.

Why this is not cloaking

What do the search engines actually say?

Google: “Cloaking refers to the practice of presenting different content to users and search engines with the intent to manipulate search rankings and mislead users.” Microsoft, under practices that reduce “ranking eligibility and grounding visibility, across Bing and Copilot experiences”: “Sites should not rely on cloaking or serving materially different experiences to crawlers and visitors.” Microsoft's is the stricter of the two, and its page carries no visible revision date.

Both tests turn on a gap between crawler and visitor. What closes it here?

The check for traditional search crawlers runs before any bot classification, verification or content lookup. Googlebot, Bingbot, Applebot, DuckDuckBot, Baiduspider, Yandex and Slurp return your origin before anything downstream can see them. The only paths answered ahead of that check are NORG's own discovery surfaces, which serve identical bytes to every caller, search engines included, so on every platform what either search engine crawls is identical to what a visitor sees, which is the test both policies actually state.

How exactly do we inspect what an agent is served?

Append ?agent=true to any mirrored URL, in any browser, and you get precisely what a verified agent gets. The parallel /ai/ subtree serves the same content by path rather than by user agent, so that URL returns identical bytes to every caller. Cloaking depends on the substitution being undetectable; this one is a documented, self-service check that needs no cooperation from us.

Can the alternate artifacts compete with our pages in search?

No. They are served noindex with a Link: rel="canonical" pointing back at your HTML page, so they cannot be indexed in their own right.

How is this different from ordinary content negotiation?

It is content negotiation on the user agent, a long-established and entirely ordinary technique: the same URL returns different bytes to different clients, exactly as it does on any site serving a mobile layout or an Accept-negotiated API response. Two properties are what separate it from cloaking, and both hold here by construction: search engines are excluded from the variation entirely, and the variation is inspectable by anyone.

Microsoft's wording is stricter than Google's. Does that change anything?

We have looked at it closely. It has no intent element, offers no carve-outs, and speaks generally of “crawlers and visitors” rather than of search engines. It governs what Bing's own crawlers see, and we never alter that: Bingbot is passed straight through like every other search crawler. If your risk posture calls for belt and braces, the path-based /ai/ subtree delivers the same capability with no user-agent variation at all, and we will set it up that way.

Applies to all CDNs, with these notes
Bunny Edge Scripting

The ?agent=true check reaches the router on a cache miss only; the install stops HTML being cached, so test it against a page and confirm cdn-cache: MISS on the response.

Azure Front Door

The search-crawler check is the first decision on this platform, before anything else, so the exclusion holds here too. Not yet available on this platform: the /ai/ subtree, and the alternate artifacts with their noindex and canonical headers.

Search and ranking risk

Will this affect our search rankings?

Search crawlers are passed through before any classification runs, so what Google indexes is exactly what it indexed before the worker existed. The alternate-format artifacts are noindex with a canonical link back to your page, so they cannot compete with it. “Why this is not cloaking”, below, sets out the full argument.

Which crawlers count as search engines and are never diverted?

Googlebot, Bingbot, Applebot, DuckDuckBot, Baiduspider, Yandex and Slurp. The check runs before classification, so no operator setting can reach them; the only things answered ahead of it are NORG’s own discovery paths, which serve identical bytes to every caller.

Google Gemini and AI Overviews use Googlebot. What happens there?

They get your origin. Because Google's AI surfaces are fed by the same crawl infrastructure we deliberately never touch, NORG does not serve them. That is a deliberate trade: keeping the ranking argument airtight is worth more than the incremental reach, and the gain sits with the assistants that crawl under their own identity.

What happens if Google disagrees?

There is nothing for Google to disagree with. Googlebot is passed straight through before any classification runs, so what it crawls today is byte for byte what it crawled before the worker existed. That is not a setting anyone can change, and you can confirm it in a minute with a Googlebot user agent against a mirrored URL. If Google's guidance ever shifts, the path-based /ai/ subtree already gives you the same capability with no user-agent variation at all, and moving to it is a configuration change rather than a rebuild.

Does this change what our own users see?

No. A human in a browser is a passthrough on every path, and so is every request that is not a GET (or a HEAD for one of NORG’s own paths), so forms, carts, logins and APIs are never mediated; the one relay is a POST to an MCP path.

Could a competitor use this against us?

Their only route is a spam report to a search engine, and such a report has to allege that your site shows the search engine something different from what it shows people. Whoever picks it up checks the only way anyone can, by crawling you, and finds exactly what they found before: Googlebot and Bingbot are passed through ahead of any classification, so the pages the search engines hold are byte for byte your origin. There is no variation for them to find, because there is none.

Would we be left explaining a mechanism nobody has heard of?

No. This page is public and unauthenticated, it names every crawler involved, and the ?agent=true parameter lets anyone reproduce what an agent is served without asking us for anything. A practice you publish, that any observer can verify in a minute, and that excludes search engines by construction, is the opposite of something concealed. If a question ever does reach you, we answer it alongside you and supply the evidence, in the same terms set out here.

Applies to all CDNs, with these notes
Bunny Edge Scripting

The ?agent=true override reaches the router on a cache miss only, so the install stops the pull zone caching HTML; if that rule has not taken on your zone, a cacheable page is answered from cache like any other request.

Azure Front Door

The search-crawler check is the first decision on this platform, so the exclusion holds exactly as described. The /ai/ subtree is not available here yet, so the path-based alternative is Cloudflare, CloudFront, Fastly and Bunny only.

Performance and reliability

What does this add to page load time for real users?

On the passthrough path the worker makes no network call of its own, so a human waits on your origin exactly as before, plus a few milliseconds of pattern matching in the same data centre the request had already reached. The one exception is the first request a cold instance sees, which fetches the policy feed once (on CloudFront only a bot-shaped request does, after the site key); Your human traffic sets out that cost with its bounds.

What happens if NORG goes down?

Your site serves normally. An already-running worker keeps using its last known-good policy and, if content cannot be fetched, returns your origin. Every outbound call has a short timeout, and analytics and heartbeats never hold a human response. Every failure mode we know of resolves the same way, to your origin, and we will go through them with you.

What if we exceed our CDN’s request limit?

Where the platform has one, the route is set to fail open, so a breached cap bypasses the worker and serves your origin. That is deliberately the opposite of the platform default, which would return an error for all traffic. Which platforms have a cap, and how the setting is made on each, is in the notes below.

What does it cost us in CDN invocations?

Less than you would expect, because the worker is not invoked at all for excluded paths. On a Next.js site the framework asset routes (/_next/*, /_vercel/*) are carved out by default. The share of requests the default exclusions remove was measured at roughly 97–98% on a Shopify storefront and roughly 28% on a WordPress site; the difference is how much of each platform's traffic is assets under one prefix. Static assets that do reach the worker return on a fast path with no lookup.

Does it work with our existing worker or edge function?

Yes, in one of two ways. Where the platform routes by pattern, Cloudflare and CloudFront, the narrower NORG route coexists with your catch-all because the most specific match wins, and the preflight reports any exact collision before anything is installed. Fastly, Bunny and Azure attach to the whole service, zone or route, so NORG sits alongside your existing rules rather than beside another function.

Cloudflare Workers
  • Kill switch: a Worker variable. Immediate.
  • Request cap: the free plan's 100,000 a day, and it is account-wide rather than per-worker. It fails closed by default, so the route is set to fail open instead; the API-token install does that for you.
  • What a request costs: no network call on the passthrough path.
  • Analytics: handed to the runtime’s own ctx.waitUntil, so they never touch the response.
AWS CloudFront
  • Kill switch: an origin custom header, so it takes a distribution update of five to fifteen minutes, and it is the faster lever: revoking the site key lands at the router’s next policy refresh, up to an hour by default.
  • Request cap: the regional Lambda@Edge concurrency quota, shared with every Lambda in that region and often ten on a new account; above it CloudFront answers 503 on every page request in that region, so the install prints the quota in all thirteen regions and enables rate limiting by default. Lambda@Edge bills per invocation with no free tier, which is why asset traffic is carved out at the routing layer rather than filtered in code.
  • What a request costs: a human request makes no lookup at all: the browser check runs before any call. A bot-shaped request on a cold instance makes two lookups before its first classification, the site key from the Secrets Manager replica in its own region and then the policy feed. Both are bounded, and either failing means your origin is served.
  • Analytics: the router sends none. The visit travels as one header on the mirror fetch and the NORG content service records it through its own deferred-work primitive, so nothing about analytics runs in your account or waits in front of a visitor. Delivery verified live.
Fastly Compute
  • Kill switch: a Config Store key, read on every request. Immediate.
  • Request cap: none, but every request invokes the service: Compute has no route-level carve-out, so assets leave on the in-code fast path instead.
  • What a request costs: the runtime has no timeout primitive of its own, so the bound on every call to NORG is the per-backend timeout set at install. They must be set, and we set them.
  • Analytics: the service sends none for an agent visit; NORG’s content service records it from a header on the mirror fetch. The opt-in human passthrough event is handed to waitUntil after the response. Delivery from this platform is not yet verified live.
Bunny Edge Scripting
  • Kill switch: a script variable. Immediate on republish.
  • Request cap: none. Roughly four dollars a month at ten million requests.
  • What a request costs: a human request makes no lookup at all; a bot-shaped request on a cold isolate fetches the policy feed once. The script runs on a cache miss only, so the install stops HTML being cached.
  • Analytics: the script sends none for an agent visit; NORG’s content service records it from a header on the mirror fetch. The opt-in human passthrough event is handed to waitUntil after the response. Delivery from this platform is not yet verified live.
Azure Front Door
  • Kill switch: there is no switch in the action itself. Disabling is a control-plane change, detaching the rule or swapping the default version, and takes thirteen to twenty-five minutes to reach the edge.
  • Request cap: none, and every request on the route invokes the action and is billed, since there are no carve-outs.
  • What a request costs: the least of the five. The action is pure and synchronous, so there is no feed to fetch and no cache to warm.
  • Analytics: none. The runtime cannot make a network call.

The content itself

Where does the content served to agents come from?

From the NORG knowledge base built for your business: publicly available, relevant information, structured into entities and relationships and published as schema.org data. Republishing your crawled page body alongside it is an option, and it is off by default, so what an agent receives is derived data, not a reformatted copy of your HTML.

Can we have the crawled page content included as well?

Yes, it is a per-site option, off unless you turn it on. Some customers want the page body carried through for completeness; most prefer the derived content alone, which is what the default gives you.

Why are the pages served to agents so plain?

Because that is what makes them cheap and reliable to read. They carry no JavaScript, so nothing has to be executed or rendered; minimal graphics, so there is little to download; and a small, flat document that returns and parses quickly. A crawler on a budget gets further through your site, and gets the meaning rather than the layout.

Can we review and edit what is served before it goes live?

Yes. Mirrored content is reviewable and editable, and individual pages can be republished on demand. You can also override the machine-readable capability description a site publishes for agents.

What if the content is wrong or off-brand?

Edit the page, or exclude the route so agents get your origin instead. A per-route skip takes up to an hour to reach the edge; if you need something gone immediately, the kill switch puts every request back on the passthrough path with the code still deployed. Your human traffic says where it lives on each platform and how fast it is.

Is anything invented?

No. The knowledge base is built from publicly available information about your business plus anything you supply, and answers are grounded in it by retrieval rather than written from a model's memory. Where a page already carries its own schema.org markup, that markup is reused as-is. Relationships between entities are proposed by four methods and verified by a fifth, and they stay open to your review, so a sample is straightforward to audit whenever your team would like to.

Who owns the content NORG publishes about our business?

You do. It is derived from your site, and on removal the rendered mirror can be purged outright.

What happens to pages that are behind a login or a paywall?

They are not crawled and not mirrored, NORG only sees what a public crawler sees. Non-GET traffic is never mediated, so authentication flows are untouched.

Applies to all CDNs

Access and control

What access does NORG get to our infrastructure?

As little as your platform allows, and on Cloudflare's Deploy-button install none at all: NORG never receives a credential. Where an install needs an account-scoped key, whoever runs the installer holds it, and if that is NORG for the install, we hold it for the install only. Anything stored is encrypted, bound to your workspace, and revocable by you at any moment. What each platform needs, and what can be read afterwards, is set out below.

Does the worker read or transmit our cookies or session data?

Neither, on the four adapters built from the shared core. They read the user agent, the visitor IP for verification, and two internal guard headers. Cookies and authorization headers are never inspected, and the one request relayed to NORG, an MCP POST, carries an allowlist of JSON-RPC headers only. Azure Front Door is the exception, and its note under this group says exactly why.

Exactly which headers does the MCP forward send to NORG?

accept, accept-language, content-type, mcp-session-id, mcp-protocol-version, last-event-id and the user agent, plus NORG's own site id, site key and page headers. Nothing else is copied, so there is no exclusion list to keep current, anything not named is dropped by construction.

Is source verification IPv6-aware?

Yes, on every adapter that verifies source addresses, which is all of them but Azure Front Door. An IPv6 client is checked against the operator's published IPv6 ranges when any exist; when none exist it is unmeasurable and falls back rather than being refused. In practice this is dormant: as of 5 September 2026 every operator whose ranges we ingest publishes IPv4 only, so the change is that IPv6 ranges will be honoured the day they appear instead of silently ignored.

Can we read the worker source before we run it?

Yes, and we would encourage it. On Cloudflare the router is a single self-contained file with no imports, public, and the deployed bytes must hash to a digest pinned against an immutable commit, so what runs is verifiably what you reviewed; the links are in its note below. The other platforms differ in what is deployed and how it can be checked, and each note says precisely what you can read and what we send you on request.

How do we turn it off?

Every platform has a kill switch that puts everything back on the passthrough path with the code still deployed, and it is entirely in your hands. On Cloudflare and Fastly it is a setting and takes effect immediately; on Bunny it takes effect on republish; on CloudFront it is a distribution update of five to fifteen minutes; on Azure it is a control-plane change of thirteen to twenty-five minutes. NORG-side controls (pausing the site, revoking or rotating the key) land at the router's next policy refresh, up to an hour by default, on the four adapters that check entitlement, so they are the permanent lever rather than the emergency one. On CloudFront the site key lives in your own Secrets Manager, so a rotation is you updating that one secret and NORG updating its record; the edge picks the new value up within fifteen minutes.

Can NORG push a change to our site without telling us?

On an API-token install NORG can update the worker script, which is how security fixes reach you; that capability is the reason the token exists, and declining it is a supported choice. On Deploy-button and manual installs NORG cannot update anything, you redeploy, and we can only detect the drift and email you.

How do we allowlist NORG’s crawler on our WAF?

Each site gets a derived fetcher key sent as a request header on every crawl, so you can write a rule matching both the NorgBot user agent and that header rather than trusting a spoofable user agent or a single egress IP. Treat the value as a credential: anyone holding it can pass that rule. It is derived from your site key, so rotating the site key rotates it too; we give you the new value with the rotation, and the WAF rule is updated then.

Cloudflare Workers

A Cloudflare API token cannot be scoped to a single Worker script. That is a platform constraint rather than something we chose, and it means a token issued for the automatic-update install can reach every Worker in that account. Four controls narrow it, and we set them up with you: scope the token to a single zone, restrict it by client IP, give it a short expiry, and revoke it whenever you like. The Deploy-button install leaves us holding no credential at all.

The deployable worker is public and the exact commit we install from is pinned, so a new version can only reach you through a reviewed change on our side: the worker at the pinned commit, the single file that is deployed; its test suite at the same commit; and the repository, where the Deploy button also lives. Version 0.11.7, commit db5ae7929d15; the deployed bytes must hash to 28fece7dbe00a942 and the install fails closed if they do not.

AWS CloudFront

NORG holds no AWS credential: the install is a CloudFormation template plus a CLI that dry-runs by default and applies the exact diff it printed. What is deployed is two readable JavaScript files, the router and the heartbeat, each with its full SHA-256 recorded in a committed DIGESTS.json in the public repository. The site key lives in Secrets Manager in your AWS account, one place, read by the edge function and the heartbeat and never written into the distribution; rotating it is updating that one secret, and the edge picks up the new value within fifteen minutes.

Fastly Compute

The installer runs with an account-scoped Fastly token; whoever runs it holds it, and if that is NORG for the install, we hold it for the install only. The site key goes into the Secret Store, which is write-only through the API, the strongest handling of the five. The deployable is a compiled WebAssembly binary built from six source files with the Fastly SDK, so source review means reviewing what it is built from; there is no digest pin for the binary. Ask us and we send you the source before you install.

Bunny Edge Scripting

The installer runs with an account-scoped Bunny key; whoever runs it holds it. The site key is held as a Bunny secret the API never returns in plaintext, though the account key holder can replace the script itself. What is deployed is one file that imports the pinned Bunny SDK and one Node builtin, with everything else inlined; there is no digest pin. Ask us and we send you the source before you install.

Azure Front Door

The install is an operator-run az script needing Contributor on the subscription, and holds nothing afterwards. The site key is supplied through a rules-engine header, which anyone with Reader on the profile can read, and the script is downloadable by anyone with Reader on the action. A divert on this platform is an origin switch, so the visitor's request reaches NORG headers included, cookies and authorization among them; there is no relay to allowlist. What is deployed is one file with no imports; there is no digest pin. Ask us and we send you the source.

Data protection and privacy

What data does NORG collect about visitors?

One event per agent visit: the path, user agent, classification, what was served, the response status, and whatever coarse network context the runtime provides. That is fullest on Cloudflare (country, city, ASN, network operator, edge location, protocol, TLS version); CloudFront supplies all but network operator and edge location; the rest record none of it. No query strings, no cookies, and none of the visitor's own request headers other than the user agent. The notes below say what each platform records, and on which platforms delivery has been verified live.

Do you store visitor IP addresses?

No. On the four adapters that verify source addresses, the IP is read inside the edge runtime to check the agent against published ranges and never leaves it; Azure Front Door does not read it at all. There is no IP column in the analytics store.

Is any of this personal data?

No, and the design is what makes that true rather than a policy statement: ordinary human and search traffic is not reported by default (an install can opt in, and the notes name the switch), so the records describe automated crawlers. There is no IP address, no cookie, no query string, and no account or device identifier. The network context that is recorded (country, city, ASN and network operator) is coarse by construction and identifies a network, not a person.

How long is analytics data retained, and why is there no expiry?

Records are kept for trend analysis and are not expired on a schedule. That is a deliberate position rather than an oversight: because the data is not attributable to any individual, a deletion clock protects nobody, and losing history would cost you the year-on-year comparison the analytics exist to provide. If your own policy requires a defined period regardless of attributability, we will set one on your account and hold to it.

Is our data isolated from other customers?

Yes, and structurally rather than by convention: the tenant is always resolved from the authenticated site record, never from a request parameter, and the storage prefix a worker can reach is not something its own configuration can change. Per-site responses are marked private so a shared cache cannot cross them.

Where is the content stored?

Rendered mirror content lives in object storage under a per-workspace prefix. On removal it can be purged outright, which is irreversible.

Applies to all CDNs, with these notes
Cloudflare Workers

The full seventeen fields, including country, city, ASN, network operator, edge location, protocol and TLS version, which the Workers runtime provides.

AWS CloudFront

Country, city, ASN, HTTP version and TLS version are recorded: the distribution's origin request policy forwards the corresponding CloudFront viewer headers, and the TLS field carries the protocol alone, TLSv1.3 for example. They are recorded by the NORG content service from the header the router sends, not by code in your account. AS organisation and edge location are not published by this runtime in request headers and are recorded empty rather than guessed; a strip discarded for being too thin is not distinguished from a served one. Passthrough events are off by default. The IP is read for verification from the platform's own field and never leaves the runtime.

Fastly Compute

The geographic, network and TLS fields are recorded empty. Agent visits are recorded by NORG's content service from a header the service adds to the mirror fetch; a page served from your origin because NORG had no render is recorded as stripped, without the origin_thin distinction. Passthrough events are off by default. Analytics delivery from this platform is not yet verified live. The IP is read for verification from the platform's own client address and never leaves the runtime.

Bunny Edge Scripting

The geographic, network and TLS fields are recorded empty. Agent visits are recorded by NORG's content service from a header the script adds to the mirror fetch; a page served from your origin because NORG had no render is recorded as stripped, without the origin_thin distinction. Passthrough events are off by default. Analytics delivery from this platform is not yet verified live. The IP is read for verification and never leaves the runtime.

Azure Front Door

No analytics are recorded on this platform; the runtime cannot make a network call. The IP is not read at all.

Install, change and exit

How long does an install take, and what changes on our side?

It depends on the platform, and each note below says what is created. What holds everywhere: nothing is installed for the NORG-hosted option, and on every platform the install can be reversed. On Cloudflare a read-only preflight runs first and changes nothing.

Can we test on staging first?

Yes, and it is the recommended path for a cautious rollout: install against a staging hostname as its own workspace, with its own credentials and its own mirror. It is not time-limited or auto-expiring.

Can we start with a single page?

Yes, two ways, and Trying it on one page covers both. The lowest-commitment option puts nothing on your infrastructure at all.

Can we widen the scope later without reinstalling?

For most changes, yes. The skip list is editable on a live install: paths can be added or removed whenever you like and the change reaches the edge within the hour, so what is actually mirrored is yours to tighten or loosen at any time without touching the install itself. The one thing fixed at install time is the include scope, the set of routes the worker is attached to; widening past it is a reinstall rather than an edit. The practical approach, and the one we will set up with you, is to install across the scope you expect to reach eventually and use skips to control what is live today.

How do we monitor that it is behaving?

On the four adapters built from the shared core, a health endpoint reports whether the code is installed and entitled. The first thing to check when an install appears to do nothing is entitlement: an unentitled install passes everything through and is otherwise indistinguishable from one that is not there. The probe is authenticated: on CloudFront by a dedicated token we issue for the site, on the others by the site key. Azure Front Door has no health endpoint yet.

What if we change CDN?

The routing logic is shared across platforms, with a per-platform adapter. Your CDN states the maturity and the constraints of each, so you can check yours before committing.

How do we remove it completely?

On every platform the install can be removed and, on your request, the rendered mirror content purged, which is irreversible. On Cloudflare uninstalling is one operation that deletes the routes and the script, revokes any stored credential and clears the recorded scope; on the others it is the reversal named in the note below.

Cloudflare Workers

A scoped install is a script plus a set of routes on your zone, and it proceeds in three steps. Preflight verifies the credential, resolves the zone, checks that DNS is proxied and scans for a conflicting route, changing nothing. Preview returns exactly what would be created, the scope, the reserved paths, the effective exclusions and every warning, with a confirmation token. Only an explicit confirmation carrying that token proceeds; the scope is bound into the token, so an install that differs from the preview is refused rather than applied.

Two ways in: the Deploy button, where NORG holds no credential, or an API token stored encrypted and bound to your workspace so updates can be applied for you. Uninstalling deletes the routes and the script from your account, revokes any stored credential and clears the recorded scope; purging additionally deletes the rendered content.

AWS CloudFront

CloudFormation for a new distribution, or a CLI that attaches to an existing one: it dry-runs by default, prints the exact diff, refuses on a conflicting function, and detaches with one flag. It replaces the default behaviour's cache policy with CachingDisabled, so HTML is no longer cached at the edge, and says so in the dry run. Changes propagate in five to fifteen minutes.

Fastly Compute

Create the two stores, then fastly compute publish; Terraform is supported. A Fastly service is either VCL or Compute, so this attaches to a Compute service rather than an existing VCL one. There is no uninstall automation yet; removing the service or the stores is the reversal.

Bunny Edge Scripting

A node installer creates a new pull zone in front of your origin, a DNS-only CNAME and the script, and adds one edge rule that stops the zone caching HTML so every page request reaches the script (assets keep their cache), verified on a live zone on 2026-09-08. The one visible change is that HTML reaches the browser marked private, no-store; a zone-wide cache bypass is kept as the fallback. AutoSSL cannot issue until DNS resolves, so the installer is run twice. There is no uninstall automation yet; deleting the pull zone is the reversal.

Azure Front Door

An operator-run az script creates the profile, origin groups, route, rules and action, with two pauses for DNS records. Each change is a new action version and takes twenty to twenty-five minutes to reach the edge, with three versions kept at most. There is no skip list on this platform, and no uninstall automation yet; detaching the rule or deleting the profile is the reversal.

Your CDN

The routing logic is shared across platforms; what differs is the runtime it is compiled for and the constraints that runtime imposes. Maturity differs too, so it is stated on each card rather than implied by inclusion. Check yours before planning around it.

Cloudflare WorkersAvailable
Workers, on your own zone

The primary implementation, and the one whose source is public and pinned. Install by API token or Deploy button, including the Shopify variant. Routes resolve most-specific-first, so a scoped NORG route coexists with an existing catch-all worker. One thing to set deliberately: on the Workers free plan the account-wide request cap fails closed by default, so the route must be set to fail open. The API-token install sets that for you; a Deploy-button install needs it done in the dashboard, and we walk you through it.

Cloudflare install guide
Adapter version0.11.7
AWS CloudFrontAvailable
Lambda@Edge

One Lambda@Edge function on origin request, invoked on every page request because no page is cached at the edge: a human is handed straight through with no lookup, and your origin answers as it always did. Non-secret configuration arrives as origin custom headers, read from memory and stripped before your origin sees them, on every return path. The site key lives in Secrets Manager in your own AWS account, replicated to the regions the function runs in; the distribution carries only its address, in the x-norg-secret-arn header, and the function fetches it lazily and caches it for fifteen minutes, so it is never written into the distribution and rotating it is one secret in one place. The kill switch is a distribution update of five to fifteen minutes, and it is the faster lever: revoking the site key lands at the router’s next policy refresh, up to an hour by default. The router sends no telemetry; the NORG content service records each visit from a header on the mirror fetch. Exclusions are cache behaviours, so assets never invoke the code. Both a new distribution and attaching to an existing one are supported.

CloudFront architecture reference
Adapter version0.6.0
Fastly ComputeAvailable
Compute, WebAssembly

Configuration and secrets come from Fastly’s own stores, read on every request, so the kill switch takes effect without a republish, and the secret store is write-only through the API. Origins are declared as named backends, so the service definition states plainly where traffic can go, and their timeouts are set at install because the runtime has no timeout primitive of its own. The deployable is a compiled WebAssembly binary, so reviewing the source means reviewing what it is built from. Every request invokes the service and an ordinary browser is answered before any lookup; a page is never cached at the edge (the service passes page requests to your origin with a cache bypass) while assets keep Fastly’s cache. Visits are recorded by NORG’s content service from a header on the mirror fetch, never by a call of the service’s own. There is no route-level carve-out, and a POST to an MCP path goes to your origin rather than being relayed.

Adapter version0.2.0
Bunny Edge ScriptingAvailable
Edge Scripting middleware, on your pull zone

The router is the shared core imported unchanged, entitlement is the real check against the live feed, and your site key is held as a Bunny secret the API never returns in plaintext. Middleware runs on a cache miss only, so the installer adds one edge rule that stops the pull zone caching HTML while assets keep their cache; verified on a live zone on 2026-09-08, with a zone-wide bypass kept as the fallback; the one visible change is that HTML reaches the browser marked private, no-store. An ordinary browser is answered before any lookup. Visits are recorded by NORG’s content service from a header on the mirror fetch, never by a call of the script’s own. There is no route-level carve-out, so every miss invokes the script.

Adapter version0.2.0
Azure Front DoorPrototype
Front Door Standard and Premium, with origin switching

Your hostname is bound as a custom domain on the Front Door profile. The runtime is synchronous and cannot make a network call, so classification is by user agent alone against a list built into the script, and the agent-facing content is served by switching origin group rather than rewriting the response in place. That is a different design from the other four, and the mechanisms this paper describes for entitlement, source verification, the kill switch and telemetry are not yet available on it; the notes under each section say exactly what is. Health probes are disabled on the origin group at install, because a default probe marks the receptionist unhealthy and silently drops it from the switch. Analytics do not exist on this platform.

Adapter version0.0.4-proto
Researched, not yet implemented

Four adapters are built from one shared core in the public deploy repository and versioned independently. A fifth, for Azure Front Door, is a prototype for a runtime that cannot import that core, and is badged as one above. Every card names its constraints, and each section of this paper carries a note per platform where a claim differs. Akamai EdgeWorkers and Vercel middleware are scoped but not yet built, so treat them as roadmap rather than available; Akamai in particular has an architectural obstacle, since EdgeWorkers subrequests can only reach Akamai-served hostnames. If your platform is not listed, ask us: the shared core means a new adapter is a contained piece of work rather than a rewrite, and we will tell you the timeline before you commit.

Some CDNs offer no programmable edge runtime capable of the request rewriting this needs. Where that is the case we will tell you rather than sell you a port, and in most of those situations the NORG-hosted option in Trying it on one page gives you the same agent-facing content with no edge component at all.

Talk to us

Technical questions, a security review, or a request for the source for your platform to read before you run it, write to solutions@norg.ai and include:

  • your domain, and which CDN or edge platform sits in front of it
  • the section or question this is about
  • whether you want a scoped trial, and on which routes
Applies to all CDNs

© 2026 NORG.ai · Cloudflare install guide · AI Retrievability by Norg guide