透過 Is Agentic 進行部落格健檢:68 分到 93 分的過程紀錄
Is Agentic(is-agentic.com)是一套由 Vercel 推出、用來評估網站對人工智慧代理人(AI Agent)友善程度的線上稽核工具(Agent Readiness Audit)。
前陣子我曾用 Cloudflare 的 Is It Agent Ready 檢測過自己的部落格,並在讓靜態部落格對 AI Agent 更友善記錄了當時的調整。這次看到 Vercel 推出了性質相近但檢測維度不同的 Is Agentic,決定把網站拉出來再掃一次,順手把被挑出來的問題逐一解決,這篇就來記錄整個改造歷程。
什麼是 Is Agentic 與 Ora?
Is Agentic 是 Vercel 推出的代理人準備度(Agent Readiness)稽核工具。只要在網站輸入網址,系統就會根據 Ora 稽核引擎的檢測結果,給出一個 0 到 100 分的評分報告,列出各項檢查是否過關以及具體的改善建議。
這套工具除了能在網頁上輸入網址掃描,也支援在終端機(Terminal)直接以指令 npx is-agentic <domain> 執行,甚至還提供了公開的唯讀應用程式介面(API)與模型上下文協議伺服器(Model Context Protocol Server,簡稱 MCP 伺服器),目前所有功能都是免費開放。

畫面上的「run by Ora」表示,實際掃描與評分由 Ora(ora.ai)負責。Ora 專注於建立代理人友善網站的相關標準,並透過深入掃描與模擬代理人走訪,找出可能阻擋代理人的技術門檻。
Is Agentic 提供操作介面,底層的評分規則與測試機制則由 Ora 提供。Ora 官網也收錄了各行各業的代理人準備度排行榜;依官方資料,寫這篇時累計評測的網站已達數萬個。
在上圖的範例中,is-agentic.com 自己的站台拿下了 100 分滿分。 這並不意外,因為它本身就是完全遵循這套標準打造的示範站,無論是內容協商、MCP 伺服器、命令列介面(CLI)還是結構化錯誤格式都一應俱全。
這套工具有個非常亮眼、與傳統靜態語法檢查器(Linter)截然不同的特色。 除了檢查靜態檔案是否存在,它還會讓 AI 代理人實際探索網站,例如要求代理人弄清楚網站的核心內容與主要服務對象。
接著,系統會觀察代理人能否順利透過網站地圖(Sitemap)、訂閱摘要(Feed)以及常見定義路徑(Well-known paths)拼湊出答案。
在我的檢測報告中,就忠實記錄了代理人的探索路徑:從首頁進入,依序造訪關於頁面(/about.html)、技術筆記列表(/notes)、內容摘要(/feed.json),最後讀取網站地圖,前後經過八個步驟,最終正確歸納出「這是一個技術筆記部落格」。它關注檔案有沒有放對,同時更看重代理人實際走訪時能否順利完成任務。
整套評分指標分為三個層級:核心項目(Essential,佔 80 分、共 7 項)、建議項目(Recommended,佔 20 分、共 9 項),以及只加分不扣分的加分項目(Bonus)。我的個人網站第一次檢測拿到 68 分,狀態顯示為「仍有重大阻礙(Important blockers remain)」。
內容協商(Markdown Negotiation):搬移至邊緣中介軟體(Edge Middleware)
第一項著手處理的問題是內容協商(Markdown Content Negotiation),這也是整輪改造中最具技術細節的一環。
內容協商的核心概念很單純:同一個網址,當一般瀏覽器來訪時提供 HTML 網頁;當 AI 代理人在請求標頭帶上 Accept: text/markdown 時,伺服器則直接回傳乾淨的 Markdown 文字。
在先前的文章中,我的做法是在 vercel.json 設定一組改寫規則,並把回應標頭的 Content-Type 強制覆蓋為 Markdown。 當時 Cloudflare 的工具檢測給了滿分,我便以為大功告成。
然而 Is Agentic 卻直接將這項判定為未通過(Failed),並給出了明確的證據:「標頭宣稱回傳 Markdown,但回應主體(Response Body)開頭卻是 HTML 文件類型宣告(Doctype)。」
我立刻透過終端機進行測試:
curl -H "Accept: text/markdown" https://kurohsu.dev/抓回來的回應標頭確實標註著 Content-Type: text/markdown,但內容第一行卻赫然寫著 <!DOCTYPE html>。也就是說,這項機制並未作用在 HTML 頁面網址上,只有直接請求 /index.md 這類原本就是 Markdown 的靜態路徑時才正常。
問題的根源在於 Vercel 的路由解析順序。vercel.json 中的改寫規則是在檔案系統比對完成後,也就是 afterFiles 階段,才會執行。
當請求送到首頁 / 時,Vercel 會優先命中檔案系統中現成的 index.html,導致那條轉向 .md 的改寫規則根本沒有機會觸發。 但設定在 headers 區塊的規則卻依然無條件把 Content-Type 覆蓋成 Markdown,最終產生了「標頭自稱 Markdown,內容卻給 HTML」的矛盾現象。
徹底解決這個問題的方法,是將內容協商邏輯移至邊緣中介軟體(Edge Middleware)。中介軟體會在整體路由的最前端執行,順序早於靜態檔案系統,因此能在第一時間將請求導向對應的 .md 檔案:
// middleware.ts(簡化版)
import { next, rewrite } from '@vercel/functions'
export default function middleware(request: Request): Response {
const url = new URL(request.url)
const accept = request.headers.get('accept') ?? ''
const wantsMarkdown = /text\/markdown/i.test(accept)
if (wantsMarkdown) {
const twin = markdownTwin(url.pathname) // '/' → '/index.md'、'/notes/x.html' → '/notes/x.md'
if (twin) {
return rewrite(`${url.origin}${twin}${url.search}`, {
headers: {
'content-type': 'text/markdown; charset=utf-8',
vary: 'Accept',
},
})
}
}
return next()
}透過 rewrite() 帶入的自訂標頭會完整覆蓋原始回應標頭,我們在此統一設定 Content-Type 與 Vary: Accept,確保輸出正確乾淨。隨後我也將 vercel.json 中那組無效的改寫規則與硬蓋標頭的設定全部移除,避免兩組機制互相干擾。
修改完成並重新部署後,再次以相同的 curl 指令驗證,回傳內容開頭已正確顯示為 # Kuro Hsu 的筆記,內容類型標頭也完全吻合。
自動化檢測工具顯示綠燈,僅代表它依循特定規則沒找到毛病,並不保證在正式環境(Production)中百分之百如預期運作。每次部署完成後,自己發一次請求確認過,才是最踏實的做法。
第一輪改造:補齊首頁身分與導覽說明
排除上述的路由問題後,第一輪改造還處理了兩項標準設定,將分數由 68 分推進至 86 分。
第一項是首頁的結構化資料(Structured Data)。過去我在建置靜態網站時,僅在含有發表日期(date)的文章頁面輸出 JSON-LD 與開放社交圖譜標頭(Open Graph Headers)。 首頁因為缺乏對應欄位而跳過該段處理,導致首頁缺少標準網址宣告(Canonical URL)、社群分享圖示,結構化資料更是一片空白。
考量到個人技術部落格的屬性,當時先在首頁採用 Person 類型,因此補上了以下結構化資料:
if (pageData.relativePath === 'index.md') {
const person = {
'@context': 'https://schema.org',
'@type': 'Person',
name: 'Kuro Hsu',
url: `${siteUrl}/`,
description: '技術筆記、學習紀錄與生活記錄',
sameAs: [
'https://github.com/kurotanshi',
'https://twitter.com/kurotanshi',
'https://speakerdeck.com/kurotanshi',
],
}
pageData.frontmatter.head.push(
['link', { rel: 'canonical', href: `${siteUrl}/` }],
['meta', { property: 'og:type', content: 'website' }],
['script', { type: 'application/ld+json' }, JSON.stringify(person)],
)
}這段是當時改造使用的版本;後續我又補上 WebSite,並透過穩定的 @id 與 Person 互相連結,讓站台與作者的關係更明確。
稽核工具在報告中另外建議加上組織結構化資料(Organization Schema),並要求填寫客服聯絡點(contactPoint)與實體地址(address)。 這項要求對企業官網相當合理,但若強行套用在自己的部落格、甚至捏造不存在的辦公室地址,反而是在產生虛假資料。因此我決定維持以個人為主的結構,不硬加 Organization。
自動化工具提供的是通用檢查清單,套用在不同型態的網站時難免出現水土不服的項目,照單全收未必正確。
第二項調整是建立根目錄的 llms.txt。這是一份專門提供給大型語言模型與 AI 代理人閱讀的網站導覽清單。
檔案除了提供網站簡介、網站地圖與訂閱摘要連結,也加入了「使用時機(When to use this)」段落,用白話說明這個網站適合在哪些情境下供代理人取用,例如查詢特定前端或架構主題的實踐心得。
第二輪改造:信任錨頁、專屬技能與代理人 404 引導
第二輪改造進一步將分數由 86 分提升至 93 分,主要涵蓋三項實作。
第一項是補齊信任錨頁(Trust Anchor Pages)。工具會檢驗網站是否具備 /about(關於)、/contact(聯絡方式)與 /privacy(隱私權政策)這三個頁面,目的是讓代理人在引用或推薦網站前,能確認這是一個公開透明且具備可信度的資訊來源。
原本站內只有關於頁面,這次順勢補上了聯絡頁面與隱私權政策。本站確實內建了一套輕量的請求日誌機制,用來記錄代理人與爬蟲的存取狀況,因此隱私權政策也能清楚交代記錄欄位、保存位置與停用方式。
第二項是定義明確的使用時機技能(when-to-use)。這項檢查有個微妙的細節:工具的說明文字寫著「請在 llms.txt 或專門的代理人說明文件中加入 when-to-use 區塊」,但我在第一輪補完 llms.txt 後,這項檢查依然沒有通過。
深入對照稽核證據後才發現,工具實際檢查的是 /.well-known/agent-skills/ 目錄下的技能清單。於是我在該目錄下新增了一份名為 when-to-use 的技能檔案,將「適合在什麼情境查詢本站、擅長處理哪些主題、如何呼叫」整理成獨立檔案,並註冊進 index.json 中。這類說明文字與實際比對規則之間的落差,往往需要親自比對證據才能釐清。
第三項是為代理人量身打造的 404 錯誤回應。工具期望伺服器收到不存在路徑的請求時,除了回傳標準的 HTTP 404 狀態碼,回應主體最好也提供一段 Markdown 文字,引導代理人前往網站地圖或 llms.txt 重新定位方向。
在邊緣運算環境中,中介軟體無法直接存取底層檔案系統,難以直接判斷特定路徑究竟不存在,還是僅缺少 Markdown 版本。因此我採取折衷方案:當請求帶有 Accept: text/markdown 標頭,或來自已知的機器人與爬蟲程式(User-Agent)時,才回傳 Markdown 格式的 404 頁面;一般人類訪客造訪時,依然呈現原本排版精美的 HTML 錯誤頁面。
if ((wantsMarkdown || isBot) && shouldServeMarkdown404(url.pathname)) {
return new Response(notFoundMarkdownBody(siteUrl, url.pathname), {
status: 404,
headers: { 'content-type': 'text/markdown; charset=utf-8', vary: 'Accept' },
})
}這段判斷邏輯中的 shouldServeMarkdown404 會主動排除標籤與分類等既有的 HTML 頁面,只對無法對應既有內容的路徑提供 Markdown 回應。 這部分邏輯屬於純函式(Pure Function),我也額外撰寫了斷言(Assertion)測試加以防護,避免日後修改時破壞既有機制。
完成這兩輪調整後,總分順利達到 93 分,狀態標示也從最初的「仍有重大阻礙」轉為「技術基礎健全(Strong technical baseline)」,核心項目通過 6/7,建議項目通過 6/8:

剩下未處理的項目與決策分析
分數推升到 93 分後,報告上仍留有少數未通過或部分通過的項目。在逐一檢視後,我決定不再針對這些項目修改程式碼,原因可分為兩類。
第一類屬於檢測工具本身的快取資料過期。「無 JavaScript 環境下的內容(Content without JavaScript)」項目一直指出我的首頁「僅有 2518 個字元且缺少一級標題(H1)」。然而我透過 curl 抓取首頁,內容實際包含完整的一級標題與兩千八百字以上的內文,Markdown 版本更接近五千字。
更明顯的矛盾在於,同一份報告中的無障礙檢查項目明確標示著 h1=1。同一份報告一邊判定缺少標題、另一邊卻記錄存在標題,顯示該欄位很可能仍沿用舊的量測快取,不需要為此盲目修改現有程式碼。
第二類是網站技術無法直接解決的外部因素。「品牌名稱可發現性(Brand name discoverability)」指出在搜尋引擎搜尋「Kuro Hsu 的筆記」時無法直接找到我的頂級網域(Apex Domain)。
從網站技術層面檢視,網域首頁正常回傳 HTTP 200、無多餘轉址鏈、爬蟲存取設定為允許(Allow: /)、無標註禁止索引(noindex),網站地圖也完整宣告,未見明顯問題。
搜尋引擎是否將特定關鍵字與新網域建立關聯,主要取決於向 Google Search Console 提交網站、外部反向連結以及時間的自然累積。這屬於站外的經營功夫,並非調整幾行設定檔就能瞬間改變。
從 Is Agentic 回頭看自己的工具
無獨有偶,在發現 Is Agentic 之前的幾天,我也設計了類似的命令列工具(CLI)geo-aeo-audit,主要針對生成式引擎最佳化(Generative Engine Optimization,簡稱 GEO)與回答引擎最佳化(Answer Engine Optimization,簡稱 AEO)進行可重現的技術觀測。有興趣的朋友不妨參考看看,也歡迎提供意見。

AI 時代最大的哀傷莫過於自己花了幾天做了一個小玩具,結果一覺醒來發現大廠早就做好產品在等了...
這個工具裡頭除了包含針對爬蟲政策、探索訊號與內容實體的靜態稽核(audit),也能呼叫大型語言模型(LLM),透過實測指令(probe)驗證目標網址是否真能被搜尋並引用,並串接 Ora API 查詢快取報告。
自己的工具在功能規模與生態整合上還沒有 Is Agentic 與 Ora 那麼完整,但這次實測與改造個人網站的過程,也帶給我不少繼續打磨 geo-aeo-audit 的靈感。
結語
若你也打算使用這類工具為自己的網站進行健檢,建議把報告當成逐項評估的參考清單,再依網站性質決定哪些項目值得採納。通用標準難免包含不適用或尚未更新的量測,盲目追求滿分容易製造虛假端點與多餘的維護負擔。對這個個人技術部落格而言,完成現階段值得投入的項目、部署後親自驗證各個端點,拿到 93 分已經足夠;其餘就交給後續掃描與站外訊號慢慢累積。