用一支 Cloudflare Worker 打通 Agent Readiness 清單
上一篇講完 isitagentready.com 的評分項目 之後,剛好就在想:這一長串檢查項目裡,真的要手動一個一個改靜態檔案、改框架路由、改 CDN 設定嗎?
其實沒必要。這些東西幾乎清一色是「特定路徑回傳特定內容」或「對回應加點 header」,天生就是邊緣層該做的事。用一支 Cloudflare Worker 掛在網域前面,十分鐘就能把清單上大部分的項目補齊。
為什麼選 Worker
三個理由:
- 邊緣執行:所有請求都會經過,不需要動到後端應用程式。
- 一個檔案管全部:robots.txt、llms.txt、
.well-known/*的路由、回應的 Link header 都可以在同一支 Worker 處理。 - 好部署好改:
wrangler deploy一下就上線,改完不需要重新 build 網站。
如果你的網站已經在 Cloudflare 後面,新增一支 Worker 並綁到對應的 route(例如 example.com/*)就完事。
Worker 骨架
以下是可以直接複製的起點,邏輯分成三塊:靜態檔案路由、Content Negotiation、Link header 注入。
// worker.js
const ROBOTS_TXT = `User-agent: *
Content-signal: search=yes, ai-input=yes, ai-train=no
Allow: /
User-agent: GPTBot
Allow: /
User-agent: ClaudeBot
Allow: /
User-agent: PerplexityBot
Allow: /
Sitemap: https://example.com/sitemap.xml
`;
const LLMS_TXT = `# Example Site
> 一句話說明這個站在做什麼。
## 重要頁面
- [關於](https://example.com/about): 網站主旨與聯絡方式
- [文章列表](https://example.com/blog): 所有文章索引
`;
const API_CATALOG = {
linkset: [{
anchor: "https://api.example.com/v1",
"service-desc": [{
href: "https://example.com/openapi.json",
type: "application/vnd.oai.openapi+json",
}],
"service-doc": [{
href: "https://example.com/docs",
type: "text/html",
}],
}],
};
const MCP_SERVER_CARD = {
name: "example-mcp",
version: "1.0.0",
protocolVersion: "2025-11-25",
transports: [{ type: "streamable-http", url: "https://example.com/mcp" }],
auth: { type: "oauth2", metadata: "/.well-known/oauth-authorization-server" },
};
export default {
async fetch(request) {
const url = new URL(request.url);
// 1. 靜態路由
switch (url.pathname) {
case '/robots.txt':
return text(ROBOTS_TXT);
case '/llms.txt':
return text(LLMS_TXT, 'text/markdown');
case '/.well-known/api-catalog':
return json(API_CATALOG, 'application/linkset+json; profile="https://www.rfc-editor.org/info/rfc9727"');
case '/.well-known/mcp/server-card.json':
return json(MCP_SERVER_CARD);
}
// 2. 一般請求:轉發到 origin,順便做 Content Negotiation
const originResp = await fetch(request);
const accept = request.headers.get('accept') || '';
const isHtml = originResp.headers.get('content-type')?.includes('text/html');
if (isHtml && accept.includes('text/markdown')) {
const html = await originResp.text();
return new Response(htmlToMarkdown(html), {
headers: { 'content-type': 'text/markdown; charset=utf-8' },
});
}
// 3. HTML 回應都附上 Link header
if (isHtml) {
const headers = new Headers(originResp.headers);
headers.append('Link', '</sitemap.xml>; rel="sitemap"');
headers.append('Link', '</llms.txt>; rel="service-doc"');
headers.append('Link', '</.well-known/api-catalog>; rel="api-catalog"');
headers.append('Link', '</.well-known/mcp/server-card.json>; rel="mcp-server-card"');
return new Response(originResp.body, { status: originResp.status, headers });
}
return originResp;
},
};
const text = (body, ct = 'text/plain') =>
new Response(body, { headers: { 'content-type': `${ct}; charset=utf-8` } });
const json = (body, ct = 'application/json') =>
new Response(JSON.stringify(body, null, 2), {
headers: { 'content-type': `${ct}; charset=utf-8` },
});
htmlToMarkdown 這個函式我留空——實務上可以用 turndown 之類的函式庫,或直接呼叫 Cloudflare AI Gateway / Browser Run 幫你轉。自己寫也可以,抓 <main> 或 <article> 清掉 script/style 就很夠用。
這兩個常數的穩定程度不一樣,實作時要分開看:
API_CATALOG依 RFC 9727 的 Linkset JSON 格式,回應 MIME 應該是application/linkset+jsonMCP_SERVER_CARD依 SEP-1649 草案;MCP 本身已有正式規格,但 server card discovery 還不是穩定標準
API_CATALOG 已經有 RFC 可以依循;MCP_SERVER_CARD 比較像是提前把 discoverability 的洞先補起來。正式上線前,建議用最新版規範與 isitagentready.com 各跑一次,確認機器真的讀得到。
老實講,/.well-known/api-catalog 跟 /.well-known/mcp/server-card.json 是純靜態 JSON,丟到 public/.well-known/ 給 Pages / Vercel / Netlify 之類的靜態 host 直接送是更輕的做法。
放在 Worker 主要兩個理由:
- Content-Type 控制:
/.well-known/api-catalog依 RFC 9727 沒有副檔名,多數靜態 host 預設會回application/octet-stream,得另外設 MIME 規則;Worker 可以直接回application/linkset+json - 反正 Worker 也要做別的:Content Negotiation、Link header 注入本來就要 Worker,把這兩個 endpoint 順便集中管理,邏輯一目了然
如果你的網站完全不需要 Worker(例如純 Astro / Next.js 靜態站、又不在意 MIME 設定),那這兩個 endpoint 直接擺檔案就好,不用為它們開一支 Worker。
對應到評分項目
上面這支 Worker 覆蓋到的項目:
| 評分項目 | 處理方式 |
|---|---|
| robots.txt | 直接回傳,內含 AI bot 規則與 content-signals |
| sitemap.xml | 由 origin 產生,Worker 不動 |
| Link header | 對 HTML 回應 append 四組 rel |
| Markdown 內容 | 看到 Accept: text/markdown 就轉譯 |
| llms.txt | 直接回傳 |
| AI Bot 規則 | 在 robots.txt 內 |
| Content Signals | robots.txt 的 Content-signal directive |
| API Catalog | /.well-known/api-catalog |
| MCP Server Card | /.well-known/mcp/server-card.json |
剩下 Web Bot Auth、OAuth Discovery、WebMCP、x402、UCP、ACP、Agent Skills 這幾項,要嘛需要跟身分認證整合、要嘛涉及實際的業務能力(電商、付款),不是 Worker 塞個檔案就能解決——這些才是真的要評估「做不做」的部分。
補充:Web Bot Auth 不要自己在 Worker 刻
上面那串裡 Web Bot Auth 特別值得拉出來講。它的核心是讓 bot 用密碼學方式向網站驗證身分,不再依賴 User-Agent 或 IP 這種容易偽造的東西。技術細節依 draft-meunier-web-bot-auth-architecture-02 草案:
- bot 用私鑰簽請求,header 帶
Signature-Input、Signature跟Signature-Agent - 簽名包含
created/expires時戳跟 Key ID(JWK Thumbprint) - 驗證端依
Signature-Agent指向的 key directory 取得公鑰並驗章
Worker 確實有 crypto.subtle.verify 可以實作,但強烈建議直接用 Cloudflare 平台層,原因:
| 自己在 Worker 寫 | 用 Cloudflare 內建 |
|---|---|
| 公鑰存哪裡?KV / Secrets 都不理想 | 在 dashboard 填 key directory URL,Cloudflare 自動拉 |
| 要自己處理 key rotation、JWKS cache | 平台幫你維護 |
| Replay 防護要自己設計短效簽章、必要時另存 nonce | Cloudflare 目前建議用短 expires 降低 replay 風險 |
| 規格還在草案,改了要重寫 | Cloudflare 會跟著規格升 |
實際操作流程(官方文件):
- Manage Account → Configurations → Bot Submission Form
- Verification Method 選 Request Signature
- Validation Instructions 填你的 key directory URL(裡面放 Ed25519 公鑰)
- 用
https://crawltest.com/cdn-cgi/web-bot-auth測你的簽章——回 200 表示 key 認得且驗證通過、401 可能是 key 未登錄或已登錄但驗證失敗、400 表示格式錯
如果是反過來、你要讓自己的 bot 去簽請求給別人,Cloudflare 也有 web-bot-auth npm 套件:
import { signatureHeadersSync } from 'web-bot-auth';
const headers = signatureHeadersSync(request, signer, { created, expires });
簡單分一下:
- ✅ Worker 適合:HMAC 對稱簽章驗證、固定公鑰的 Ed25519 驗證、靜態檔案路由、header 改寫
- ❌ Worker 不適合:Web Bot Auth 完整流程、OAuth JWT + JWKS rotation、跨節點 replay 防護——這些有狀態、有金鑰管理需求,交給 Bot Management / Workers OAuth Provider 之類專屬服務更穩
偷懶版:robots.txt 直接交給 Cloudflare
如果你已經是 Cloudflare 的客戶,上面 Worker 裡的 ROBOTS_TXT 那段其實不用自己維護——Cloudflare 提供 Managed robots.txt,在 dashboard 點一點就好。
操作路徑(官方文件):
- 進入 Cloudflare dashboard,選對應網域
- Security Settings → Bot traffic
- 開啟 Instruct AI bot traffic with robots.txt
啟用後 Cloudflare 會自動:
- 在你網域根目錄掛上一份
robots.txt(如果原本就有,會幫你合併) - 對主流 AI 爬蟲寫入
Disallow: /:ClaudeBot、GPTBot、Google-Extended、Applebot-Extended、Amazonbot、Bytespider、CCBot、meta-externalagent 等 - 預設套用 Content Signals:
Content-signal: search=yes, ai-train=no(允許搜尋、禁止訓練) - 持續維護這份清單,新的 AI 爬蟲冒出來時自動補進去
不想顯示 Content Signals 的政策說明註解,可以在 Control AI Crawlers 區塊取消勾選 Display Content Signals Policy。目前已經有超過 380 萬個網域在用這個服務。
如果只是要 robots.txt,啟用 Managed robots.txt 就完事,Worker 裡那段刪掉就好。Worker 的價值在於:Markdown Content Negotiation、Link header 注入、/.well-known/* 的 JSON 回應——這些 Cloudflare dashboard 還沒包成一鍵服務的部分。
robots.txt 是「禮貌請求」,技術上沒有強制力,會不會遵守由爬蟲自己決定。如果你真的要擋(例如不想被白嫖),要搭配 Cloudflare 的 AI Crawl Control,那是在邊緣層執行阻擋或收費規則,不靠對方自律。
聊聊 Cloudflare 的一盤大棋
寫到這裡會發現一件事:整份 Agent Readiness 清單裡,Cloudflare 的影子無所不在。
| 角色 | Cloudflare 做的事 |
|---|---|
| 標準制定者 | Content Signals、Web Bot Auth、Agent Skills Discovery RFC 都是 Cloudflare 主推 |
| 網站端執行環境 | Workers、Browser Run(內建 WebMCP)、Managed robots.txt |
| AI 端執行環境 | Workers AI(全球 GPU 推論)、Cloudflare Agents(agent 本體部署)、Remote MCP Server |
| 評分裁判 | isitagentready.com 本身就是 Cloudflare 推出的 |
| 商業模式 | AI Crawl Control、Pay Per Crawl 把 AI 爬取變成可收費的資源 |
去年最關鍵的補刀,是把「AI 自己」也收進來。Workers AI 在 2025 年大幅擴張,把 GPU 推論服務鋪到全球 190 多個城市,serverless 計費,模型直接在邊緣跑;同年 Cloudflare Agents 平台上線,agent 本體也能直接在 Cloudflare 上部署;今年 Agents Week 又補上 Agent Cloud(Dynamic Workers、Artifacts、Remote MCP Server、Project Think),等於宣告:
你的 agent、agent 跑的程式碼、agent 用的工具、agent 拿的資料、agent 發出的網路請求,全部我家包辦。
以前 Cloudflare 是「把你的內容送到使用者面前」的 CDN;現在要做的是「把 AI 整條生產鏈收進自己平台」。從網站要被 agent 讀的那一端、到 agent 本身在哪裡跑、到 agent 出去爬別人網站的那條路,全部都是 Cloudflare 的地盤。
這個組合非常眼熟——早期 Google 用 PageRank、Sitemap 標準、Search Console、廣告網路,差不多就是這一套。只是這次換成了 AI Agent 的世界,玩家換成了 Cloudflare,而且野心更大:Google 當年只要做搜尋的中間人;Cloudflare 想當 AI 整段流程的中間人。
這不是在酸。這套組合拳會成功,是因為每一步都解決了真實的問題:
- 網站主不知道要為 AI Agent 做什麼 → 評分工具告訴你
- 做了也沒人知道標準長怎樣 → Cloudflare 寫 RFC
- 寫了不知道怎麼實作 → Workers / Managed 服務包好給你
- AI 本身要跑在哪 → Workers AI、Agents 平台直接給你 GPU 跟 runtime
- 實作了還被 AI 白嫖 → Pay Per Crawl 讓你收錢
對一般網站主跟開發者來說,其實頗順手。但站遠一點看,Cloudflare 正在把 AI 時代的 Web 基礎設施——標準、執行、算力、計費、稽核——五個層面全部納進自己的產品線。一統天下的味道很濃。
AI Agent 的 Web 比人類瀏覽的 Web 更吃「基礎設施的默契」:agent 要靠機器可讀的 manifest 找資源、靠 well-known 路徑做發現、靠簽章驗證身分。誰掌握這些預設慣例,誰就是新的守門人。
Cloudflare 的佈局看起來就是要當這個守門人。
我的看法
短期來看,Worker 這種解法很實用:一個檔案、一次部署、覆蓋大半項目,成本低到不做白不做。如果你網站還沒在 Cloudflare 後面,多數靜態部分(robots.txt、llms.txt、.well-known/*)其實放到你原本的靜態資源目錄裡就好,不必為這件事搬家。
長期來看,值得持續觀察的是 Cloudflare 到底把多少「提案」推成了事實標準、有多少會被其他大廠(Google UCP、Coinbase x402)搶走話語權。作為開發者,現在不用急著選邊站;作為網站主,把 robots.txt 跟 llms.txt 先弄好,其他的,讓子彈飛一下。
資料來源:
- Managed robots.txt — Cloudflare bot solutions docs
- Web Bot Auth — Cloudflare bot solutions docs
- cloudflare/web-bot-auth — GitHub
- RFC 9727 — api-catalog: A Well-Known URI and Link Relation to Help Discovery of APIs
- Model Context Protocol specification
- Workers AI — Cloudflare Blog
- Cloudflare Agents docs
- Making Cloudflare the best platform for building AI Agents
- Project Think — Cloudflare Blog
相關閱讀:
留言