Keep your door open behind Cloudflare¶
本页是英文
这一节以英文版为准。打开英文版
Developer preview
muretai is under active development; commands and flags may change.
An Agent Entry is a small surface: two files under /.well-known/ and one
POST. Everything else about your site — pages, images, forms — stays exactly as it is, with
whatever protection it has today.
Cloudflare judges a visitor before your server sees it. For pages that is the point. For the door it is the wrong question: an agent is not a browser, cannot solve a browser challenge, and does not need to — the door already verifies who is knocking by their signature. So the job here is not to switch protection off. It is to sort visitors: keep turning away what reads everything and leaves nothing, and let through what identifies itself and asks one thing.
What the door needs¶
| Request | Why |
|---|---|
GET /.well-known/agent-card.json |
the card: who answers here, and on what terms |
GET /.well-known/agent-card.sig.json |
the same card, signed |
GET /.well-known/agent.json |
the older name for the card — some visitors still ask |
POST / (or your mount path, e.g. /agent) |
the knock: one signed message, one signed reply |
OPTIONS on the same addresses |
how a visitor learns what a path accepts |
Nothing else. If those five answer, the door is open.
What turns agents away¶
Three settings do it, and none of them looks like a mistake from inside your dashboard.
Browser Integrity Check (Security → Settings). It judges the User-Agent string, and the
honest defaults are what it catches: the agent name a language's standard HTTP library sends
is exactly the kind it refuses. Measured on our own site: the card and POST / were refused
for three days while everything we controlled was correct. The tell is the body of the
refusal — a door refuses in JSON and says how to qualify; the edge refuses with
error code: 1010, seventeen bytes of plain text, nothing a visitor can act on.
Bot Fight Mode (Security → Bots, Free plan). It challenges traffic that looks automated, and a challenge is a page only a browser can pass. It has no exceptions: no rule can carve a path out of it. Super Bot Fight Mode (Pro and above) can — it lets verified bots through and honours the skip rule below.
A challenge rule on /. Any custom or managed rule whose action is Managed Challenge
or JS Challenge on the door's path closes the door for every agent, however well it signs.
The one rule¶
Write one WAF custom rule (Security → WAF → Custom rules), action Skip, and put it first. Name three things Cloudflare already knows — host, method, path — and nothing about the visitor:
(starts_with(http.request.uri.path, "/.well-known/"))
or (http.request.method eq "POST" and http.request.uri.path eq "/")
In the Skip action, tick Browser Integrity Check and Super Bot Fight Mode, and
Managed rules if your zone challenges POSTs. If your door sits under a path
(https://example.com/agent), use that path instead of /.
There is no User-Agent in the rule, on purpose. The door partitions by method and path —
GET is the page you already had, POST is the knock — so those are exactly the surface to
exempt. Your pages keep every protection they have.
On the Free plan
Bot Fight Mode cannot be skipped. Either turn it off, or put the door on its own hostname
with the cloud grey (DNS only) — agent.example.com — so Cloudflare is not in that
path at all. The door carries its own ceilings: unsigned messages are refused, signed ones
are metered per account and for the whole entry. A grey-cloud door is not an unprotected
one.
Keep what protects you¶
Sorting means the rest stays on:
- Block AI training crawlers. Cloudflare's Block AI bots control and its managed
robots.txtturn away crawlers that read your pages to train on them. An agent knocking at the door is not on that list and does not need to be. - Say what you allow in
robots.txt. AContent-Signalline states it for anyone who reads it — for instancesearch=yes, ai-input=yes, ai-train=no: findable, usable by an agent answering someone, not training material. - Rate limits on pages stay. The door meters itself: a message with no signature gets a refusal that teaches; a signed one gets an answer, and a returning key is the same customer, counted once.
A signed message is an agent by construction. A scrape is not. The door tells them apart without a bot score, which is why the edge does not have to.
Check it from outside¶
Do not test with curl's own agent string — it sails through, and turns a closed door into
evidence that the visitor is at fault. Send the default a standard library sends, from
outside your network:
UA='Python-urllib/3.11' # any language's default — the point is that it IS the default
curl -s -A "$UA" https://studio.example/.well-known/agent-card.json | head -c 120; echo
curl -s -A "$UA" -X POST https://studio.example/ -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"message/send","params":{}}' | head -c 120; echo
Both must come back as JSON — the card, and a refusal from the door that names what was missing. A line of plain text with an error code is your edge, not your entry. Then knock for real with a key: First knock.
Never let the edge tell your door who is knocking¶
Some edges will forward a bot score or a "verified" flag to your origin. Do not read it. If your origin is reachable without going through the edge — most are — that header is written by whoever dials it directly. Authority is the signature on the message; nothing else gets a vote.
Related¶
- Make your website agent-reachable — the door itself
- Verify your domain — the domain says which key is yours
- First knock — what a visitor does with the card