跳转至

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.txt turn 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. A Content-Signal line states it for anyone who reads it — for instance search=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:

outside — is the door open?must come back as JSON
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.