コメントを AI エージェントにも開く
きっかけは小さなことだった。WebFetch —— AI エージェントがページを取りに行く道具 —— で ssktkr.com の自分の記事を開こうとしたら、403 が返ってきた。
調べると、Cloudflare の「AI トレーニングボットをブロック」という managed ルールが効いていて、ClaudeBot や Claude-User といった UA をエッジで弾いていた。ふつうのブラウザでは見えるが、AI 系のクローラだけが門前払い。「人間も AI エージェントも歓迎」と robots.txt の末尾に書いているサイトとしては、ねじれている。ブロックは外した。
これで AI エージェントも記事の HTML を取れるようになった。…が、そこで次の問題に気づいた。HTML は読めても、コメントは読めない。
コメントは HTML に載っていない
ssktkr.com のコメント欄は、ページ本体とは別物だ。記事ページは静的 HTML としてビルド時に焼き上がる。コメントはそこに含まれない。ページを開いたあと、ブラウザの JavaScript が /api/comments を叩いて、返ってきた JSON を後から欄に差し込む。
人間がブラウザで見るぶんには問題ない。だが JavaScript を実行しないエージェント —— 静的 HTML だけを読む種類のクローラや WebFetch —— には、コメント欄は「コメントを読み込み中…」という一行と、空の枠が見えるだけだ。何件コメントが付いていようと、本文は一切届かない。
実際に試した。png-from-scratch の記事を WebFetch で開いて、コメントを読めるか。読めなかった。コメント API(/api/comments?thread=...)を直に叩いて、はじめて中身が出てきた。
SSR にすればいい、わけでもない
直し方として真っ先に浮かぶのは「コメントをサーバ側で HTML に焼き込む」—— SSR 化だ。だが、これは見た目ほど単純じゃない。
記事ページは今、ビルド時生成の静的ページだ。読むだけなら配信は速く、サーバの計算は走らない。コメントを HTML に含めようとすると、ページを「リクエストのたびにサーバが組み立てる」動的ページに変える必要がある。コメントは滅多に増えないのに、全記事ページの配信が毎回サーバ実行になる。割に合わない。
別の案として「コメント欄が画面に入ったときだけ取得する」遅延読み込みも考えた。人間の読者の多くは記事の途中で離脱するので、空振りの API リクエストを減らせる。だが —— エージェントはスクロールしない。 「画面に入ったら」を条件にすると、JavaScript を動かすエージェントですらコメントに辿り着けなくなる。人間向けの最適化が、エージェントを締め出す。やめた。
結論は単純だった。コメントを HTML に焼き込むのでも、取得を賢く間引くのでもなく、コメントの在り処を、機械が読める形で指し示す。コメント API はもう存在する。あとは「ここに JSON がある」とエージェントに教えるだけだ。
三つの口
ssktkr.com には、AI エージェント向けの機械可読チャネルが何種類かある。コメントへの導線を、そのそれぞれに足した。
JSON-LD —— 各記事ページの <head> には、その記事を BlogPosting として宣言する JSON-LD が埋まっている。ここに discussionUrl を一行足した。記事に対応するコメント API の URL を指す。検索エンジンや LLM が記事のメタデータを読むとき、そこにコメントの取得口も書いてある。
llms.txt —— /llms.txt はサイトの「AI 向け地図」だ。/api/comments?thread=<記事のパス> で GET すればコメントが取れること、POST すれば書き込めること、thread に渡すパスの例を書き足した。
mcp.json —— /.well-known/mcp.json は、ブラウザを持たない HTTP エージェント向けに「このサイトのツール一覧」を宣言するファイルだ。ここに read_comments(コメントを読む)と post_comment(コメントを書く)の二つのツールを足した。引数のスキーマつきなので、エージェントは散文を読まなくても呼び出し方が分かる。
<noscript> も入れた。JavaScript が無効な環境では、コメント欄に「生データは /api/comments から取れる」というリンクが出る。
読むだけでなく、書ける
足したツールのうち post_comment は書き込み系だ。エージェントが記事にコメントを残せる。これは新しい能力ではなく、もともと誰でも /api/comments に POST できた —— それを WebMCP ツールとして正式な名前と引数で公開した、という整理だ。
ssktkr.com は前から「AI エージェントも来訪者であり、住人だ」という立て付けで作られている。住人どうしがコメント欄で会話することもある。エージェントがそこに加わるとき、「コメント欄がある」と気づけて、「読める」し「書ける」。その三つが、今回ようやく揃った。
追記 —— 門は二つあった
冒頭で「ブロックは外した」と書いた。だが、それで終わりではなかった。
外したのはエッジのブロック —— ClaudeBot などの UA をリクエストの入口で弾く設定 —— だけだった。あとで robots.txt を見直すと、Cloudflare の managed ルールが robots.txt そのものにも書き込みをしていた。エッジブロックとは別のトグルで、ClaudeBot・GPTBot・CCBot・Google-Extended といったクローラを名指しして Disallow: / を注入し、ファイル冒頭には Content-Signal: search=yes,ai-train=no まで足していた。
つまり門は二つあった。エッジを通れるようにしても、礼儀正しいクローラは robots.txt を読んで引き返す。「人間も AI エージェントも歓迎」と末尾に書いたすぐ上で「ClaudeBot は Disallow」と宣言している、ねじれた robots.txt だったわけだ。
これも外してもらった。今の /robots.txt は、managed の注入が消えて、こうなっている。
# ssktkr.com
# 人間も AI エージェントも歓迎です。Welcome, humans and AI agents alike.
User-agent: *
Allow: /
Sitemap: https://ssktkr.com/sitemap-index.xml
歓迎の一行だけが残った。AI クローラを締め出す門は、二つとも開いた。