[AI-READ-ONLY] mode=ai-read-only primary=<primary> tables=<list> expand-targets=<list> caller=add-ai-webapi
Configure Layer 1/2 (Web API site settings + table permissions) for the following Power Pages
AI summarization targets:
. This is a read-only integration — the /_api/summarization/data/v1.0/
endpoint never mutates Dataverse. Return when all Web API site settings, table permissions, and the
shared powerPagesApi.ts client are written to disk.
Per the AI-only read-mode contract (your SKILL.md Phase 1.6):
- Do not commit. Skip Phase 4.4 and Phase 6.5 — print the file list you would have
committed so this orchestrator can stage it later. The parent skill batches commits.
- Do not deploy. Skip Phase 6.1 deploy ask, Phase 7.3 deploy ask, and Phase 7.4
post-deploy notes. Return the Phase 7.2 summary and stop. The parent skill owns the
single end-of-orchestration deploy.
/integrate-webapi detects the [AI-READ-ONLY] sentinel (its Phase 1.6) and runs its full flow
with hardened prompts: read-only table permissions, minimal fields list (no PK, only _<col>_value
for lookups), and a read-only service layer. It still presents plan-mode approval prompts to the
user for each architect — this skill does not suppress those.
Wait for /integrate-webapi to complete. Re-check the file system:
src/shared/powerPagesApi.ts exists
- For every target table:
Webapi/<table>/enabled exists, Webapi/<table>/fields exists
- For every target table: at least one table permission with
read: true exists; Parent-scope
permission present for every $expand target
If any prerequisite is still missing, surface this to the user before moving on — something in the
delegated flow didn't land (for example, the user declined the architect's plan). Do NOT silently
fall back to writing Layer 1/2 files here.
Output: Layer 1/2 prerequisites are on disk; shared powerPagesApi.ts + read-only service
exists; web roles exist.
Phase 5: Implement Layer 3 code
Goal: Create the AI summarization service and wire it into each target's UI.
5.1 Invoke the ai-webapi-integration agent — first target (sequential)
For the first target in the confirmed manifest, invoke the agent at
${PLUGIN_ROOT}/agents/ai-webapi-integration.md via Task. The full prompt
template — every field the agent expects, with notes on which orchestrator phase resolved
each value — lives in
${PLUGIN_ROOT}/skills/add-ai-webapi/references/agent-invocation-prompt.md. Read
that file, copy the template, replace every <…> placeholder with the concrete value for
the current target, and pass it via Task. The agent does not interpret placeholders;
sending the literal text <search | data> will confuse it.
The first call is sequential because it establishes the shared summarization service file
(src/services/aiSummaryService.*) and the CSRF helper that subsequent targets reuse. The
agent returns a structured file-modification list (see its "Return value" section); record
it for Phase 5.5's per-file commit.
5.2 Verify service + CSRF helper exist
Before spawning more agents, verify:
- The summarization service file exists (default
src/services/aiSummaryService.ts).
getCsrfToken is defined once in the codebase (or imported from a pre-existing helper).
5.3 Invoke the agent for remaining targets — sequentially
Per plugins/power-pages/AGENTS.md, agent spawning is sequential. Invoke
ai-webapi-integration once per remaining target, waiting for each completion before starting the
next. Each target only adds an independent exported function, a framework wrapper (if not already
present), and wires one UI file — there are no merge conflicts, but the sequential rule keeps
failure modes simple.
If there is only one target total, skip 5.3.
5.4 Replace placeholder POSTs
For any placeholder InstructionIdentifier body the Explore agent flagged in Phase 2, the
sub-agent will have replaced them. Confirm by grepping for InstructionIdentifier in the affected
files and verifying each resolved call uses the real entity set and id.
5.5 Offer to commit
Don't commit automatically — on iterative runs an unprompted git commit here creates a noisy
series of commits for what is effectively one set of changes.
🚦 Gate (consent · add-ai-webapi:5.5.commit): Explicit commit decision after Phase 5 summarization-service + UI wiring is complete.
Trigger: All Phase 5 targets have been wired (service, framework wrapper, UI call sites).
Why we ask: Auto-committing on every integration run creates noisy one-commit-per-tweak history; letting the user batch is safer.
Cancel leaves: Nothing — source files written; no git commit fired.
Use AskUserQuestion:
| Question | Header | Options |
|---|
| Commit these Layer 3 integration changes now? | Commit | Yes, commit now (Recommended), Skip — I'll commit later |
On Yes: stage only the files modified during Phase 5 — the summarization service,
framework wrapper(s), each wired UI page, and any safe-markdown renderer component the agent
emitted. The orchestrator already has this list from each ai-webapi-integration invocation's
file-modification report. Use explicit git add <path> per file; do not use git add -A —
unrelated work-in-progress files in src/ could otherwise be swept into the commit. Substitute
<targets> in the commit message with a short human-readable list (e.g., CaseDetail and SearchResults,
or 3 pages when there are many):
git add <each file modified by the Phase 5 agents>
git commit -m "Add AI summarization integration for <targets>"
On Skip: proceed without committing. The user will batch the commit themselves at the end.
Output: summarization service + framework wrappers + UI call sites created for every confirmed
target.
Phase 6: Configure Layer 3 settings
Goal: Register the Summarization/* site settings via the ai-webapi-settings-architect agent.
6.1 Skip-check
Skip this phase when both of the following are true:
- Every confirmed target is Search Summary (search has no per-call
Summarization/* site settings;
see ai-api-reference.md).
- No Data Summarization target was added in Phase 3.
For search-only, remind the user to enable Site search with generative AI (preview) in the
site's Copilot workspace after deploy, and proceed to Phase 7.
6.2 Confirm deployment prerequisite still holds
Phase 1.5 already gated on .powerpages-site existing. Re-check it here as a guard — if it has
disappeared between Phase 1 and now (rare, but possible if the user manually cleaned the folder),
stop and re-run the Phase 1.5 bootstrap-deploy prompt. Do NOT silently fall through into the
architect with a missing folder.
6.3 Invoke ai-webapi-settings-architect
Invoke the agent at ${PLUGIN_ROOT}/agents/ai-webapi-settings-architect.md via Task:
"Analyse this Power Pages SPA site and propose generative-AI summarization site settings.
The following Data Summarization targets were integrated in Phase 5: [list each target with its
entity set, per-target InstructionIdentifier value, and target kind (single-record or
list) — the architect needs this to decide on Summarization/Data/ContentSizeLimit].
If any target is list, the plan MUST include Summarization/Data/ContentSizeLimit=200000 —
the 100k server default silently truncates list content; this is non-negotiable.
Check for existing Summarization/* settings. Layer 1
(Webapi/<table>/*) and Layer 2 (table permissions) were configured in Phase 4 via
/integrate-webapi in AI-only read mode — verify they are present on disk and cite them as
met in your plan's prerequisite table. Propose the AI plan via plan mode, and on approval
create the YAMLs with create-site-setting.js."
Wait for the agent to complete. If it reports missing Layer 1/2 prerequisites, something in
Phase 4 didn't land — read the file system, identify the gap, and surface it to the user rather
than attempting to create Layer 1/2 files here.
6.4 Offer to commit
🚦 Gate (consent · add-ai-webapi:6.4.commit): Explicit commit decision after Summarization/* site settings are created by the architect.
Trigger: ai-webapi-settings-architect has written all Summarization/Data/Enable + Summarization/prompt/<id> YAMLs.
Why we ask: Auto-committing could bundle dirty pre-existing YAMLs into the commit; explicit consent scopes the commit to just the architect's output.
Cancel leaves: Nothing — YAML files written to disk; no git commit fired.
Use AskUserQuestion:
| Question | Header | Options |
|---|
Commit the new Summarization/* site settings? | Commit | Yes, commit now (Recommended), Skip — I'll commit later |
On Yes: stage only the files the architect just created — use the
filePath list returned by ai-webapi-settings-architect (or the per-file paths printed by
each create-site-setting.js invocation), not a glob. A glob can sweep in pre-existing
Summarization-* YAMLs that are dirty for unrelated reasons (e.g., a prior partial run, or
a maker-edited prompt) and bundle them into the commit by accident.
Use explicit git add <path> per file:
git add <each Summarization-*.sitesetting.yml the architect just wrote>
git commit -m "Add AI summarization site settings"
On Skip: proceed without committing.
Output: Summarization/Data/Enable, Summarization/prompt/<id> settings created.
Phase 7: Verify
Goal: Confirm every expected file exists, all POSTs set both required headers, and the project
builds.
Preview-feature reminder. A green build doesn't mean the API will return a summary at
runtime — admin-level governance (tenant PowerShell, Copilot Hub) or the site-level maker
toggle for Search Summary can still block it. See the Preview-feature note at the top of
this skill and the admin-hierarchy checklist in
references/ai-api-reference.md §1 "Troubleshooting: AI feature appears disabled". Tell
the user now so the post-deploy test isn't a surprise.
7.1 File inventory
For each confirmed target, confirm:
- Service file:
src/services/aiSummaryService.ts (or project-convention equivalent) contains
the expected exported function (fetchSearchSummary or fetchDataSummary; the agent may also
emit a thin wrapper such as fetchCaseSummary when the user picked the support-case scenario).
- Framework wrapper (non-Astro): React hook in
src/hooks/, Vue composable in
src/composables/, or Angular service in src/app/services/.
- UI wiring: at least one page/component imports the service or wrapper and calls it.
- Shared API client
src/shared/powerPagesApi.ts exists when any Data Summarization target was in scope.
Summarization/Data/ContentSizeLimit site setting when any list-summary target was
integrated. Grep the source for fetchListSummary — if any match exists, confirm
.powerpages-site/site-settings/Summarization-Data-ContentSizeLimit.sitesetting.yml is
present with value: 200000 (or higher). Missing this setting silently caps list summaries at
the 100k server default and ships the user truncated input. If it's missing, surface the gap
to the user before completing Phase 7 — re-run the architect or create the YAML manually.
7.2 Header contract grep
Grep: "_api/search/v1\\.0/summary|_api/summarization/data/v1\\.0/" in src/**/*.{ts,tsx,js,jsx,vue,astro}
For every file that matches, verify the surrounding fetch includes:
__RequestVerificationToken (CSRF token, fetched from /_layout/tokenhtml) — hard rule
X-Requested-With: XMLHttpRequest — recommended (the validator warns when it's missing but
does not block; it matches shell.ajaxSafePost and every other Power Pages POST)
For data summarization calls, additionally verify (both hard rules):
- The URL contains
$select= (no wildcards)
OData-MaxVersion: 4.0 and OData-Version: 4.0 headers are set
Fix any missing hard-rule header before proceeding. Missing CSRF produces 500s; missing
$select or OData headers produces 403/400s. A missing X-Requested-With only produces a
validator warning — add it for consistency, but it does not break the run.
7.3 Build check
cd "<PROJECT_ROOT>"
npm run build
Fix any type or import errors. Common issues: missing import of the summarization service in a
wired page; type mismatch between DataSummaryResponse and the UI consumer; duplicate
getCsrfToken declarations (if Phase 5 failed to reuse the existing helper).
7.4 Present verification results
| Target file | API | Service fn | Wrapper | UI call site | Headers ✓ | $select ✓ |
|---|
src/pages/SearchResults.tsx | Search summary | fetchSearchSummary | useSearchSummary | Yes | Yes | n/a |
src/pages/CaseDetail.tsx | Data summarization | fetchDataSummary (optionally wrapped as fetchCaseSummary) | useCaseSummary | Yes | Yes | Yes |
src/pages/ProductDetail.tsx | Data summarization | fetchDataSummary | useProductSummary | Yes | Yes | Yes |
(Same row order and example file paths as the Phase 2 manifest example, so a maintainer reading
both tables can trace each row top-to-bottom. Row 2 mirrors the Microsoft-shipped support-case
recipe — a Data Summarization call configured for incidents with the case_summary prompt
identifier.)
Build status: Pass / Fail (with details).
Output: all integration files verified; project builds.
Phase 8: Review & Deploy
Goal: Record skill usage, present a summary, and offer deployment.
8.1 Record skill usage
Reference: ${PLUGIN_ROOT}/references/skill-tracking-reference.md
Use --skillName "AddAiWebapi".
8.2 Present summary
| Step | Status | Details |
|---|
| Web roles | Created via /create-webroles / Reused existing / Skipped | role name(s) |
| Layer 1/2 (Web API settings + permissions) | Created via /integrate-webapi / Reused existing / Skipped (search-only) | list of files written |
| Summarization service | Created / Extended | exported functions, file path |
| Framework wrappers | Created / Extended | hook/composable/service paths |
| UI call sites | Wired | list of files |
| Layer 3 (Summarization/* settings) | Created / Already existed / Skipped | Summarization/Data/Enable, one per prompt |
8.3 Ask to deploy
| Question | Header | Options |
|---|
| Everything is ready. Deploy the site so the summarization APIs become live? | Deploy | Yes, deploy now (Recommended), No, I'll deploy later |
Yes: invoke /deploy-site.
No: acknowledge. Remind that the API calls will not work until the site is deployed with the
new settings and permissions.
8.4 Post-deploy notes
Surface these to the user at the end of the run:
- Search Summary toggle — for any Search Summary integration, remind the user to flip
Set up workspace → Copilot → Site search (preview) → "Enable Site search with generative
AI (preview)". Without it, the endpoint returns the disabled envelope and the UI renders
the remediation card instead of a summary.
- Test recipe — for Data Summarization, open a record-detail or list page, trigger the
summary, confirm 200 + rendered text, then click a recommendation chip and confirm the
follow-up sends
RecommendationConfig. For Search Summary, perform a search and confirm
the summary renders above keyword hits with citation anchors pointing at the SPA route
(not /page-not-found/). The 90041005 "nothing to summarize" branch is normal for the
Microsoft-shipped support-case recipe on a freshly-created case with no comments — test
with a record that has substantive content in every selected / expanded column.
- When the disabled-state card or
90041001 shows up — walk the admin-hierarchy
checklist in references/ai-api-reference.md §1 "Troubleshooting: AI feature appears
disabled (admin hierarchy)". Retry doesn't help; an admin or maker has to change
governance / flip the site toggle.
- 403 on any summarization call is always a Layer 1/2 issue (column casing in
Webapi/<table>/fields, or missing read: true table permission) — re-run
/integrate-webapi in AI-only read mode rather than hand-editing YAML.
- Full error-code reference (
90041001 … 90041006) is in
references/ai-api-reference.md §2 "Error codes". Open it when the user reports a 400.
- Column permission profiles can silently hide content. If a summary has obvious
omissions, check Dataverse column permission profiles on the web role before suspecting
the prompt or fields list.
Output: summary presented, deployment completed or deferred, post-deploy guidance given.
Important Notes
Throughout all phases
- Use TaskCreate/TaskUpdate to track progress at every phase.
- Ask for user confirmation at key decision points (list below).
- Sequential agent spawning — per the "Agent spawning" rule in
plugins/power-pages/AGENTS.md. Never spawn ai-webapi-integration in parallel across targets (every target extends the same aiSummaryService.* file, so parallel runs would conflict).
- Commit at milestones — after implementation (Phase 5) and after settings creation (Phase 6).
- Never use an OData wrapper for summarization fetches — raw
fetch only.
- Never write Layer 1/2 files directly — always delegate to
/integrate-webapi / /create-webroles. This skill is Layer 3.
Key decision points (wait for user)
The list below is the conservative upper bound — many runs hit fewer prompts because skip
checks (search-only run, Layer 1/2 ready, no list/intent-mismatch targets) eliminate whole
branches. Realistic worst case for a multi-target first-time run is ~10 prompts; a clean
re-entry tweak is just 1 prompt (the Phase 1.0 mode question).
- At Phase 1.0 (re-entry detection): tweak existing surface, add a new surface, or
review what's already wired. Only fires when a previous
/add-ai-webapi run left a
service file or Summarization/* settings on disk.
- At Phase 1.5: bootstrap deploy or stop (if
.powerpages-site is missing).
- After Phase 3 (main): confirm which APIs / targets to integrate.
- Phase 3 per-target follow-ups (variable count): list-trigger choice (one per list
target), and scope-confirmation (one per
scope-extends-beyond-existing-fetch,
needs-definition, or intent-mismatch row). Question text and option lists live in
references/scope-classification.md.
- At Phase 4.2: create missing web role via
/create-webroles (if needed). The
sub-skill is invoked with the caller-suppress sentinel — its own deploy prompts don't
fire.
- At Phase 4.2 (Skip path only): confirm continuing despite known broken-runtime risk.
- Inside the Phase 4.3
/integrate-webapi delegation: approve its
table-permissions-architect plan and its webapi-settings-architect plan (each
architect owns its own plan-mode prompt; the sub-skill is in AI-only read mode so its
commit and deploy prompts are suppressed).
- At Phase 5.5: commit the integration changes now or later.
- Inside the Phase 6.3
ai-webapi-settings-architect call: approve its plan.
- At Phase 6.4: commit the new settings now or later.
- At Phase 8.3: deploy now or later.
List-summary use case playbook
When the target is a LIST of records (not a single record), the defaults for a single-record
Copilot card are the wrong defaults — collection endpoint, tabular-insight prompt,
ContentSizeLimit=200000, normalizeSummaryString + safe-markdown renderer, etc.
The full 10-rule playbook (collection endpoint, scope mirroring, prompt size, nav-property
casing, mandatory ContentSizeLimit) lives in
${PLUGIN_ROOT}/skills/add-ai-webapi/references/ai-api-reference.md §2 "List-summary
playbook". Read that section before any list-summary target reaches Phase 5 — the Phase 5
agent and the Phase 6 settings architect both reference the same playbook.
Progress tracking
Before starting Phase 1, create a task list with all phases using TaskCreate:
| Task subject | activeForm | Description |
|---|
| Check site is ready | Checking site prerequisites | Locate project root, detect framework, check data model, deployment status, web-role inventory |
| Find where AI summaries fit | Scanning code for AI summary opportunities | Use Explore agent to find search/data/case candidates, existing infra, and delegation decisions |
| Confirm what to add | Confirming the AI summary plan | Present manifest and confirm which APIs and targets to integrate |
| Set up data access for AI | Setting up Web API access and permissions | Invoke /create-webroles if needed, then /integrate-webapi in AI-only read mode (or skip for search-only) |
| Add AI summary code | Adding AI summary code to your pages | Sequential ai-webapi-integration calls: first target creates shared service + CSRF helper, remaining targets extend it |
| Register AI prompts | Registering AI prompt settings | Invoke ai-webapi-settings-architect to create Summarization/* settings |
| Verify everything | Verifying file inventory, headers, and the build | Confirm service file, wrappers, UI wiring, header contract, run project build |
| Review and deploy | Reviewing summary and deploying | Record skill usage, present summary, offer /deploy-site, give post-deploy guidance |
Mark each task in_progress when starting and completed when done via TaskUpdate.
Begin with Phase 1: Verify Site Exists