「開発では取れているのに、本番だけSharePointページの本文がCopilotで取れない」。この“ページだけイライラ問題”は、インデックスと権限、そしてCopilot側の選択ロジックの三位一体で起きます。本稿では、根本原因の見立てから10分で試せる暫定回避、確実に収束させる恒久対策、監視と再発防止の仕組み化までを、現場運用の粒度で徹底的にまとめます。
現象の整理(なぜ「ページだけ」失敗するのか)
まずは、開発(dev)と本番(prod)での差異、ページとドキュメントでの差異、Graph APIとCopilotでの差異を表に落として、切り分けの初期仮説を置きます。
| 観点 | 状態 | 示唆 |
|---|---|---|
| 開発テナント(dev) | ページのメタデータ/本文を正常取得 | Copilot側の機能自体は正常。prod特有の設定またはデータ状態が原因の可能性が高い |
| 本番テナント(prod) | ドキュメントは取得OK、ページのみ断続的に失敗 | Site Pagesライブラリのインデックスや権限、またはCopilotの候補選択に偏りが発生 |
| ページの更新有無 | 未変更(SPFx等のカスタム無し) | コンテンツ自体の変化ではなく、検索・権限・キャッシュの経路問題が濃厚 |
| Graph API直接取得 | 基本成功 | “ライブ取得”は可能だが、Copilotは原則Microsoft Searchインデックスを参照するため、インデックス遅延/欠落があると再現する |
この観測から導かれる一次仮説は「Microsoft Searchインデックスの状態と、ページ特有の権限/プロパティがCopilotの候補選択に影響し、結果として“ページだけ”抜け落ちる」です。
CopilotがSharePointページ本文を取得する仕組みの前提
Copilot(Copilot Studio で構築したエージェントを含む)がSharePointのページ内容を応答に使う際の大まかな流れは以下です。
- 候補探索:Microsoft Search(Graph Search APIの裏側)に対して、ナレッジソースで指定されたサイト/ライブラリ/URLラベルをヒントにクエリを投げ、候補(ページ/ドキュメント)を取得。
- セキュリティトリミング:呼び出しユーザーまたはアプリのトークンでアクセス可能なアイテムに限定。
- 本文抽出と再ランキング:インデックスに保存された本文・要約・シグナル(クリック、既読、類似性など)を加味して上位候補を決定。
- 最終取得:必要に応じてGraph経由で本文の追加フェッチを行い、応答を生成。
ここで決定的に重要なのが「ページは“Site Pages”ライブラリの特殊なアイテム」である点です。モダンページの本文はキャンバスJSON(CanvasContent1 など)として管理され、ドキュメント(OfficeファイルやPDF)に比べて以下の特徴があります。
- インデックスに反映されるプロパティが多く、管理プロパティのマッピング状態に左右されやすい。
- 公開状態(ニュース/通常ページ)やプロモート状態(
PromotedState)など、検索対象/優先度に影響するメタが存在。 - サイトやライブラリのNoCrawl、ページ単位の再インデックスフラグ、サイトの検索設定の影響を受けやすい。
このため、ドキュメントは取れているのにページだけ不安定、という現象が起きがちです。
よくある原因と具体的な兆候
| 原因候補 | 具体的な兆候 | 一次確認ポイント |
|---|---|---|
| 検索インデックスの遅延・欠落 | 特定ページだけ検索でヒットしない/旧版が返る。Copilotの応答に古い要約が混ざる | サイト/ライブラリ/アイテム単位の「再インデックス」を実行、KQLでヒット有無確認 |
| 認証トークン/権限の不整合 | ドキュメントOK、ページNG。401/403が断続的に発生。共有リンクの種類で挙動が変わる | Graphで対象ページのGET時のHTTPステータス、トークンのスコープ/失効、サイト権限の整合 |
| 本番と開発の設定差 | devで成功、prodで失敗。特定サイトやハブ配下だけ再現 | 検索スキーマ、セマンティック検索、条件付きアクセス(CA)、情報保護ラベルの差分比較 |
| Copilot/エージェントのキャッシュ・セッション | 同タイトル重複やURLが多いと、特定URLを拾わない。Publishし直すと一時的に直る | Copilot Studioで再公開、URLラベルの整理、ブラウザキャッシュクリア |
10分でできる暫定対処(まずは復旧を最優先)
- ページ個別の再インデックス:Site Pagesライブラリで対象ページを選択し、「このアイテムのプロパティの再インデックス」を実行。
- ライブラリ単位の再インデックス:Site Pagesの「ライブラリの設定」→「詳細設定」→「このドキュメントライブラリを再インデックス」。
- Copilot側の再公開:Copilot Studio(または運用中のエージェント)をPublishし直し、セッションを切り替えて再試行。
- ナレッジソースURLの最小化:サイトコレクションではなく、対象サイトの
Site Pages直下URLを1~3個程度に絞り、明確なラベル(日本語)を付与。 - Graphでの直接検証:同ページをGraphでGETして本文/メタが取れることを確認(認可/401/403の切り分け)。
上記で復旧する場合、根はインデックスまたは候補選択(キャッシュ)です。恒久対策へ進みましょう。
恒久対策:手順書(現場向け)
1. インデックス健全性のチェックと是正
以下の順序で、サイト→ライブラリ→アイテムの三層で“インデックス経路”を正します。
| 手順 | 操作 | 狙い/注意 |
|---|---|---|
| サイトの再インデックス | サイトの「検索設定」から再インデックス(またはサイト管理UIの再インデックス操作) | サイトレベルの再クロール指示。反映に最大24時間程度見込む |
| Site Pagesライブラリの再インデックス | ライブラリ設定→詳細設定→再インデックス | ページ専用の再取り込み。併せて「NoCrawl」が無効(クロール許可)か確認 |
| ページ個別の再インデックス | 対象ページの「プロパティ」→「再インデックス」 | 緊急復旧用。対象のみ短時間で改善するケースが多い |
| 検索スキーマの点検 | キャンバス本文(例:CanvasContent1)が管理プロパティに適切にマップされているか確認 | 本文が検索に乗らないとCopilotが拾いにくくなる |
| セマンティック検索の有効化 | テナント設定でセマンティック検索/強化検索オプションを有効化 | 要約精度と候補選択の改善を期待。段階的展開の有無に留意 |
KQLによる簡易検証例
組織の検索ボックスまたはGraphの検索APIで、対象ページがヒットするかをKQLで確認します。
path:"https://contoso.sharepoint.com/sites/プロジェクトA/SitePages"
(FileType:aspx OR contentclass:STS_ListItem_WebPageLibrary)
Title:"設計レビュー" AND IsDocument:True
ここでヒットしない場合は、インデックス未収載か検索スキーマ不整合の可能性が高いです。
2. 権限とトークン(401/403)の検証
ページは「サイト権限」「ライブラリ権限」「ページ固有権限」の三層で差異が生じやすく、さらに共有リンクの種類(組織限定/特定ユーザー/リンク所有者全員)や有効期限も影響します。Copilotは検索結果のセキュリティトリミングを通るため、インデックス上は見えるが最終取得時に403という矛盾が起こりえます。
- Copilotが利用するアプリ登録/サービスプリンシパルに付与したサイト権限(サイトコレクション/Sites.Selected/Sites.Read.All等)が実要求と整合しているか。
- ユーザー委任フローの場合、条件付きアクセス(ネットワーク/デバイス準拠/アプリ制限)でトークンが失効していないか。
- Site Pagesのみユニーク権限に分岐していないか、フォルダー単位の権限断層が無いか。
Graphでの基本テスト(例)
# ページ一覧(タイトル・URL確認)
GET https://graph.microsoft.com/v1.0/sites/{site-id}/pages?$select=id,title,webUrl,lastModifiedDateTime
# 指定ページの詳細
GET [https://graph.microsoft.com/v1.0/sites/{site-id}/pages/{page-id}](https://graph.microsoft.com/v1.0/sites/{site-id}/pages/{page-id})
# 検索APIでSite Pages配下のみ探索
POST [https://graph.microsoft.com/v1.0/search/query](https://graph.microsoft.com/v1.0/search/query)
Content-Type: application/json
{
"requests": [
{
"entityTypes": ["listItem"],
"query": { "queryString": "path:"[https://contoso.sharepoint.com/sites/プロジェクトA/SitePages](https://contoso.sharepoint.com/sites/プロジェクトA/SitePages)" AND Title:"設計レビュー"" },
"from": 0,
"size": 5
}
]
}
ここで401/403が出る場合は、トークンスコープまたは権限の整合性を見直します。200で返るのにCopilotが拾えない場合は、以降の「候補選択」や「スキーマ」の論点です。
3. ナレッジソースURLとラベルの整理
Copilotが「どのURLから候補を拾うか」をシンプルに与えることは、検索精度の改善に直結します。
- 「サイトコレクションのルートURL」ではなく、Site Pages直下のURLに絞る(例:
/sites/プロジェクトA/SitePages)。 - URLの登録数は最小限(1~3)にし、重複や似たラベルを避ける。
- ラベルは検索語としても使われるため、日本語で具体的に(例:「プロジェクトAの正式手順」「インフラ設計標準」)。
4. 本番と開発の設定差分を棚卸し
devで成功している以上、prod側に「検索・保護・アクセス制御」の差分が紛れている可能性が高いです。次の表をチェックリストとして活用します。
| 項目 | dev | prod | 差分アクション |
|---|---|---|---|
| セマンティック検索(テナント) | 有効/無効 | 有効/無効 | 揃える。無効の場合は候補理解が弱くなる |
| 検索スキーマ(管理プロパティ) | Canvas/タイトル/タグのマッピング | Canvas/タイトル/タグのマッピング | エクスポートして比較、必要に応じてインポート |
| 条件付きアクセス(CA) | 対象クラウドアプリ/場所/デバイス準拠 | 対象クラウドアプリ/場所/デバイス準拠 | Copilot/Graphの通行を阻害していないか確認 |
| 情報保護ラベル(MIP) | ページに付与無し/あり | ページに付与無し/あり | ラベル適用時の検索可否・外部共有制限を確認 |
| サイト/ライブラリNoCrawl | 無効 | 無効/有効 | 有効ならクロール対象外、無効へ |
5. Copilot/ブラウザのキャッシュ・セッションを整理
- Copilot Studioのプロジェクトを再Publish(公開し直し)し、新セッションで検証。
- Edge/Chromeのキャッシュを削除し、InPrivateで再実行。
- 同タイトルのページが複数ある場合は、タイトルを固有化するか、URLラベルの重み付けを見直す。
6. 監視・自動化(再発防止)
人手での復旧に頼らず、CI/CDや定期ジョブで“差分と劣化”を検知します。
- インデックス健全性のヘルスチェック:代表ページ群のKQL検索をスケジュール実行し、ヒットしなければ通知。
- 検索スキーマのドリフト監視:dev/prodから設定をエクスポートして差分比較、乖離が出たらレビュー。
- ナレッジソースURLの差分検出:Copilot側のURL定義をコード化(IaC)し、PRレビューで変更を可視化。
運用でそのまま使える「手順とスクリプト」
PowerShell(PnP)例:Site Pagesの再インデックスとノークロール確認
# 認証(対話式)
Connect-PnPOnline -Url "https://contoso.sharepoint.com/sites/プロジェクトA" -Interactive
# Site PagesライブラリのNoCrawl確認
Get-PnPList -Identity "Site Pages" | Select-Object Title, NoCrawl, ItemCount
# NoCrawlを無効化(クロール許可)
Set-PnPList -Identity "Site Pages" -NoCrawl:$false
# ライブラリ再インデックス(環境によりコマンド名が異なる場合あり)
Request-PnPReIndexList -Identity "Site Pages"
# サイト全体再インデックス(必要時)
Request-PnPReIndexWeb
※環境やバージョンにより、再インデックス指示のコマンド名称が異なる場合があります。UIからの実行と併用してください。
PowerShell(PnP)例:検索スキーマのエクスポート/インポートで差分吸収
# devから検索設定をエクスポート
Connect-PnPOnline -Url "https://contoso.sharepoint.com/sites/dev" -Interactive
Get-PnPSearchConfiguration -Scope Site -Path "./dev-search.xml"
# prodへインポート(差分をレビューした上で)
Connect-PnPOnline -Url "[https://contoso.sharepoint.com/sites/prod](https://contoso.sharepoint.com/sites/prod)" -Interactive
Set-PnPSearchConfiguration -Scope Site -Path "./dev-search.xml"
curl例:Graph Searchでページのヒット可否を点検
curl -X POST https://graph.microsoft.com/v1.0/search/query \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"requests": [
{
"entityTypes": ["listItem"],
"query": { "queryString": "path:\"https://contoso.sharepoint.com/sites/プロジェクトA/SitePages\" AND Title:\"設計レビュー\"" },
"from": 0,
"size": 5
}
]
}'
CI/CDに組み込む簡易ヘルスチェック(擬似例)
# 擬似コード:代表ページの検索ヒット率を計測してしきい値を割ったら失敗扱い
$targets = @(
"https://contoso.sharepoint.com/sites/プロジェクトA/SitePages/設計レビュー.aspx",
"https://contoso.sharepoint.com/sites/プロジェクトA/SitePages/運用標準.aspx"
)
$hit = 0
foreach ($url in $targets) {
$q = "path:`"$($url.Substring(0, $url.LastIndexOf('/SitePages') + 10))`" AND WebUrl:`"$url`""
# Graph検索呼び出し(実装略)
# if (ヒット) { $hit++ }
}
if ($hit -lt $targets.Count) { throw "Search index degraded." }
権限・トークンの落とし穴と解消パターン
- リンク種別の不一致:ページのみ「特定ユーザー」リンクで共有されており、Copilot実行ユーザーに権限がない。解消:権限の継承を復帰、または対象ユーザー/アプリに明示付与。
- 条件付きアクセスの揺らぎ:prodでのみネットワーク/デバイス準拠のポリシーが厳しく、トークンが再評価で失効。解消:対象クラウドアプリの例外設計、セッション制御の見直し。
- アプリ権限と委任権限の取り違え:Graphのテストは委任で成功、Copilotはアプリ権限経路で403。解消:運用経路と同一の権限モデルでテストする。
ナレッジソース設計のベストプラクティス
| やるべきこと | 理由 |
|---|---|
| URLはSite Pages直下に絞る | 候補範囲が明確になり、ページ本文の拾われ方が安定 |
| URLラベルは日本語で具体的に | クエリ拡張時の手掛かりになり、誤選択を抑制 |
| 重複タイトルを避ける | ランキングで競合し、誤ったページが選ばれやすくなる |
| 代表ページの監視対象化 | インデックス劣化を早期検知できる |
トラブルシューティングの分岐フロー(RCAテンプレート付き)
以下のフローで切り分けると、2~3ステップで“犯人”に到達できます。
- Graphでページ本文取得が成功するか(200/本文あり)→ 成功なら「検索/キャッシュ系」、失敗なら「権限/トークン系」。
- KQLで対象ページがヒットするか → ヒットしないなら「インデックス/スキーマ」。
- devとprodの設定差分があるか → あれば差分を是正。
RCA(原因分析)記載テンプレート
【事象】
本番テナントでSite Pages配下のページ本文をCopilotが取得できない。ドキュメントは取得可能。
【発生日/頻度】
2025-xx-xx ~ 断続的
【影響範囲】
サイト:/sites/プロジェクトA 配下
対象:ニュース/通常ページ計120件のうち約15件
【切り分け】
* Graph GET:200(本文取得可)/ 一部403
* KQLヒット率:85%(該当15件が未ヒット)
* dev:再現せず
【原因】
検索インデックスの欠落(Site PagesのNoCrawl誤設定と再インデックス未実施)+ 権限のユニーク化
【恒久対策】
* NoCrawl解除、ライブラリ再インデックス、個別再インデックス
* 権限の継承復帰、ナレッジソースURLの整理
* 監視ジョブ実装(KQLヒット率しきい値90%)
【再発防止】
CI/CDに検索スキーマ差分検知を追加
FAQ(現場でよく問われること)
Q. ドキュメントは拾えるのに、なぜページだけ落ちる?
A. ページは本文がキャンバスJSONとして格納され、検索スキーマとインデックスに依存度が高いためです。管理プロパティの不整合やNoCrawl、個別再インデックス未実行があると、ページのみ欠落しやすくなります。
Q. Graphで取れるのにCopilotが取れないのは?
A. Graphの“ライブ取得”は成功しても、Copilotはまず検索インデックスから候補を選ぶため、インデックス欠落やランキングの影響で外れることがあります。
Q. 再インデックスの効果はどれくらいで出る?
A. 小規模なら数分~数時間、広範囲だと最大24時間程度見込みます。個別アイテムの再インデックスは比較的早く反映される傾向です。
Q. セマンティック検索は必須?
A. 必須ではありませんが、候補選定と要約品質の改善に寄与します。本番で無効・開発で有効だと差が出やすくなります。
Q. 情報保護ラベル(MIP)を付けても検索できますか?
A. ラベルのポリシー次第です。閲覧権限が無いユーザーやアプリにはセキュリティトリミングで非表示になります。
Do/Don’t(やる・やらない)
| Do | Don’t |
|---|---|
| Site Pages直下URLに絞って登録 | サイトルートURLを大量登録してCopilotの選択を迷わせる |
| ページタイトルを固有化 | 同タイトルのページを乱立させる |
| 定期的なKQLヘルスチェック | 「動いているから大丈夫」と監視なし運用 |
| 権限モデルをdev/prodで揃える | prodだけCAやラベルを厳格化して未検証のまま本番投入 |
エスカレーション時に集めるべきログ/情報
- 時間帯と対象URLのリスト(再現率・パターン)。
- Graph APIのレスポンス(HTTP 200/401/403、応答ヘッダーの相関ID)。
- 検索ヒット有無のKQL結果(ヒット/未ヒットをCSV化)。
- 権限スナップショット(サイト、ライブラリ、アイテムの許可レベル)。
- Copilot設定(ナレッジソースURL、ラベル、公開バージョン)。
これらが揃っていれば、サポート側での再現・調査が格段に速くなります。
チェックリスト(印刷して壁貼りできる版)
| カテゴリ | チェック | OKの基準 |
|---|---|---|
| インデックス | Site PagesがNoCrawlでない/再インデックス済み | KQLで代表ページが即時ヒット |
| 権限 | サイト/ライブラリ/ページの許可に断層なし | Graph GETが安定して200 |
| 設定差分 | dev/prodの検索スキーマ/CA/MIPが一致 | 差分レポートが空(または意図した差のみ) |
| Copilot | URLラベル最小化、重複タイトル解消、再Publish済み | 候補の誤選択が消失 |
| 監視 | KQLヘルスチェック、しきい値アラート | 劣化時に通知が飛ぶ |
ケーススタディ(収束までの実録パターン)
ケースA:NoCrawl誤設定+個別再インデックス不足
本番の一部サイトでSite PagesがNoCrawlになっており、公開直後のニュースページが永遠に検索に乗らず、Copilotは近縁の古いページを拾っていた。NoCrawl解除→ライブラリ再インデックス→個別再インデックスの順で解消。
ケースB:条件付きアクセスでトークンが再評価失敗
リモート接続時のみページ取得が403。CAのセッション制御により、Copilot実行時のトークンが途中で無効化。該当クラウドアプリの例外設定を見直し、安定化。
ケースC:タイトル重複とURLラベルの希薄化
「設計標準」という同一タイトルのページが多数。Copilotの候補選択でランダム化。ページタイトルの固有化と、Site Pages直下URLのみに絞る設計で再現解消。
まとめ(再発させないために)
CopilotがSharePointページを取りこぼす背景には、検索インデックス、権限/トークン、候補選択の三つの経路があり、特にSite Pages特有の性質が影響します。復旧を早めるには「ページ個別→ライブラリ→サイト」の順で再インデックスをかけ、並行してGraphとKQLでヒット可否を数値化。恒久対応はdev/prodの設定差分を正し、ナレッジソースURLを最小・明確に設計すること。最後に、監視とIaCでドリフトを自動検知すれば、同種の事故を未然に防げます。
付録:実務テンプレート集
1) 差分点検ワークシート(抜粋)
| 項目 | 収集元 | dev値 | prod値 | 判定/メモ |
|---|---|---|---|---|
| セマンティック検索 | テナント設定 | |||
| 管理プロパティ(CanvasContent) | 検索スキーマ | |||
| Site Pages NoCrawl | ライブラリ設定 | |||
| 条件付きアクセス | Azure AD | |||
| 情報保護ラベル | コンプライアンスセンター | |||
| ナレッジソースURL | Copilot設定 |
2) サポートエスカレーション用メール雛形
件名:本番のみ発生:CopilotがSharePointページ本文を取得できない
概要:
* 本番テナントのSite Pages配下のページ本文をCopilotが取得できない
* ドキュメントは取得可能、開発テナントでは再現しない
再現手順:
1. Copilotに「<具体的な質問>」を入力
2. 本来参照されるべきページURL:
観測値:
* Graph GET:200/403混在(詳細ログ添付)
* KQLヒット率:<数値>%
* ライブラリNoCrawl:False
* 再インデックス:ライブラリ/アイテムに実施済み
希望事項:
* サービス側の既知事象の有無
* 該当時間帯の相関IDに基づく調査

コメント