Works
Blog Recruit Contact AI互換性診断
エージェンティックWeb
calendar_today
[エージェンティックWeb実装ガイド Vol.3] 山下 太郎 山下 太郎

エージェンティックWeb実装ガイド 第3回:問い合わせられるサイト ― NLWebで、Webを会話可能な窓口にする

名乗ったサイトの次は、問い合わせられるサイトへ。NLWebは、Webを自然言語で問える窓口にする。エージェントが問い、サイトが自分のデータから構造化して答える層だ。連載「エージェンティックWeb実装ガイド」第3回、何を答えさせ、何を答えさせないかまで。

エージェンティックWeb実装ガイド 第3回:問い合わせられるサイト ― NLWebで、Webを会話可能な窓口にする

前回、名乗ったサイトが応えるサイトになる、と最後に書いた。今回はその二段目、「問い合わせる」に上がる。

一段目の「見る」で、サイトは自分の意味を機械に差し出した。ただし、それは静的な差し出しだ。名札と地図を置いても、エージェントの側はまだ、ページを集めて読み、目当ての答えを自分で組み立てなければならない。二段目は、その手間をサイト側が引き受ける層だ。エージェントが自然言語で問い、サイトがその問いに、自分の持つ意味から答える。静的な地図が、応答する窓口になる。

連載の梯子と、今回の現在地 下段(見る)ほど渡す権限は小さく、上段(取引)ほど大きい。今回は二段目、静的な記述に「会話」を足す層。 見る(意味) Schema.org・llms.txt 第2回 問い合わせる(会話) NLWeb 第3回・現在地 操作する(アクション) WebMCP 第4回 取引する(決済) A2A・AP2・ACP・UCP 第5回 横断:RAG(根拠)+ セキュリティ・権限 ― すべての層に効く(第6回)

静的な地図から、応える窓口へ

前回積んだSchema.orgのマークアップを思い出してほしい。あれは、ページの中に「これは商品」「価格は税込1,200円」という札を貼る作業だった。札は正確だが、受け身だ。エージェントが価格を知りたければ、ページを取得し、JSON-LDを解析し、目当ての値を自分で拾い出す。サイトは差し出すだけで、こちらから何かを返しはしない。

NLWebは、この関係を反転させる。「予算3万円以内で、在庫のある商品は?」と自然言語で問われたら、サイト側がその問いを解釈し、自分の持つデータから答えを組み立てて返す。ページを一枚ずつ読ませる代わりに、問い合わせられる窓口を一つ立てる。

NLWebは、Microsoftが2025年5月のBuild 2025で発表したオープンプロジェクトだ。構想し主導するのはR.V. Guha ―― RSS、RDF、そしてSchema.orgの生みの親で、MicrosoftにCVP兼Technical Fellowとして加わった。この血筋は偶然ではない。NLWebは新しい語彙を発明しない。前回整えたSchema.orgを、そのまま入力として使う。名札を貼る作業と、その札で会話する仕組みが、同じ人物の設計思想でつながっている。

位置づけを一言で表すなら、NLWeb自身の言葉が要を突いている。NLWebは、MCPやA2Aにとって、HTMLがHTTPに対して果たしたのと同じ役割を果たす、と。HTTPが通信の土管で、HTMLがその上を流れる中身の型だったように、MCPがエージェント通信の土管なら、NLWebはその上を流れる「自然言語で問い、意味で答える」中身の型にあたる。

NLWebの導入は、オープンソースの参照実装(Python)を自分で動かすことから始まる。自社サイトのデータを指し、自分で選んだLLMとベクトルストアの上で走らせる。手元のノートPCからクラウドまで、軽量に動くよう作られている。

どう動くのか ― 意味を、ベクトルに変えて問い合わせ可能にする

窓口の内側では、四つの段が順に動く。

まず、既存の構造化データを取り込む。Schema.org、RSS、JSONL、サイトマップ ―― サイトがすでに公開している半構造化データが入力になる。新しく何かを書き起こす必要は、原則ない。前回積んだ意味が、そのまま材料になる。

次に、それを埋め込み(ベクトル化)して、ベクトルストアに索引化する。ベクトルストアは選べる。Qdrant、PostgreSQL(pgvector)、Milvus、Azure AI Search、Elasticsearch、Snowflakeなど、主要なものはおおむね揃っている。ここで、テキストの意味が数値の座標に変換され、「意味の近いものを引く」検索が可能になる。

問いが来ると、三段目が動く。自然言語の質問を解釈し、ベクトルストアから関連するものを検索し、順位づけ(再ランク)する。この段は見た目より重い。参照実装では、一つの問いが、脱文脈化やランキングのために何度もLLMを呼び出すことがある。窓口の裏で、それだけの計算が走っている。

最後に、検索結果をもとにLLMが回答を組み立て、Schema.org形式のJSONで返す。返ってくる型は、Article、Product、Place、Recipe、Reviewなど、前回見たSchema.orgの型そのものだ。人間向けのUIはそれを整形して見せ、エージェントはそのまま構造として受け取る。

NLWebのパイプライン ― 意味を、ベクトルに変えて問い合わせ可能にする 前回積んだSchema.orgのデータが、ベクトルに変わり、質問に答える材料になる。 ① 既存の構造化データ Schema.org・RSS JSONL・sitemap = 前回積んだ意味 ② 取り込み・索引化 埋め込み(ベクトル化) → ベクトルストアへ Qdrant / Postgres 他 ③ 問い合わせ処理 質問を解釈し検索 → 再ランク 裏で複数回のLLM呼び出し ④ 応答を組み立て LLMが回答を生成 → Schema.org形式のJSON 型:Article・Product 他 出口は二つ。/ask は人とアプリへ、/mcp はエージェントへ。 NLWebのインスタンスは、そのままMCPサーバーでもある ― 会話の窓口が、そのままエージェントの呼べる道具になる。

この流れで、二つ、押さえておきたい点がある。

一つは、答えの根拠が「あなたのデータ」だという点だ。NLWebは、LLMが世界一般について知っていることで答えるのではなく、あなたが索引化した内容から答えを引く。外部の知識を補助的に足すこともあるが、幹はあくまで自社データだ。これは、根拠を自社の一次情報に置く仕組み ―― 第6回で扱うRAGの考え方 ―― の、この層での現れだ。

もう一つは、この窓口が、そのままエージェント用の道具になるという点だ。すべてのNLWebインスタンスは、同時にMCPサーバーでもある。/askが人やアプリ向けの入口なら、/mcpはエージェント向けの入口で、askという一つのメソッドで自然言語の問いを受ける。つまり、MCP対応のアシスタントは、サイトごとの個別対応なしに、この窓口を呼べる。前回の名札が「読める」ための整備だったなら、今回の窓口は「呼べる」ための整備だ。(MCPを含む全体像は、以前まとめた。)

呼び方(どう問うか)は、いま見たとおり標準化されている。だが、その手前の見つけ方 ―― エージェントが、そもそも「untype.jpに窓口がある」とどう知るか ―― は、まだ固まっていない。今の主流は、使う側が接続先をあらかじめ登録しておく方式だ。生成AIに外部サービスを繋ぐ「コネクタ」の設定を思い浮かべればいい。誰かが繋いで、はじめて呼ばれる。窓口を立てただけで、世界中のエージェントが勝手に見つけに来るわけではない。

自動発見を標準化する動きは、始まってはいる。サイトが自分の能力の「目録」を決まった場所に置き、レジストリがそれを拾い、エージェントは「これに答えられる窓口はどこか」と問い合わせて辿り着く ―― 2026年6月、GoogleやMicrosoftなど11社が公開した共通仕様(ARD)の草案が出た。呼び方が先に決着し、見つけ方が後を追っている。この発見の層は、連載の後半で改めて扱う。

どこに、何を置くか

NLWebの実体は、サイトの隣に置くサーバーだ。自社サイトのデータを指し示し、/ask/mcpの二つのエンドポイントを立てる。感触をつかむだけなら、手順は短い。

Bash
git clone https://github.com/nlweb-ai/NLWeb
cd NLWeb
python -m venv myenv
source myenv/bin/activate
cd code
pip install -r requirements.txt
# .env.template を .env にコピーし、使うLLMとベクトルストアのキーを設定
python -m tools.db_load https://www.untype.jp/blog/rss.xml untype
python app-file.py
# → localhost:8000 に窓口が立つ

db_loadが、指定したフィードやSchema.orgデータを読み込み、ベクトルストアに索引化する。あとはサーバーを起動すれば、ローカルに問い合わせ可能な窓口ができる。既存のマークアップやRSSが揃っていれば、試作の立ち上げは速い。私が手元のRSSで試したところ、30分ほどでローカルに窓口が動いた。

ただし、これはあくまで試作の姿だ。本番については、参照実装のリポジトリ自身が釘を刺している。データはコピーせず「生きた」データベースに直結せよ(コピーは必ず鮮度のずれを生む)、スタンドアロンのサーバーを別に立てるより自分のアプリ環境にコードを組み込め、UIは付属のものでなく自前で作れ、と。試作は30分でも、実運用は別の仕事だ。

もう一段、取り込みの実際に踏み込んでおく。開発寄りの余談なので、判断だけ知りたい向きは読み飛ばしてかまわない。手間を分けるのは、意外にも「JSON-LDをHTMLに直書きするか、外部ファイルにするか」ではない。NLWebは入力が何であれ、内部ではSchema.orgのJSON-LDに正規化してから索引化する。だから効くのは別の軸だ ―― すでに一覧化されたフィード(RSSやJSONL、CSV)をdb_loadにそのまま渡すのか、それともページ群をクロールして各ページの<script type="application/ld+json">を抜き出すのか。前者はHTMLを経由せず、いちばん軽い。私が30分で動かしたのも、この経路だ。後者は抽出用のツールこそ用意されているが、ページの発見・取得・抽出という段取りが増える。さらに、JSON-LDをJavaScriptで後から差し込む作りだと、素のクロールでは見えず、もっとも重くなる。

だから、直書きのJSON-LDがすでにあるサイトでも、それをクロールさせるより、同じ情報源からフィードを一つ吐き出してdb_loadに渡すほうが速い。そのフィードを元データから毎回生成すれば、さきほどの「コピーは鮮度のずれを生む」も避けられる。そして置き場所以上に効くのが、型の質だ。直書きでもフィードでも、Productに価格や在庫、FAQPage、Articleと型がリッチなほど、ベクトルに載る意味が濃くなり、問い合わせの当たりがよくなる。どこに置くかより、どう型付けするか。前回のSchema.orgへの投資が、ここで二度目の配当を生む。

貼れる最小実例

窓口に問うのは、/askへのHTTPリクエスト一つだ。仕様はREST APIのドキュメントにまとまっている。最小の呼び出しはこうなる。

Bash
curl -X POST http://localhost:8000/ask \
  -H "Content-Type: application/json" \
  -d '{"query": "南青山で相談できるコミュニケーションデザインの会社は?", "site": "untype", "mode": "list"}'

返ってくるのは、Schema.orgの語彙で組まれたJSONだ。

JSON
{
  "query_id": "…",
  "results": [
    {
      "url": "https://www.untype.jp/service",
      "name": "コミュニケーションデザイン",
      "score": 87,
      "description": "Web制作と、AIエージェント対応の診断・設計。",
      "schema_object": { "@type": "Service", "provider": "株式会社アンタイプ" }
    }
  ]
}

ここで効くパラメータが二つある。範囲設計の要になるので、名前だけでも覚えておきたい。

siteは、答えの土俵を絞る指定だ。一つのバックエンドが複数サイト分のデータを持つとき、siteでどのサイトの範囲で答えるかを限定できる。何でも答える窓口ではなく、「この範囲について答える窓口」に仕立てるための取っ手だ。

modeは、答え方の指定だ。listは該当するものを一覧で返す。summarizeは要約して返す。generateは、検索結果をもとにLLMが文章で答える ―― 従来のRAGに近い振る舞いをする。エージェントは選択肢の一覧(list)を欲しがることが多く、人間向けUIは要約(summarize)を好み、生成(generate)はうまくはまる場面が限られる。生成は便利だが、事実を作文する余地 ―― 幻覚の面積 ―― がいちばん大きいモードでもある。

なお、参照実装はサーバー側に会話の状態を持たない。だから複数ターンの会話では、直前までの問いをprevに渡して文脈を繋ぐ。窓口は毎回、渡された文脈のぶんだけを覚えている。

何を答えさせ、何を答えさせないか

この層の実装の勘所は、コードより設計にある。何を索引化し、どのモードを既定にし、どの範囲(site)で答えさせるか ―― この三つが、窓口の性格をほぼ決める。

取り違えは、だいたい四つの形で現れる。

一つ目は、NLWebを「チャットボットを置くこと」と混同する取り違えだ。NLWebの設計思想は、派手な対話UIを足すことではなく、安定した契約(contract)を一つ用意することにある。どのUIから来ても、どのエージェントから来ても、同じ問い合わせ方で、同じ構造の答えが返る。見た目のチャット窓ではなく、裏の契約を作っている ―― この認識がずれると、評価軸ごとずれる。

二つ目は、generateモードを安易に既定にする取り違えだ。生成は口当たりがいいが、根拠の薄い合成回答を許しやすい。窓口の目的が「自社データを正確に引く」ことなら、既定はlistsummarize寄りにして、生成は要る場面に限る、という判断がいる。

三つ目は、索引した対象=答えられる範囲、という当たり前を意識しないまま、手元のデータを全部入れてしまう取り違えだ。入れれば、答える。だから、答えてほしくないもの ―― 下書き、内部向けの情報、古い版 ―― を混ぜれば、窓口はそれも平然と差し出す。何を入れないか、が範囲設計の半分を占める。

四つ目は、鮮度だ。前回のSchema.orgと同じ急所が、ここにもある。索引をコピーで作ると、元データを直しても索引は古いまま答え続ける。リポジトリが「生きたデータベースに直結せよ」と言うのは、この陳腐化を避けるためだ。

どの規模で、意味を持つか

NLWebが効くのは、問い合わせるに足る中身が、構造化された形である場所だ。早期採用の顔ぶれがそれを物語っている。Shopify、Allrecipes、Tripadvisorといった、商品・レシピ・旅行情報を大量に持ち、以前からSchema.orgに投資してきたサイトだ。ほかにEventbrite、O'Reilly Media、Hearstなども名を連ね、WordPress向けにはYoastが2026年3月、構造化データを一つにまとめるSchema Aggregation機能として実装した。カタログ、ドキュメント、レシピ、旅行情報 ―― 項目が多く、人もエージェントも「探して絞りたい」場所ほど、窓口の価値が立つ。

逆に、数ページの会社案内サイトには過剰だ。窓口を立てるコストが、問い合わせられる中身の薄さに見合わない。

コスト面も直視しておく。さきほど触れたとおり、一つの問いが裏で何度もLLM呼び出しに展開されうる。つまり費用は、問い合わせの量に比例して積み上がる。加えて、インフラの運用、データの整備、そしてこの技術がまだ発展途上で、事例も道具もこれから増える段階だという現実がある。「流行っているから置く」で始めると、費用だけが先に立つ。

だから判断はこうなる。問い合わせに足るだけの構造化された中身があり、人やエージェントがそこを「探して絞る」ことが事業上ありうるなら、窓口を立てる価値がある。そうでなければ、まだ早い。(NLWeb単体の費用対効果は、以前詳しく扱った。今回は、実装ガイドの一層として、他の層との接続の中に置き直している。)

この層で確かめること(観点だけ)

前回と同じく、この層も二段で見る。何を入れるか(Do)は、ここまでに書いた。既存のSchema.org/RSSを索引化し、sitemodeで範囲と答え方を設計し、/ask/mcpで窓口を立てる。では、それが意図どおりに働いているかを、どの観点で見るか。四つ挙げる。合否をどこで切るかという判定基準は、ここには書かない。見るべき観点までを示す。

第一に、意図した意味と範囲で答えているか。索引した対象、siteの指定、modeの既定 ―― この設計が、事業として答えさせたい範囲と一致しているか。窓口は設計どおりにしか答えない。設計が曖昧なら、答えも曖昧になる。

第二に、答えるべきでない情報に答えていないか。範囲外のデータが索引に紛れていないか。generateが、根拠のない合成回答を返していないか。人間向けの表示では隠れている内部情報を、窓口が平然と差し出していないか。この「範囲外露出」は、入れた覚えのないものではなく、入れた覚えのあるものから漏れる。

第三に、答えが一次情報(正典)に基づいているか。コピーした索引が陳腐化して、実態と違う答えを返していないか。答えの出所が、推測や外部の一般知識ではなく、自社の正しいデータに根ざしているか。この観点は、第6回のRAG ―― 根拠をどう据えるか ―― に直接つながる。

第四に、会話ゆえの新しい入口を塞げているか。自然言語で問いを受ける以上、悪意ある問い ―― プロンプトインジェクション ―― で、窓口を範囲外の振る舞いへ誘導される危険がある。読み取り中心のこの層でも、入口が言葉である以上、そのリスクはゼロにならない。ここも第6回のセキュリティで正面から扱う。

この四つのうち、機械にすぐ任せられるものと、そうでないものがある。エンドポイントが立っているか、JSONが仕様どおり返るか、といった形式面は、自動で確かめられる。だが「意図した範囲で答えているか」「範囲外を漏らしていないか」「正典に基づいているか」は、窓口の中身と事業の実態を突き合わせなければ判断できない。窓口が動くことと、正しく答えることは、別のことだ。前者は機械に、後者は人に残る。前回と同じ線引きが、この層でも引かれる。

次回

問いに答える窓口ができたら、次は動かす。第4回は「操作の層」、WebMCPを扱う。この連載の主役だ。会話までは、基本が読み取りだった。間違っても、間違った答えが返るだけで済む。だが操作は副作用を持つ。予約を入れる、注文を出す、設定を変える。エージェントに渡す権限が、ここで一段上がる。応えるサイトが、動かせるサイトになる話だ。

参考情報
山下 太郎

山下 太郎

代表取締役 / CEO

2000年、Webデザイナーとしてこの世界に飛び込み、フリーランスを経て2007年に株式会社アンタイプを創業。AI時代の到来とともに、効率だけを追うAI活用に違和感を覚えながら、それでも最前線でツールを使い続ける。企業のWebとコミュニケーションを設計する仕事を通じて、「人間らしさとは何か」を問い直す視点を発信し続けている。

View Profile arrow_outward

Related

あわせて読みたい

エージェンティックWeb実装ガイド 第2回:サイトが自分を名乗る ― 構造化データとllms.txtで、意味と全体像を伝える
エージェンティックWeb
エージェンティックWeb

エージェンティックWeb実装ガイド 第2回:サイトが自分を名乗る ― 構造化データとllms.txtで、意味と全体像を伝える

AIエージェントに操作させる前に、まずサイトの意味を正しく読ませる。構造化データ(Schema.org)とllms.txtで、サイトは自分を名乗る。連載「エージェンティックWeb実装ガイド」第2回。Google検索が無視するファイルを、なぜ今置くのか。

エージェンティックWeb実装ガイド 第1回:三番目の読者 ― Webサイトが「読まれる」から「使われる」へ
エージェンティックWeb
エージェンティックWeb

エージェンティックWeb実装ガイド 第1回:三番目の読者 ― Webサイトが「読まれる」から「使われる」へ

Webサイトの読者は、人間とクローラだけではなくなった。見て・操作し・取引する「三番目の読者」=AIエージェントである。連載「エージェンティックWeb実装ガイド」第1回は、これからのサイトに必要な層を一枚の地図として示す。

Lighthouseが「AIエージェントに読めるか」を監査し始めた — Agentic Browsingの構造と、8割が「すでに知っている仕事」である理由
Lighthouse
Lighthouse

Lighthouseが「AIエージェントに読めるか」を監査し始めた — Agentic Browsingの構造と、8割が「すでに知っている仕事」である理由

GoogleがLighthouseに標準搭載した新監査「Agentic Browsing」を解説。AIエージェントに読めるWebの条件、監査の8割が従来のアクセシビリティ対応の延長である理由、自社サイト実測で属性1個の修正から満点に至った過程を、実務の優先順位とともに整理。