@salesforce/afv-skills 1.45.0 → 1.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/package.json +1 -1
  2. package/skills/agentforce-observe/SKILL.md +32 -4
  3. package/skills/agentforce-observe/references/ahm-alerts.md +719 -0
  4. package/skills/automation-flow-generate/SKILL.md +11 -5
  5. package/skills/consumer-goods-promotion-bo-api-deploy/SKILL.md +275 -0
  6. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/README.md +32 -0
  7. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/SetCommentValue.cls +75 -0
  8. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/SetCommentValue.cls-meta.xml +5 -0
  9. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/interview-answers.json +13 -0
  10. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/copy.json +10 -0
  11. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/create.json +20 -0
  12. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/update.json +16 -0
  13. package/skills/consumer-goods-promotion-bo-api-deploy/references/conventions-and-payload-rules.md +273 -0
  14. package/skills/consumer-goods-promotion-bo-api-deploy/references/generate-and-wire.md +236 -0
  15. package/skills/consumer-goods-promotion-bo-api-deploy/references/reference-example-set-comment-value.md +132 -0
  16. package/skills/consumer-goods-promotion-bo-api-deploy/references/smoke-and-verify.md +211 -0
  17. package/skills/dx-code-analyzer-configure/scripts/validate-config.sh +14 -10
  18. package/skills/dx-code-analyzer-run/scripts/apply-fixes.js +45 -4
  19. package/skills/dx-code-analyzer-run/scripts/describe-rule.js +52 -32
  20. package/skills/dx-devops-project-manage/SKILL.md +197 -0
  21. package/skills/dx-devops-project-manage/examples/common-workflows.md +197 -0
  22. package/skills/dx-devops-project-manage/references/cli-commands.md +295 -0
  23. package/skills/dx-devops-project-manage/scripts/create-project.sh +48 -0
  24. package/skills/dx-devops-project-manage/scripts/list-projects.sh +51 -0
  25. package/skills/dx-devops-project-manage/scripts/update-project.sh +96 -0
  26. package/skills/education-cloud-academic-calendar-generate/SKILL.md +225 -0
  27. package/skills/education-cloud-academic-calendar-generate/examples/quarter-calendar.json +47 -0
  28. package/skills/education-cloud-academic-calendar-generate/examples/sample-output.md +57 -0
  29. package/skills/education-cloud-academic-calendar-generate/examples/semester-calendar.json +54 -0
  30. package/skills/education-cloud-academic-calendar-generate/references/calendar-systems.md +127 -0
  31. package/skills/education-cloud-academic-calendar-generate/references/date-validation.md +222 -0
  32. package/skills/education-cloud-academic-calendar-generate/references/foundation_prerequisites.md +40 -0
  33. package/skills/education-cloud-academic-calendar-generate/scripts/validate_calendar_dates.py +143 -0
  34. package/skills/education-cloud-course-catalog-migrate/SKILL.md +321 -0
  35. package/skills/education-cloud-course-catalog-migrate/references/gotchas-detail.md +16 -0
  36. package/skills/education-cloud-course-catalog-migrate/references/gotchas.md +16 -0
  37. package/skills/education-cloud-course-catalog-migrate/references/large-catalog-handling.md +42 -0
  38. package/skills/education-cloud-course-catalog-migrate/scripts/batch_courses.py +36 -0
  39. package/skills/education-cloud-course-catalog-migrate/scripts/detect_linked_courses.py +51 -0
  40. package/skills/education-cloud-course-catalog-migrate/scripts/detect_modality_variants.py +48 -0
  41. package/skills/education-cloud-course-catalog-migrate/scripts/resolve_api_version.py +43 -0
  42. package/skills/education-cloud-course-catalog-migrate/scripts/split_course_code.py +39 -0
  43. package/skills/education-cloud-course-catalog-migrate/scripts/validate_completeness.py +54 -0
  44. package/skills/education-cloud-multi-campus-configure/references/foundation_prerequisites.md +3 -5
  45. package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +177 -0
  46. package/skills/education-cloud-student-recruitment-agent-configure/references/agent-and-subagents.md +151 -0
  47. package/skills/education-cloud-student-recruitment-agent-configure/references/customer-narration.md +34 -0
  48. package/skills/education-cloud-student-recruitment-agent-configure/references/execution-model.md +54 -0
  49. package/skills/education-cloud-student-recruitment-agent-configure/references/flows.md +82 -0
  50. package/skills/education-cloud-student-recruitment-agent-configure/references/grounding.md +199 -0
  51. package/skills/education-cloud-student-recruitment-agent-configure/references/permissions.md +183 -0
  52. package/skills/education-cloud-student-recruitment-agent-configure/references/platform-enablement.md +82 -0
  53. package/skills/education-cloud-student-recruitment-agent-configure/references/prerequisites.md +158 -0
  54. package/skills/education-cloud-student-recruitment-agent-configure/references/routing.md +141 -0
  55. package/skills/experience-cms-brand-apply/SKILL.md +5 -5
  56. package/skills/experience-cms-brand-create/SKILL.md +2 -2
  57. package/skills/experience-cms-content-generate/SKILL.md +1 -0
  58. package/skills/experience-cms-content-render/SKILL.md +173 -0
  59. package/skills/experience-cms-content-render/assets/angular/DetailPage.component.ts +25 -0
  60. package/skills/experience-cms-content-render/assets/angular/MediaRenderer.component.ts +133 -0
  61. package/skills/experience-cms-content-render/assets/angular/TypeList.component.ts +38 -0
  62. package/skills/experience-cms-content-render/assets/angular/TypeRenderer.component.ts +90 -0
  63. package/skills/experience-cms-content-render/assets/angular/cms-content.component.ts +248 -0
  64. package/skills/experience-cms-content-render/assets/angular/cms-item.service.ts +100 -0
  65. package/skills/experience-cms-content-render/assets/react/DetailPage.tsx +20 -0
  66. package/skills/experience-cms-content-render/assets/react/MediaRenderer.tsx +129 -0
  67. package/skills/experience-cms-content-render/assets/react/TypeList.tsx +40 -0
  68. package/skills/experience-cms-content-render/assets/react/TypeRenderer.tsx +64 -0
  69. package/skills/experience-cms-content-render/assets/react/heuristicRenderer.tsx +310 -0
  70. package/skills/experience-cms-content-render/assets/react/useCmsItem.ts +129 -0
  71. package/skills/experience-cms-content-render/assets/shared/cmsContentType.ts +49 -0
  72. package/skills/experience-cms-content-render/assets/shared/cmsCore.types.ts +96 -0
  73. package/skills/experience-cms-content-render/assets/shared/externalRefs.ts +55 -0
  74. package/skills/experience-cms-content-render/references/bulk-loading.md +60 -0
  75. package/skills/experience-cms-content-render/references/codegen-guardrails.md +111 -0
  76. package/skills/experience-cms-content-render/references/detail-pages.md +87 -0
  77. package/skills/experience-cms-content-render/references/embed-recipes.md +127 -0
  78. package/skills/experience-cms-content-render/references/failure-modes.md +96 -0
  79. package/skills/experience-cms-content-render/references/heuristic-render-rules.md +131 -0
  80. package/skills/experience-cms-content-render/references/init-scaffold.md +122 -0
  81. package/skills/experience-cms-content-render/references/interaction-model.md +173 -0
  82. package/skills/experience-cms-content-render/references/package-api.md +106 -0
  83. package/skills/experience-cms-content-render/references/schema-sync.md +114 -0
  84. package/skills/experience-cms-content-render/references/styling-scopes.md +65 -0
  85. package/skills/experience-cms-content-render/references/verify.md +49 -0
  86. package/skills/experience-cms-content-type-generate/SKILL.md +2 -2
  87. package/skills/experience-content-media-stock-image-search/SKILL.md +5 -4
  88. package/skills/experience-search-coordinate/SKILL.md +198 -0
  89. package/skills/experience-search-coordinate/assets/search-payload-template.json +25 -0
  90. package/skills/experience-search-coordinate/references/content-route.md +313 -0
  91. package/skills/experience-search-coordinate/references/content-type-discovery.md +57 -0
  92. package/skills/experience-search-coordinate/references/media-route.md +172 -0
  93. package/skills/experience-search-coordinate/references/scope-resolution.md +14 -0
  94. package/skills/experience-ui-bundle-localize/SKILL.md +1 -1
  95. package/skills/experience-ui-bundle-localize/references/i18n-setup.md +5 -3
  96. package/skills/experience-ui-bundle-project-generate/SKILL.md +18 -14
  97. package/skills/experience-ui-bundle-project-generate/references/angular-project-generate.md +22 -0
  98. package/skills/experience-ui-bundle-project-generate/references/react-project-generate.md +20 -0
  99. package/skills/experience-ui-bundle-salesforce-data-access/SKILL.md +58 -54
  100. package/skills/experience-ui-bundle-salesforce-data-access/references/caching.md +6 -0
  101. package/skills/experience-ui-bundle-salesforce-data-access/references/graphiti-cli.md +2 -2
  102. package/skills/experience-ui-bundle-salesforce-data-access/references/migration.md +6 -0
  103. package/skills/experience-ui-bundle-salesforce-data-access/references/rest-and-integration.md +2 -1
  104. package/skills/experience-ui-bundle-salesforce-data-access/references/sdk-api.md +6 -0
  105. package/skills/experience-ui-bundle-site-generate/SKILL.md +59 -8
  106. package/skills/experience-ui-bundle-site-generate/references/configure-metadata-digital-experience.md +8 -3
  107. package/skills/experience-ui-bundle-site-generate/references/configure-metadata-language-settings.md +120 -0
  108. package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +336 -0
  109. package/skills/life-sciences-fieldsalesrep-coordinate/references/orchestration-flow.md +143 -0
  110. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-application-flexipage-mapping.md +127 -0
  111. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-deploy-commands.md +116 -0
  112. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-lifesci-metadata-deploy.md +111 -0
  113. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-overview.md +312 -0
  114. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-profile-layout-assignments.md +171 -0
  115. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-state-tracking.md +64 -0
  116. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-trigger-handlers.md +122 -0
  117. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-4-user-provisioning-overview.md +335 -0
  118. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-4-user-provisioning-user-provisioning-details.md +140 -0
  119. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-execution-state-and-recovery.md +196 -0
  120. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-metadata-cache-generation.md +155 -0
  121. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-overview.md +307 -0
  122. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-visit-creation-data.md +211 -0
  123. package/skills/life-sciences-fieldsalesrep-coordinate/references/state-machine-and-changes.md +108 -0
  124. package/skills/life-sciences-kam-coordinate/SKILL.md +241 -0
  125. package/skills/life-sciences-kam-coordinate/references/orchestration-flow.md +152 -0
  126. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-application-flexipage-mapping.md +79 -0
  127. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-deploy-commands.md +131 -0
  128. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-kam-config-records.md +85 -0
  129. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-lifesci-metadata-deploy.md +112 -0
  130. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-overview.md +202 -0
  131. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-profile-layout-assignments.md +67 -0
  132. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-state-tracking.md +65 -0
  133. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-trigger-handlers.md +123 -0
  134. package/skills/life-sciences-kam-coordinate/references/stage-4-participant-role-and-sprint.md +89 -0
  135. package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +337 -0
  136. package/skills/life-sciences-kam-coordinate/references/stage-5-data-creation-data.md +248 -0
  137. package/skills/life-sciences-kam-coordinate/references/stage-6-ipad-validation-script.md +35 -0
  138. package/skills/life-sciences-kam-coordinate/references/stage-6-metadata-cache-generation.md +155 -0
  139. package/skills/life-sciences-kam-coordinate/references/stage-6-user-provisioning-details.md +146 -0
  140. package/skills/life-sciences-kam-coordinate/references/stage-6-user-provisioning-overview.md +89 -0
  141. package/skills/life-sciences-kam-coordinate/references/state-machine-and-changes.md +114 -0
  142. package/skills/life-sciences-prerequisites-validate/SKILL.md +138 -0
  143. package/skills/life-sciences-prerequisites-validate/references/checks-org-settings.md +190 -0
  144. package/skills/life-sciences-prerequisites-validate/references/checks-user-and-package.md +211 -0
  145. package/skills/life-sciences-territory-configure/SKILL.md +217 -0
  146. package/skills/life-sciences-territory-configure/references/territory-metadata.md +262 -0
  147. package/skills/platform-apex-logs-debug/SKILL.md +7 -7
  148. package/skills/platform-custom-application-generate/SKILL.md +4 -4
  149. package/skills/platform-custom-object-generate/SKILL.md +7 -7
  150. package/skills/platform-custom-tab-generate/SKILL.md +1 -1
  151. package/skills/platform-dsar-policy-manage/SKILL.md +272 -0
  152. package/skills/platform-dsar-policy-manage/references/configure.md +106 -0
  153. package/skills/platform-dsar-policy-manage/references/export-and-history.md +123 -0
  154. package/skills/platform-dsar-policy-manage/references/gap-analysis-guide.md +150 -0
  155. package/skills/platform-dsar-policy-manage/references/gap-scan.md +129 -0
  156. package/skills/platform-dsar-policy-manage/references/headless-sor.md +59 -0
  157. package/skills/platform-dsar-policy-manage/references/report-format.md +59 -0
  158. package/skills/platform-dsar-policy-manage/scripts/tests/__init__.py +0 -0
  159. package/skills/platform-dsar-policy-manage/scripts/tests/test_validate_policy_tree.py +76 -0
  160. package/skills/platform-dsar-policy-manage/scripts/validate-policy-tree.py +130 -0
  161. package/skills/platform-flexipage-generate/SKILL.md +4 -0
  162. package/skills/platform-list-view-generate/SKILL.md +1 -0
  163. package/skills/platform-salesforce-connect-adapter-generate/SKILL.md +359 -0
  164. package/skills/platform-salesforce-connect-adapter-generate/references/official-examples.md +69 -0
  165. package/skills/platform-salesforce-connect-adapter-generate/references/scenarios.md +187 -0
  166. package/skills/platform-soql-query/SKILL.md +8 -8
  167. package/skills/platform-value-set-generate/SKILL.md +2 -2
  168. package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +20 -27
  169. package/skills/service-native-voice-recording-transcription-configure/SKILL.md +47 -27
  170. package/skills/service-native-voice-recording-transcription-configure/references/thunderbird-voice-settings.md +13 -9
  171. package/skills/service-native-voice-recording-transcription-configure/scripts/enable-recording-transcription.sh +104 -45
@@ -0,0 +1,82 @@
1
+ # Platform enablement — ordered toggle sequence (concrete write paths)
2
+
3
+ Read at Workflow step 2, item 3 ("Enable the platform toggles"). Do these after the Step 1 preflight gate passes and before agent creation. **Reversibility differs per toggle** — see the *Reversible?* column below; never promise a rollback you haven't confirmed, and warn the user before any flip that can't be undone.
4
+
5
+ > **Each toggle uses a DIFFERENT write path** — they are not all `IndustriesSettings` PUT fields, but two of them (the SRA toggle and Omni-Channel) are the same *shape* of headless-metadata PUT on their own settings type. Do not assume one path. The table gives the write path per toggle; on failure, walk the tier ladder to UI/MDAPI.
6
+
7
+ ## The EDU write path — `IndustriesSettings`, not `setup/org/preferences`
8
+
9
+ Both `enableEducationCloud` (and the `enableXXX` domain toggles) **and** the SRA toggle `enableStudentRecruitmentAgent` are written via the **`IndustriesSettings` headless-metadata PUT**. The `setup/org/preferences` route is **not** wired on the headless gateway — a PUT to it returns `ROUTE_NOT_FOUND`, and a Tooling sObject PATCH on `IndustriesSettings` returns `400 JSON_PARSER_ERROR`. Do not use either; use the PUT (Toggle 2 below). Read the enablement flag back from the top-level `Is*Enabled` projection field.
10
+
11
+ ## Ordered enable sequence
12
+
13
+ This table lists **only the three toggles the skill actually flips.** Their external-grant preconditions (Einstein-for-EDU license, Agentforce provisioning) have no write path and are verified — not enabled — at Step 1; see the note below.
14
+
15
+ | Order | Toggle | Write path | Exact name | Tier | Reversible? | Currency |
16
+ |---|---|---|---|---|---|---|
17
+ | 1 | **Turn on Einstein** (Einstein Setup) | **`EinsteinGptSettings` headless-metadata PUT** flipping member `<enableEinsteinGptPlatform>` (fullName `EinsteinGpt`) — same shape as Toggles 2–3. (Gates the SRA toggle's editAccess.) See "Toggle 1 — write + read" below. | member **`enableEinsteinGptPlatform`** / read **`IsEinsteinGptPlatformEnabled`** (org-pref name `EinsteinGPTPlatformEnabled`) | T1 `EinsteinGptSettings` PUT → T2 `sf` → T3 UI (Setup → Einstein Setup) | **Toggles both ways** (`true`↔`false`) — idempotent set, safe to re-write to the desired state | ✅ **in-skill** — check, enable if off |
18
+ | 2 | **Enable Student Recruitment Agent** | **`IndustriesSettings` headless-metadata PUT** flipping member `<enableStudentRecruitmentAgent>`; read back the top-level projection `IsStudentRecruitmentAgentEnabled` | member **`enableStudentRecruitmentAgent`** / field **`IsStudentRecruitmentAgentEnabled`** | T1 IndustriesSettings PUT → T2 `sf` → T3 UI | **Toggles both ways** (`true`↔`false`) — idempotent set, safe to re-write to desired state | ✅ current (gate `orgHasStudentRecruitmentAgentBetaAccess`) |
19
+ | 3 | **Enable Omni-Channel** | **`OmniChannelSettings` headless-metadata PUT** flipping member `<enableOmniChannel>` (fullName `OmniChannel`) — NOT an EDU toggle, NOT org-pref | field **`enableOmniChannel`** | T1 `/headless/metadata` PUT → T2 `sf`-deploy → T3 UI | Re-writing `true` is idempotent, but **treat as forward-only** — Omni-Channel is not expected to be disabled once on; don't attempt to turn it off | ✅ **required for channel deploy** — the inbound routing flow's Route Work element routes the Messaging service channel to the agent through a fallback queue (all Omni-Channel objects — see `routing.md`) |
20
+
21
+ > **Preconditions — verified in `prerequisites.md`, NOT flipped here.** Two external grants have no write path but gate the toggles above: the **Einstein-for-Education-Cloud license** (`EinsteinForEducationCloud`, P3 — part of the SRA toggle's `editAccess`; if absent, Toggle 2 can't be enabled — report and stop) and **Agentforce provisioning** (P4 — must exist before agent creation; the `BotDefinition` existence check is tier-1-attemptable via `/query` → `sf` → UI, but provisioning itself is a Salesforce grant). Both are verify-only Step-1 gates (see `prerequisites.md` gates P3/P4); do not attempt to enable them here.
22
+
23
+ ### Toggle 1 — Einstein Setup (write + read)
24
+
25
+ `EinsteinGptSettings` is **on the `/headless/metadata` allowlist (read + write)** — same settings-file pattern as `IndustriesSettings`/`OmniChannelSettings`.
26
+
27
+ 1. **Tier 1 — headless metadata PUT** (write-enabled `dispatch`, NOT `dispatch_readonly`): `PUT /services/data/vXX/headless/metadata`, body `{"type":"EinsteinGptSettings","fullName":"EinsteinGpt","xmlRep":"<?xml version=\"1.0\" encoding=\"UTF-8\"?><EinsteinGptSettings xmlns=\"http://soap.sforce.com/2006/04/metadata\"><enableEinsteinGptPlatform>true</enableEinsteinGptPlatform></EinsteinGptSettings>"}`. Synchronous — `200 {"results":[{"success":true,...}]}`, no async job. ⚠️ **Confirmed failure mode on some orgs:** this PUT can instead return `400 UNSUPPORTED_OPERATION — "MetadataCrud does not support UPDATE on type: EinsteinGptSettings"`. Treat that exact error as a clean T1→T2/T3 drop signal — don't retry or reshape the payload. ⚠️ The write member is **`enableEinsteinGptPlatform`** (lowercase `Gpt`) — **NOT** `EinsteinGPTPlatformEnabled` (the org-pref name) nor the `Is*Enabled` read projection; a wrong member is silently dropped and the PUT no-ops. `fullName` is **`EinsteinGpt`**.
28
+ 2. **Tier 2:** `sf`-deploy the `EinsteinGptSettings` member.
29
+ 3. **Tier 3** UI: Setup → Einstein Setup → turn on.
30
+
31
+ **Verify (any path):** either a tooling **query** `SELECT IsEinsteinGptPlatformEnabled FROM EinsteinGptSettings` (returns `200` with the top-level projection), or the headless GET `/headless/metadata?type=EinsteinGptSettings&fullName=EinsteinGpt` and confirm `<enableEinsteinGptPlatform>true</enableEinsteinGptPlatform>` in the returned `xmlRep`. ⚠️ The headless GET can hit the same `UNSUPPORTED_OPERATION — MetadataCrud does not support READ` wall as the write above. **Use the tooling query as the primary verify** on orgs where the write 400'd — don't rely on the headless GET as the fallback read in that case. ⚠️ Do **NOT** use the GET-*by-DurableId* (`/tooling/sobjects/EinsteinGptSettings/<DurableId>`) — it 400s `MALFORMED_QUERY: column Metadata not found` (that object exposes no `Metadata` column); the tooling **query** form above is the reliable read.
32
+
33
+ ### Toggle 2 — the write attempt order (RecruitmentAgentEnabled)
34
+
35
+ > **WARNING: Precondition — verify the license gate first.** The `RecruitmentAgentEnabled` pref's `editAccess` is `OrgPermissions.EinsteinForEducationCloud && EinsteinGPT.orgHasEinsteinGPTEnabled` (+ `isAdminUser && ViewSetup`; a System Administrator satisfies the admin half). If unmet, the toggle can't be enabled. The **license** is a verify-only prereq (P3) — report and stop; **Einstein Setup** (Toggle 1) the skill can enable. Don't fall through the write tiers when the license is missing — they fail identically. (The runtime gate also ANDs in the `StudentRecruitmentAgent256` Gater — Salesforce-granted, not flippable here.)
36
+
37
+ 1. **Tier 1 — headless metadata PUT.** `PUT /services/data/vXX/headless/metadata` via the **write-enabled `dispatch` tool** (NOT `dispatch_readonly` — read-only can return `success:true` **without writing**, so the PUT silently no-ops; always cold-verify), body:
38
+ ```json
39
+ {"type":"IndustriesSettings","fullName":"Industries","xmlRep":"<?xml version=\"1.0\" encoding=\"UTF-8\"?><IndustriesSettings xmlns=\"http://soap.sforce.com/2006/04/metadata\"><enableStudentRecruitmentAgent>true</enableStudentRecruitmentAgent></IndustriesSettings>"}
40
+ ```
41
+ Synchronous — returns `200 {"results":[{"success":true,...}]}`, **no async job, no polling.** Write member is the MDAPI name **`enableStudentRecruitmentAgent`** (NOT the `Is*Enabled` read projection). **Toggles both ways** (`true`↔`false`), so it is an idempotent set — safe to write to the desired state. `success:true` alone is not proof the value changed — always VERIFY with the tooling GET below (cold re-read the top-level projection `IsStudentRecruitmentAgentEnabled`).
42
+ > **WARNING:** If the toggle can't be enabled and the license precondition above is unmet, stop and fix the license — do NOT retry lower tiers, they fail identically.
43
+ 2. **Tier 2 (`sf`, if a shell is present):** `sf`-deploy the `IndustriesSettings` member (fallback if the headless PUT is unavailable on the gateway).
44
+ 3. **Tier 3 (UI):** Setup → Set Up Education Cloud → Set Up Agentforce/Einstein for Education Cloud → **Enable Student Recruitment Agent** → Save.
45
+
46
+ **Paths that do NOT work (don't waste a call on them):** `PATCH setup/org/preferences/RecruitmentAgentEnabled` and a Tooling sObject `PATCH` on `IndustriesSettings/<DurableId>` — the same two dead ends called out in the opening "EDU write path" note above (`ROUTE_NOT_FOUND` / `400 JSON_PARSER_ERROR` respectively).
47
+
48
+ **Verify (any path):**
49
+
50
+ The enablement pref is reflected on the `IndustriesSettings` describe. Reading it by **known DurableId** is a tier-1 call — `GET .../tooling/sobjects/IndustriesSettings/<DurableId>` via `dispatch_readonly` (the plain, non-tooling `/sobjects/` path 404s — this object is tooling-only), using the constant DurableId `bWRjLzBIRS9JbmR1c3RyaWVzU2V0dGluZ3M=` directly. No discovery query is needed — the DurableId is a deterministic constant for this singleton.
51
+
52
+ **Read/write name asymmetry.** One switch, three names: org-pref `RecruitmentAgentEnabled` = MDAPI write member `enableStudentRecruitmentAgent` = read projection `IsStudentRecruitmentAgentEnabled` = Setup UI *"Turn On Student Recruitment Agent."* The **WRITE** (`xmlRep`) uses the MDAPI member `<enableStudentRecruitmentAgent>`; the **READ/VERIFY** inspects the top-level flat projection `IsStudentRecruitmentAgentEnabled` (also mirrored in `.Metadata.enableStudentRecruitmentAgent`). Read the top-level projection, not `.Metadata.*`-only, since some `Is*Enabled` flags have no Metadata sibling.
53
+
54
+ ```bash
55
+ # GET-by-DurableId (headless, dispatch_readonly): tooling/sobjects/IndustriesSettings/<DurableId>
56
+ # constant DurableId: bWRjLzBIRS9JbmR1c3RyaWVzU2V0dGluZ3M=
57
+ # then inspect the TOP-LEVEL field IsStudentRecruitmentAgentEnabled == true (NOT .Metadata.*)
58
+ ```
59
+
60
+ ### Toggle 3 — Omni-Channel (required before channel deploy)
61
+
62
+ Omni-Channel is a Service Cloud platform feature, enabled by setting `OmniChannelSettings` `<enableOmniChannel>true</enableOmniChannel>`. It is **required to deploy either agent to a channel**: the inbound routing flow's Route Work element routes the Messaging service channel to the agent through a required fallback queue, and the queue / routing config / service channel are all Omni-Channel objects. Enable it before the channel-deploy step (`routing.md`).
63
+
64
+ `OmniChannelSettings` is **on the `/headless/metadata` allowlist (read + write)** — same settings-file pattern as `IndustriesSettings`:
65
+
66
+ 1. **Tier 1 — headless metadata PUT** (write-enabled `dispatch`, NOT `dispatch_readonly`): `PUT /services/data/vXX/headless/metadata`, body `{"type":"OmniChannelSettings","fullName":"OmniChannel","xmlRep":"<?xml version=\"1.0\" encoding=\"UTF-8\"?><OmniChannelSettings xmlns=\"http://soap.sforce.com/2006/04/metadata\"><enableOmniChannel>true</enableOmniChannel></OmniChannelSettings>"}`. Synchronous — returns `200 {"results":[{"success":true,...}]}`, no async job. ⚠️ **Confirmed failure mode on some orgs:** this PUT can instead return `400 UNSUPPORTED_OPERATION — "MetadataCrud does not support UPDATE on type: OmniChannelSettings"`. Treat that exact error as a clean T1→T2/T3 drop signal — don't retry or reshape the payload. `fullName` is the singular **`OmniChannel`**.
67
+ 2. **Tier 2:** `sf`-deploy the `OmniChannelSettings` member.
68
+ 3. **Tier 3** UI: Setup → Omni-Channel Settings → Enable.
69
+
70
+ **Verify (any path):** GET `/headless/metadata?type=OmniChannelSettings&fullName=OmniChannel` via `dispatch_readonly` and confirm `<enableOmniChannel>true</enableOmniChannel>` in the returned `xmlRep`. `success:true` on the PUT is not proof by itself — read it back. ⚠️ **Confirmed failure mode:** this GET can 400 `UNSUPPORTED_OPERATION — "MetadataCrud does not support READ on type: OmniChannelSettings"`. Don't substitute a tooling query — `SELECT IsOmniChannelEnabled FROM OmniChannelSettings` 400s `INVALID_TYPE` too. On either failure, verify via Setup UI instead.
71
+
72
+ ## UI fallbacks (retained — use if the primary path fails on the org)
73
+
74
+ - Order 1: Setup → Einstein Setup → turn on.
75
+ - Order 2: Setup → Set Up Education Cloud → Set Up Agentforce/Einstein for Education Cloud → **Enable Student Recruitment Agent** → Save.
76
+ - Order 3: Setup → Omni-Channel Settings → Enable *(required before channel deploy)*.
77
+
78
+ ## Notes
79
+
80
+ - **Required current gates:** Agentforce provisioned (P4, verify), `EinsteinForEducationCloud` license (P3, verify), `RecruitmentAgentEnabled` (Toggle 2), Omni-Channel (Toggle 3).
81
+ - **Both Einstein layers are required** — the platform pref `EinsteinGPTPlatformEnabled` (skill flips, Toggle 1) **and** the license-provisioned `EinsteinForEducationCloud` org perm (verify-only, P3 in `prerequisites.md`).
82
+ - **Omni-Channel (Toggle 3) is required for channel deploy** — the inbound routing flow routes Messaging → agent through a fallback queue; queue, routing config, and service channel are Omni-Channel objects. Enable it before the channel-deploy step. See `routing.md` for the full routing layer.
@@ -0,0 +1,158 @@
1
+ # Prerequisites, licenses, and the three SRA gates
2
+
3
+ Read this at Workflow step 1. It covers what must be true before any SRA setup step, how to **verify each gate with a concrete call**, and the license/permission matrix.
4
+
5
+ > The org's current API version is resolved at Step 0 (`SKILL.md`), before this file is ever read — every `vXX` below reuses that literal. If Step 0 hasn't run yet, run it before any check in this file, rather than guessing a version here.
6
+
7
+ ## Readiness tiers
8
+
9
+ The **Tier** column below uses the three-tier ladder (see `execution-model.md`): **T1** (headless — a named `dispatch`/`dispatch_readonly` REST call over `/headless/metadata`, sObject, Connect, or Tooling-by-Id) · **T2** (`sf` CLI — MDAPI deploy / discovery query, needs a shell) · **T3** (manual UI, or a Salesforce/commercial grant the agent cannot touch).
10
+
11
+ ## Prereq vs. in-skill — the scope boundary (draw this line first)
12
+
13
+ The dividing question is **"can the skill flip it via API?"**:
14
+
15
+ - **Prerequisites → verify only.** If unmet, tell the user to fix it, then **re-verify** — never enable it here. These are: the **Einstein for Education Cloud license** (P3, commercial/provisioning grant); **Education Cloud enablement** (P2 — owned by base Education Cloud domain setup); the **EinsteinGPT add-on license** (the commercial entitlement — distinct from the `EinsteinGPTPlatformEnabled` *toggle*, which IS in-skill-flippable at step 2, next bullet); and the running user being a **System Administrator**.
16
+ - **In-skill → check if present, enable if not**, through the tier ladder **Headless → other MCPs → `sf` CLI → manual UI**. These are: **Einstein Setup** (`EinsteinGPTPlatformEnabled`) and the **SRA toggle** (`RecruitmentAgentEnabled` — the skill's defining action).
17
+
18
+ ## The preflight gate — run this FIRST, before any enable or build work
19
+
20
+ **Step 1 is a hard gate, not a formality.** Before enabling or configuring anything (the toggles at Step 2 onward), verify every prerequisite the skill **cannot fix itself**. If one is unmet, **do not proceed into the skill's own work** — stop, or ask the user to fix it themselves, then re-verify. Building permissions / OWD / grounding for an agent that can never exist is wasted effort; catch it here at Step 1, not when agent creation 501s at Step 9.
21
+
22
+ Classify each check into one of three outcomes:
23
+
24
+ | Outcome | Prerequisites | Action if unmet |
25
+ |---|---|---|
26
+ | **STOP** — external grant; nothing in our ecosystem can flip it | **P4** Agentforce provisioning · **P3** Einstein-for-EDU license · the **SRA Gater** (`StudentRecruitmentAgent256`) · **P5 / F-iv** Data Cloud entitlement · **P1** edition | Report exactly which grant is missing and **halt**. Request it from Salesforce / the account team. Do **not** start the toggles (Step 2). |
27
+ | **ASK-USER** — foundation this skill doesn't own, but the user can self-serve it | **P2 / F-i** EDU enablement · **F-ii** Person Accounts · **F-iii** R&A domain schema | Ask the user to complete that Education Cloud foundation setup to fill that gap, then **re-verify** and continue. Do not re-implement it here. |
28
+ | **ENABLE in-skill** — the skill flips these via the tier ladder | **Einstein Setup** (`EinsteinGPTPlatformEnabled`) · the **SRA toggle** (`RecruitmentAgentEnabled`); running-user builder PS **assignment** is likewise in-skill (Step 4) | Not a gate — Einstein/SRA toggles are the enablement step's job (item 3, `platform-enablement.md`), the PS assignment is item 4's. Check, enable if off, verify. |
29
+
30
+ **Proceed to the toggles (Step 2) only when every STOP and ASK-USER check is green.** These are definitive *now*, at Step 1 — you don't have to wait for a downstream failure to learn the answer. In particular, **provisioning is detectable here**: if `BotDefinition` is an unqueryable / `INVALID_TYPE` object (vs. a `200` with zero rows, which means "provisioned, no bots yet"), the org isn't Agentforce-provisioned — that's a STOP at Step 1, not a surprise 501 at Step 9. Use the concrete verify call for each requirement in the tables below.
31
+
32
+ > **WARNING: When reporting findings, an ENABLE-in-skill item being off is not a FAIL.** `RecruitmentAgentEnabled = false` and `EinsteinGPTPlatformEnabled = false` are the expected starting state — this skill turns them on itself at Step 2/3. Report them as not-yet-enabled/no external action needed, and reserve FAIL/STOP language for the STOP row's unmet external grants.
33
+
34
+ ## Configure vs. verify — the honest split
35
+
36
+ Almost nothing here is *purely* manual. For each prerequisite, separate **can the agent configure it (and at which tier)** from **can the agent verify it**. Even the truly-manual grants get a concrete verify call so the agent confirms org state instead of assuming.
37
+
38
+ | # | Requirement | Configure? (tier) | **Verify call (run this)** | Tier |
39
+ |---|---|---|---|---|
40
+ | P1 | Edition (Enterprise / Performance / Unlimited / Developer) | **No** — commercial | Edition has no SOQL/tooling query field and no tier-1 GET (this one genuinely has no `/query` form, unlike the WHERE-filter verifies below); verify at tier 2 (`sf`) or a tier-3 UI check (Setup → Company Information).<br>Tier 2: `sf org display --target-org <alias> --json` → check `.result.edition` ∈ {Enterprise, Performance, Unlimited, Developer} | T3 |
41
+ | P2 | Education Cloud enabled | **Yes** — verify here (step 2a); if off, ask the user to enable it, then re-verify | **T1** — `dispatch_readonly` GET `/services/data/vXX/tooling/sobjects/IndustriesSettings/bWRjLzBIRS9JbmR1c3RyaWVzU2V0dGluZ3M=` (deterministic DurableId) → top-level **`IsEducationCloudEnabled == true`** (the top-level field; **not** `.Metadata.enableEducationCloud` — that's the write-path member name, see `platform-enablement.md`) | T1 |
42
+ | P3 | **Einstein for Education Cloud license** (the license gate on the SRA toggle) | **No** — **commercial/license grant — verify only** — `OrgPermissions.EinsteinForEducationCloud`, granted by the *Einstein for Education Cloud add-on*. **If absent, the `RecruitmentAgentEnabled` toggle can't be enabled** (it's part of the toggle's `editAccess`). Report it and stop — the skill can't flip a license. | **T1** — `dispatch_readonly` `/query`: `SELECT Status FROM PermissionSetLicense WHERE DeveloperName='EinsteinForEducationCloudPsl'` → confirm **`Status='Active'`** (`OrgPermissions.EinsteinForEducationCloud` itself has no SOQL surface; this PermissionSetLicense is the underlying grant) → fall back to `sf data query` (T2) → UI (T3) | T1 verify (license itself is T3/commercial) |
43
+ | P4 | **Agentforce provisioned** | **No** — **Salesforce grant — no API** | **Preflight STOP check — resolve at Step 1.** Attempt tier-1 `/query` (routable over `dispatch_readonly`) for `BotDefinition` existence → fall back to `sf data query` (T2) → tier-3 UI check.<br>Tier 2: `sf data query -q "SELECT Id FROM BotDefinition LIMIT 1" --target-org <alias>`.<br>**Read the result precisely:** a **`200` with zero rows = provisioned, just no agents yet → PASS** (do not stop). Only an **error / `INVALID_TYPE` / 501 (object not queryable) = NOT provisioned → STOP now**, don't defer to the Step-9 501. | T1 verify (dispatch_readonly /query) → T2 sf (provisioning itself T3) |
44
+ | P5 | Data Cloud / Data 360 | **No** — Home Org grant | query a Data Cloud object / confirm Data Cloud app available | T1 (comes with Home Org) |
45
+
46
+ > **The only prerequisite the agent truly cannot touch via API is P4 (provisioning)** (a Salesforce grant), alongside the commercial license gates P1/P3 and the Data Cloud entitlement P5. Everything else is configurable or delegated, and each gets a verify call.
47
+ >
48
+ > **Running-user access is not a separate gate.** The person running this skill must be a **System Administrator** (stated in the scope line above) plus hold the builder permission sets the config work needs — but **assigning those sets is the skill's own job, done at tier 1** as part of the Step 4 permissions work (`permissions.md`), not a stop/ask-user prerequisite. See "assignment and the perm-set clone are tier 1" below for the mechanics.
49
+ >
50
+ > **Message-consumption billing is out of scope.** Flex Credits / Conversations billing is a *runtime commercial* concern, not a setup gate — SRA configures fine without it and you only feel it at message volume. Confirm SKUs with the account team; the skill does not verify or stop on it.
51
+
52
+ ### Assignment and the perm-set clone are tier 1 (sObject REST)
53
+
54
+ **Assigning** an existing permission set is a **tier-1** sObject POST —
55
+
56
+ Tier 1 (write-enabled `dispatch`):
57
+
58
+ ```json
59
+ dispatch({
60
+ "url": "/services/data/vXX/sobjects/PermissionSetAssignment",
61
+ "method": "POST",
62
+ "body": { "AssigneeId": "<userId>", "PermissionSetId": "<psId>" }
63
+ })
64
+ ```
65
+
66
+ Tier 2 (`sf`, if a shell is present):
67
+ ```bash
68
+ sf org assign permset --name EducationCloudFullAccess --target-org <alias>
69
+ # or, explicitly:
70
+ sf data create record -s PermissionSetAssignment \
71
+ -v "AssigneeId=<userId> PermissionSetId=<psId>" --target-org <alias>
72
+ ```
73
+
74
+ **Creating/cloning** a permission set (`EducationCloudAiAgentAccess`, `permissions.md` step 4b) is also **tier 1** — the clone runs over **plain sObject REST + the collections API** (`POST /sobjects/PermissionSet` → `POST /composite/sobjects` for the object/field-perm rows → `POST /sobjects/PermissionSetAssignment`), all routing over `dispatch`, granular with per-row errors. (`PermissionSet` is *also* on the `/headless/metadata` CRUD allowlist, but the sObject-REST path is the one used here — cleaner and more granular than a metadata deploy. `sf`-deploy / UI remain the tier-2/3 fallbacks.) See `permissions.md` Step 4b for the full row shapes.
75
+
76
+ ## The three SRA gates — verify all three with concrete calls
77
+
78
+ SRA is gated behind three conditions. If any is false, most agent steps 501/403. **Run the verify call; report which gate is missing rather than guessing.**
79
+
80
+ 1. **Agentforce provisioned** (P4).
81
+
82
+ Attempt the tier-1 `/query` (routable over `dispatch_readonly`) for `BotDefinition` existence → fall back to `sf data query` (T2) → UI (T3).
83
+
84
+ Tier 2 form:
85
+ ```bash
86
+ sf data query -q "SELECT Id FROM BotDefinition LIMIT 1" --target-org <alias>
87
+ ```
88
+ **A `200` with zero rows = provisioned (no agents yet) → PASS.** An **error / `INVALID_TYPE` / 501 = NOT provisioned → STOP at Step 1** and request provisioning — don't start the foundation work and wait for the Step-9 agent-creation call to fail. No API enables provisioning.
89
+ 2. **Education Cloud enabled** — **T1** — top-level **`IsEducationCloudEnabled == true`** on IndustriesSettings via `dispatch_readonly` tooling GET-by-DurableId (the top-level field; **not** `.Metadata.enableEducationCloud`, which is the write-path member name — see `platform-enablement.md`).
90
+ 3. **SRA gate** — the runtime access check `orgHasStudentRecruitmentAgentBetaAccess` is a **three-part AND**, from core `IndustriesEducation.accessChecks.xml`:
91
+
92
+ ```text
93
+ orgHasStudentRecruitmentAgentBetaAccess =
94
+ OrgPermissions.EinsteinForEducationCloud ← the license gate (P3)
95
+ , OrgPreferences.RecruitmentAgentEnabled ← the toggle we flip
96
+ , Gater.com.salesforce.StudentRecruitmentAgent256 ← a perm-Gater / feature flag (Salesforce-granted)
97
+ ```
98
+ (The older sibling check `orgHasEducationAdmissionsAgentAccess` uses the un-suffixed `Gater.com.salesforce.StudentRecruitmentAgent`; the `256` suffix is the current one.)
99
+
100
+ - **The toggle's presence, not its value** — same `IndustriesSettings` GET-by-DurableId as item 2: the response including a top-level `IsStudentRecruitmentAgentEnabled` field (regardless of `true`/`false`) confirms the preference exists in this org. Its current value doesn't matter here — Step 2/3 sets it.
101
+ - **License gate (P3) — what makes the toggle non-editable.** The `RecruitmentAgentEnabled` pref's `editAccess` requires `OrgPermissions.EinsteinForEducationCloud && EinsteinGPT.orgHasEinsteinGPTEnabled` (+ `isAdminUser && ViewSetup` — a **System Administrator** satisfies the admin half). Missing the license or Einstein → the toggle can't be enabled. The **license** (P3) is verify-only; **Einstein Setup** the skill can flip at tier 1 — an `EinsteinGptSettings` headless-metadata PUT of member `<enableEinsteinGptPlatform>` (see `platform-enablement.md` Toggle 1). Read it back per `platform-enablement.md` Toggle 1's verify — the tooling query form `SELECT IsEinsteinGptPlatformEnabled FROM EinsteinGptSettings` (GET-by-DurableId 400s here). Report a license miss and stop; enable Einstein Setup if that's what's off, then retry.
102
+ - **The Gater** (`StudentRecruitmentAgent256`) is a **Perm-Gater / feature flag, NOT a perm-set org permission** — it is **not** grantable via a permission set and there is no reliable `PermissionSet WHERE Permissions*=true` SOQL for it (`PermissionsAccsStuRecruitmentAgent` is a licensing-catalog artifact, not the runtime gate — see the note below). Confirm the gater indirectly: the "Enable Student Recruitment Agent" toggle is present/editable in Setup, and `RecruitmentAgentEnabled` can be turned on. If the toggle is missing or the write 501/403s after P3 is satisfied, the gater hasn't been enabled on the org — request enablement from Salesforce.
103
+
104
+ > `RecruitmentAgentEnabled` is the **enablement** pref (the toggle we flip — see `platform-enablement.md`). The **actual runtime gate** is the three-part expression above (Einstein-for-EDU license + pref + Gater). **WARNING: `AccsStuRecruitmentAgent` is NOT the runtime gate** — it appears only in EBF *licensing* metadata (`.pld.xml`, `Accs*Agent` family, default off), never in the SRA access-check. Treat it as a licensing-catalog SKU line, not the perm the runtime evaluates.
105
+
106
+ ## Step 2a — Verify the EDU foundation (head-start check, not a blind delegation)
107
+
108
+ SRA is built **on top of** the Education Cloud R&A foundation. Do **not** assume base Education Cloud domain enablement has been run — **verify each piece**, and if one is missing, ask the user to complete that setup to fill *that gap*, then re-verify. Never re-implement its enablement here, and never proceed on an unverified foundation.
109
+
110
+ Opening line to the user: *"If you've already set up your Education Cloud foundation for Recruitment & Admissions, that's a great head start — let me confirm the parts your admissions agent needs are actually in place."*
111
+
112
+ | # | Foundation piece | Why SRA needs it | Verify | Tier |
113
+ |---|---|---|---|---|
114
+ | F-i | **Education Cloud enabled** | Everything below assumes it | **T1** — the IndustriesSettings GET-by-DurableId above → top-level `IsEducationCloudEnabled == true` | T1 |
115
+ | F-ii | **Person Accounts** enabled | Flows B2/B4/B5 all *Process Person Account*; SRA record creation breaks without it | `IsPersonAccountEnabled` on the org / `Account` has a `IsPersonAccount` field; attempt tier-1 `/query` (routable over `dispatch_readonly`) for the WHERE-filter/describe read, e.g. `SELECT Id FROM Account WHERE IsPersonAccount = true LIMIT 1` → fall back to `sf data query` (T2) → tier-3 UI check (Setup → Person Accounts). **Read the result precisely: a `200` with zero rows = the `IsPersonAccount` field exists and is queryable, i.e. Person Accounts IS enabled — there just aren't any Person Account records yet → PASS** (do not stop). Only an **error / `INVALID_FIELD` (field not recognized on `Account`) = NOT enabled → STOP now.** Zero rows is not ambiguous — it is a clean query against a field that only exists once the feature is on. | T1 verify (dispatch_readonly /query) → T2 sf |
116
+ | F-iii | **R&A / Admissions domain objects available** (schema, not records) | Flows and subagent actions bind to the objects. The agent *creates* records at runtime — **empty objects are fine; record presence is not a setup prerequisite** | existence of `AcademicInterest`, `AcademicTerm`, `Learning`, `ApplicationTimeline`, `ProgramTermApplnTimeline`, `IndividualApplication` via `EntityDefinition` — attempt tier-1 `/tooling/query` (routable over `dispatch_readonly`; `EntityDefinition` is tooling-only, so use `/tooling/query` not data `/query`) → fall back to `sf data query` (T2) → tier-3 UI (Object Manager) | T1 verify (tooling /query) → T2 sf |
117
+ | F-iv | **Data Cloud available** | Learning Program grounding (P5) | `SELECT Id FROM DataStream LIMIT 1` at **T1** (routable over `dispatch_readonly`) — a `200` confirms Data Cloud is provisioned, even if the only rows are internal/system streams (Education-specific streams are F-iv.a's concern, not this check's) → fall back to `sf` (T2) → tier-3 UI | T1 verify (dispatch_readonly /query) (comes with Home Org) |
118
+ | F-iv.a | **Standard DMOs pre-provisioned** (Learning Program, Academic Term, PTAT, Application Timeline) | Grounding retriever indexes them | These come pre-provisioned with Education Cloud (F-i) + Data Cloud (F-iv) — nothing to install. Verify directly via the DMO's own Connect REST resource (not a SOQL-queryable sObject, and not `DataStream`): `GET /services/data/vXX/ssot/data-model-objects/ssot__<Object>__dlm` (routable over `dispatch_readonly`), using the DMO's own name — `LearningProgram`, `AcademicTerm`, `ApplicationTimeline`, and **`ProgramTermApplicationTimeline`** (**WARNING:** spelled out in full — not F-iii's abbreviated `ProgramTermApplnTimeline` sObject name, which 404s here) → `200` = present → fall back to `sf` (T2) → tier-3 UI (Data Cloud → Data Model). A `404` here (not a `DataStream` search or a guessed sObject name erroring) is the only valid absence signal | T1 verify (dispatch_readonly GET /ssot/data-model-objects) → T2 sf |
119
+
120
+ > **WARNING: F-iii's pass condition is `EntityDefinition` presence alone — do not additionally require a live `describe`/query-as-data success on these objects.** The running user's ability to actually query or describe them as data depends on the builder persona's EDU permission sets (*Education Cloud Full Access*, etc.), which this skill itself assigns later at step 4a — not something F-iii should presuppose. A `describe`/query attempt against one of these objects failing with an access- or "not supported"-shaped error **before** step 4a runs is expected, not a sign the domain schema is missing (see SKILL.md Gotchas: EDU objects show 0 fields until *Education Cloud Full Access* is assigned). Only treat the object as genuinely missing — and only then ask the user to complete Education Cloud foundation setup — if it's absent from `EntityDefinition` itself.
121
+
122
+ > **WARNING: F-iv.a's pass condition is DMO presence alone — do not also check for the `DataStream`/DLO ingestion pipeline and report its absence as a gap.** The CRM connector, data streams, and DLO→DMO mapping that actually populate these DMOs are built by *this skill* at setup time (see `grounding.md`'s Mechanism 2 data-spine section) — they are work this skill owns, not a foundation prerequisite to verify beforehand. Finding zero `LearningProgram`/`AcademicTerm`/etc. data streams during preflight is the expected starting state, not something to flag as a readiness gap — same category as F-iii's "0 records is fine."
123
+
124
+ ### AEA/Employee path only — community licensing prerequisite
125
+
126
+ If the customer wants the AEA/Employee agent's authenticated community access, verify the org carries the community licenses and profiles the Campus Tours sharing rule's target portal group depends on (`permissions.md` Step 6b) — **4 UserLicenses** (`Customer Community`, `Customer Community Login`, `Customer Community Plus`, `Customer Community Plus Login` — these are base UserLicenses, not add-on PermissionSetLicenses; querying `PermissionSetLicense` for these names returns 0 rows even on a fully-licensed org) and **4 Profiles** (`Customer Community Login User`, `Customer Community Plus Login User`, `Customer Community Plus User`, `Customer Community User`). Skip entirely on an ASA/Service-only build — the sharing rule's authenticated-community target only matters for the AEA path.
127
+
128
+ Verify (attempt T1 `/query` over `dispatch_readonly` → `sf` fallback):
129
+ ```sql
130
+ SELECT Name FROM UserLicense WHERE Name IN ('Customer Community','Customer Community Login','Customer Community Plus','Customer Community Plus Login')
131
+ SELECT Name FROM Profile WHERE Name IN ('Customer Community Login User','Customer Community Plus Login User','Customer Community Plus User','Customer Community User')
132
+ ```
133
+ If none of these are present, the AEA path's portal group (`permissions.md` Step 6b) likely doesn't exist yet — flag that to the customer rather than assuming Step 6b's target is already there.
134
+
135
+ Match each missing piece to how it actually gets fixed — don't treat every gap as one blanket foundation-setup ask, since Data Cloud isn't part of that foundation setup:
136
+
137
+ - **F-i, F-ii, F-iii** (EDU enablement, Person Accounts, R&A domain schema) → *"The agent needs <piece>, which isn't set up yet — let's get your Education Cloud foundation set up first, then I'll re-verify and continue."* Ask the user to complete base Education Cloud domain enablement (which drives `enableEducationCloud`, Person Accounts, and R&A-domain enablement, bringing the object schema).
138
+ - **F-iv** (Data Cloud) → **do not** fold this into the Education Cloud foundation ask above — Data Cloud is a **Home-Org entitlement** (P5): if it's absent, treat it like the other Salesforce grants (P3/P4) — report the gap and stop; it is not something this skill can flip. The grounding *setup* built on top of Data Cloud is done later **inside this skill** (`grounding.md`), not here.
139
+
140
+ ## Org requirement — provisioned + entitled, not a bare org
141
+
142
+ Any org this skill runs against must be **Agentforce-provisioned** (P4), carry the **Einstein for Education Cloud** license (P3, `OrgPermissions.EinsteinForEducationCloud`) with **EinsteinGPT enabled**, and have the **SRA Gater** (`Gater.com.salesforce.StudentRecruitmentAgent256`) turned on — these are Salesforce grants a bare scratch org does **not** have, and **none of them can be flipped by this skill**. They are **preflight STOP checks (Step 1)**: verify them before any Step 2+ work and halt if any is missing, rather than doing the foundation build and hitting the wall at Step 9 (agent creation 501s / the SRA toggle is absent or "not editable"). (See "The preflight gate" and "The three SRA gates" above for how to verify each.)
143
+
144
+ ## Org permissions (classify — don't lump together)
145
+
146
+ | Org perm / gate | Class | Notes |
147
+ |---|---|---|
148
+ | `OrgPermissions.EinsteinForEducationCloud` | **SRA license gate (P3)** | The add-on org perm the `RecruitmentAgentEnabled` toggle's `orgAccess`/`editAccess` require (with `EinsteinGPT.orgHasEinsteinGPTEnabled`). Missing it → the toggle can't be enabled. |
149
+ | `Gater.com.salesforce.StudentRecruitmentAgent256` | **SRA feature gate** | The perm-**Gater** the runtime actually evaluates in `orgHasStudentRecruitmentAgentBetaAccess`. NOT a perm-set org permission; Salesforce-granted; not SOQL-queryable as a `Permissions*` field. |
150
+ | ~~`AccsStuRecruitmentAgent`~~ | **licensing-catalog artifact — NOT the runtime gate** | Appears only in EBF `.pld.xml` licensing metadata (`Accs*Agent` family, default off), never in core SRA access-checks. Do not treat as the perm the runtime checks. |
151
+ | `BotHyperforceRuntime` | Generic platform | Agentforce runtime prereq — applies to any Agentforce agent, not SRA-specific. |
152
+ | `CopilotDigitalChannelsPilot` | Generic platform | Copilot/digital-channels prereq — not SRA-specific. |
153
+
154
+ ## Licenses / add-ons (confirm real SKUs with account team)
155
+
156
+ The **customer-facing minimum**: Agentforce Service (unauth) / Employee (auth) + Education Cloud + Einstein for Education Cloud + Data Cloud + Knowledge + Messaging. Confirm the exact SKUs with the account team.
157
+
158
+ A fully-provisioned org may additionally carry: `AgentforceServiceAgentAddOn` + `AgentforceEmployeeAgentAddOn` (+ `…ManagerAddon`), `EducationCloudAddOn` + `EducationCloudExprcCloudAddOn`, `EinsteinForEducationCloudAddOn`, EinsteinGPT add-ons (Copilot/Platform/PromptBuilder), `CustomerCommunity(Plus)(Login)`, `EmbeddedServiceMessaging(+UserPsl)`, `ChatbotEnabled`, `KnowledgeUser`, `GenieDataPlatformStarter`, `CdpSegmentsActivationsCard` — treat this as a superset (some entries are Transfer-Credit- or community-specific and not required for SRA).
@@ -0,0 +1,141 @@
1
+ # Deploy to channels, Omni-Channel routing & user verification
2
+
3
+ Read at Workflow steps 12–13. This is the full per-agent channel stack: each agent gets its own Experience Cloud site, messaging channel, Omni-Channel routing configuration, fallback queue, and inbound routing flow. User verification (auth/AEA only) is set inline during channel + site creation (Step 12 sub-steps 5–6), not as a separate step. **Prerequisite:** Omni-Channel must be enabled (`platform-enablement.md` Toggle 3) — the inbound flow's Route Work element routes through Omni-Channel objects, so it is required for channel deploy, not optional.
4
+
5
+ ## Two "channel" objects — do not conflate them
6
+
7
+ - **`ServiceChannel`** = the Omni-Channel routing *work-type*. **One per org, SHARED by both agents.** The relevant one is `Messaging` (DeveloperName `sfdc_livemessage`, RelatedEntity `MessagingSession`) — this is what the Route Work element's *Service Channel* field points at. Reuse it; do not create a new one.
8
+ - **`MessagingChannel`** = the MIAW embedded messaging channel (MessageType `EmbeddedMessaging`). **One PER agent.** This is the customer-facing channel bound to a site.
9
+
10
+ ## Shared vs per-agent — read everything FIRST
11
+
12
+ Before creating anything, read the current state of every layer. Shared layers usually already exist on any Service-Cloud org; per-agent layers are SRA-specific and absent until you create them. Attempt each read at tier 1 (`dispatch_readonly` `/query` or `/headless/metadata` GET); fall back to `sf data query` (tier 2) or a UI check (tier 3) if a call doesn't return.
13
+
14
+ | Layer | Scope | Read to run first |
15
+ |---|---|---|
16
+ | Omni-Channel enabled | **Shared** | GET `/headless/metadata?type=OmniChannelSettings&fullName=OmniChannel` → confirm `<enableOmniChannel>true</enableOmniChannel>` |
17
+ | `ServiceChannel` (Messaging) | **Shared** | `SELECT Id, DeveloperName, MasterLabel, RelatedEntity FROM ServiceChannel` — **note: no `IsActive` column; do not query it.** The `Messaging` row (DeveloperName `sfdc_livemessage`, RelatedEntity `MessagingSession`) is standard on any messaging org — **reuse it, do not create** |
18
+ | Experience Cloud site (`Network`) | **Per agent** | `SELECT Id, Name, Status FROM Network` |
19
+ | `MessagingChannel` | **Per agent** | `SELECT Id, MasterLabel, MessageType, MessagingPlatformKey FROM MessagingChannel` — **note: there is no `ChannelType` column; do not query it** |
20
+ | Routing config (`QueueRoutingConfig`) | **Per agent** | `SELECT Id, DeveloperName FROM QueueRoutingConfig` |
21
+ | Fallback queue (`Group` Type=Queue + 2×`QueueSobject` + `GroupMember`) | **Per agent** | `SELECT Id, DeveloperName, Type FROM Group WHERE Type='Queue'`; `SELECT QueueId, SobjectType FROM QueueSobject` (expect `MessagingSession` **and** `MessagingEndUser`); `SELECT GroupId, UserOrGroupId FROM GroupMember` (expect ≥1 member) |
22
+ | Inbound routing flow (`RoutingFlow`) | **Per agent** | `SELECT ApiName, ProcessType, IsActive FROM FlowDefinitionView WHERE ProcessType='RoutingFlow'` — query by **`ApiName`**, not `DeveloperName` (`FlowDefinitionView` has no `DeveloperName` column) |
23
+
24
+ **Interactive gate — Experience Cloud sites.** If the `Network` read returns existing sites, **stop and ask the user** whether to use any of them for the agents, and — if both agents are in scope — which agent maps to which site. Do not silently reuse or stand up sites. If no sites exist, hand the user the tier-3 UI create for one per agent (Step 12 sub-step 1). **WARNING:** Note the read may return an internal **ESW plumbing site** (from the deployment wizard in Step 12 sub-step 5, named `ESW_...`) — that is not a customer-facing placement site; do not offer it as one.
25
+
26
+ ## Step 12 — Per-agent channel + routing stack
27
+
28
+ One inbound channel serves **one** agent, so build a full stack for **each** agent in scope: the Service (ASA, unauthenticated) agent and the Employee (AEA, authenticated) agent. The numbered list below is Step 12's own internal sequence — referred to as **"sub-step N"** throughout this file to keep it distinct from the top-level SKILL.md workflow steps (1–14) referenced alongside it.
29
+
30
+ **Front-load the slowest part — the site — then build the routing layer while it provisions, then come back and finish the site.** Community/site creation is async and wizard-heavy — the slowest single thing in this stack — so kick it off first rather than last; the routing config → queue → inbound flow → channel/ESD are otherwise self-contained and don't need the site to exist first. The site only *embeds* the deployment's already-built component at the very end:
31
+
32
+ 1. **Resolve site status per agent (see the interactive gate above), then front-load creation for any agent that still needs one** — **T3**. For every agent in scope that doesn't already have a site, create it now, before anything else in this stack, and explain why to the customer per SKILL.md's deferred-wait narration guidance — provisioning is the slowest part of this build, so starting it first means it's more likely to be ready by the time it's actually needed. Setup → Digital Experiences → **All Sites** → **New** → **Education Portal** → **Get Started**, then set the URL path. Don't wait for it to reach `Live` here — move straight into sub-step 2 once creation is kicked off. **If both agents are in scope, each needs its own separate site — no sharing one between them.** If every in-scope agent already has a site, skip straight to sub-step 2.
33
+ 2. **Routing configuration (`QueueRoutingConfig`)** [T1] — one per agent. Create this **before the queue** — the queue links to it, not the reverse (the `QueueRoutingConfigId` FK lives on `Group`, pointing up at the config). Create via plain **sObject REST (tier 1)** — `POST /sobjects/QueueRoutingConfig`; fall back to `sf` / UI (Setup → Omni-Channel → Routing Configurations). **WARNING: A capacity field is mandatory but not flagged in the field metadata:** the required set is `DeveloperName` + `MasterLabel` + `RoutingModel` (`MostAvailable` | `LeastActive` | `ExternalRouting`) + `RoutingPriority` (int) + **exactly one of** `CapacityWeight` (Units of Capacity) or `CapacityPercentage`. Omitting both returns `FIELD_INTEGRITY_EXCEPTION: "One capacity field must be defined."` even though `describe` marks the capacity fields nillable — set one (e.g. `CapacityWeight: 1`).
34
+ 3. **Fallback queue** [T1] — one per agent, created **with its routing config already linked**. A queue is a `Group` (`Type='Queue'`) plus **two `QueueSobject` rows — `MessagingSession` AND `MessagingEndUser`** — and **at least one `GroupMember`** (the running/admin user). Set `QueueRoutingConfigId` to the sub-step-2 config **inline in the `POST /sobjects/Group` body** (it is a field on `Group`) so no follow-up edit is needed — the inline FK persists at create. All writes are plain **sObject REST (tier 1)** — `POST /sobjects/Group`, then two `POST /sobjects/QueueSobject`, then `POST /sobjects/GroupMember` (`{GroupId, UserOrGroupId}`); the `Queue` metadata type is read-only, so writes stay on sObject REST.
35
+ - **WARNING: API-name trap:** the second supported object's `SobjectType` is **`MessagingEndUser`**, NOT `MessagingUser` — "Messaging User" is the Setup UI label only. `QueueSobject.SobjectType` is a restricted picklist; posting `MessagingUser` returns `400 INVALID_OR_NULL_FOR_RESTRICTED_PICKLIST`. (Same UI-label-≠-API-name trap as the non-existent `MessagingChannel.ChannelType` column.)
36
+ - **Read first:** a messaging org often already has a generic `FallbackQueue` wired to `MessagingSession` — offer to reuse it before creating a per-agent one (check it carries BOTH supported objects + a member, not just `MessagingSession`).
37
+ - **WARNING:** Queue setup is **non-atomic** (Group → QueueSobject×2 → GroupMember are separate calls, no spanning transaction) — capture the `00G` Id and `DELETE /sobjects/Group/{id}` (cascades to `QueueSobject`/`GroupMember`) to roll back a partial. A blind re-POST of an existing member returns `DUPLICATE_VALUE`, not a no-op.
38
+ 4. **Inbound routing flow (`RoutingFlow`)** [T1] — one per agent, built from scratch (see the two shapes below). Its Route Work references the queue (sub-step 3) and the agent (already created in Steps 9–10, with its ASA flows cloned in Step 11), so both must exist first. The full lifecycle — author (`save`) and activate — is tier 1 headless (see the flow section below for the exact activation path).
39
+ 5. **Embedded service deployment + `MessagingChannel`** [T3] — one per agent; its routing points at the inbound flow (sub-step 4) and fallback queue (sub-step 3), so build both first. The channel and its ESD are created together as **one wizard cascade** (ESD + an internal ESW plumbing site + a `Network` + a branding set) — do not attempt a standalone `POST /sobjects/MessagingChannel`; the wizard doesn't attach an ESD to a pre-existing channel (an API-created one comes out ESD-less and non-functional, and a standalone Tooling `POST /tooling/sobjects/EmbeddedServiceConfig` dead-ends headlessly demanding the wizard-minted `SiteId`), so splitting the two buys nothing.
40
+ - **Setup path:** Setup → Messaging Settings → **New Channel** → **Start** → **Native Channels → Enhanced Chat** → Next.
41
+ - **Name your channel:** set **Channel Name** + **Developer Name**; **Deployment Type = Web**; **Domain** = the org's Experience Cloud Sites domain (Setup → Domains → the row whose *Current Domain Configuration Option* is **Experience Cloud Sites Domain**) → Next.
42
+ - **Channel Routing:** **Routing Type = Omni-Flow**; **Flow Definition** = the inbound flow from sub-step 4; **Fallback Queue** = the queue from sub-step 3 — both are required to Save, so a missing/wrong selection here is a loud failure, not a silent one → **Save**.
43
+ - **WARNING: The channel cannot be torn down afterward — neither API nor UI** (not API-deletable; Setup offers no delete for a channel either). Create deliberately — the only "undo" is leaving it inactive.
44
+ - **Auth/AEA channel only — enable user verification** [T3, in the channel edit screen]: Setup → Messaging Settings → in the **row-level dropdown for your channel select Edit** (do NOT click into the channel and hit Edit there — that only edits the name/API name) → check **Add User Verification** → Save. **Ignore the *Authorization Token Expiration Time* box** — credential-based verification is fixed at 15 minutes (auto-renewing), so that value has no effect. The unauthenticated/Service (ASA) channel gets **no** user verification.
45
+ 6. **Back to the site — confirm it's ready, then finish it** [**T3** — read T1, everything else UI] — one per agent; this is where the sub-step-5 deployment's component actually gets placed, so it's the last thing touched even though creation (sub-step 1) happened first. Do **not** conflate the placement site with the ESD's internal **ESW plumbing site** (sub-step 5): the ESW site is auto-provisioned by the deployment wizard to host the embedded endpoint; the placement site here is the deliberate, customer-facing one from sub-step 1.
46
+ - **Re-check `Network` — T1** (`GET /connect/communities` → 200, or the `Network` query) — confirm the sub-step-1 site(s) reached `Status = Live`. If still provisioning, that's fine — none of sub-steps 2–5 depend on it; just don't publish until it's `Live`.
47
+ - **CRITICAL: Add the Embedded Messaging component and suppress the raw JSON output before publishing [T3, manual, Experience Builder].** By default the agent renders the **raw JSON** its actions return, which is unusable for a prospective student, and the messaging widget isn't on the page until it's placed there:
48
+ 1. **Add the component.** Setup → Digital Experiences → **All Sites** → click **Builder** next to the site's name (not **Workspaces** — that opens a different screen) → Experience Builder opens → the **Components** icon in the left nav → search "embedded" → drag **Embedded Messaging** (under the *Support* category) anywhere onto the page. **WARNING: Don't confuse it with `Embedded Service Chat`**, a similarly-named, similarly-iconed component in the same *Support* category — that's the older live-chat widget, not this deployment's component.
49
+ 2. **Disable streaming responses.** Add this to the site's page `<head>` markup (Experience Builder → Settings → Advanced → Edit Head Markup):
50
+ ```html
51
+ <script>
52
+ window.addEventListener('onEmbeddedMessagingReady', () => {
53
+ embeddedservice_bootstrap.settings.disableStreamingResponses = true;
54
+ });
55
+ </script>
56
+ ```
57
+ 3. **Set the security level to Relaxed CSP.** Setup → Digital Experiences → the site → **Security & Privacy** → Security Level → **Relaxed CSP: Permit Access to Inline Scripts and Allowed Hosts** (the inline `<script>` above won't run under the stricter default CSP).
58
+ 4. **Trust the site's own host for scripts.** Add the site as a trusted site for scripts (Security & Privacy → Trusted URLs / *Allow Hosts of Script Resources*). Get the site URL from Setup → Digital Experiences → **All Sites** → the site's URL in the list view.
59
+ 5. **Auth/AEA site only — activate user verification on the component** [T3, Experience Builder]: highlight the **Embedded Messaging** component → in the property editor check **Add credential-based user verification**. This is the site-side half of the channel's Add-User-Verification checkbox (sub-step 5); both must be set for the authenticated path. Skip on an unauthenticated/Service site.
60
+ 6. **Publish (or re-publish) the site** so the component, head markup, CSP changes, and (auth path) the verification setting all go live.
61
+
62
+ > **Note on ordering:** site *creation* (sub-step 1) is front-loaded because it's the slowest part of this stack; the `MessagingChannel`/ESD it will eventually host (sub-step 5) are built independently in the meantime and only get embedded into the site at sub-step 6. The ESD does bind to its own internal ESW plumbing site, minted by the same deployment wizard — never the sub-step-1/sub-step-6 placement site.
63
+
64
+ ### Inbound routing flow — two shapes
65
+
66
+ `ProcessType` is **`RoutingFlow`** (the Flow Builder UI labels this "Omni-Channel Flow," but the stored process type is `RoutingFlow` — verify on `ProcessType`, not the UI label). Each flow's `{!recordId}` is the `MessagingSession` Id. The whole lifecycle — author (`save`) → activate → verify — is **tier 1 headless**. Do **not** use a template — author the elements directly.
67
+
68
+ **Author — `POST /flowbuilder/flow/actions/save` (`saveType:"createNewFlow"`, `builderType:"FlowBuilder"`), T1 both shapes.** Same tier-1 surface used for the admissions flows — note the `/actions/` segment; the bare `/flowbuilder/flow/save` path 405s `METHOD_NOT_ALLOWED` (GET/HEAD only).
69
+ - **WARNING: Save-contract:** send **only `fullName` + `metadata`** on the flow object. Including top-level `status`/`processType`/`masterLabel`/`label` alongside `metadata` → `400 "Only the Metadata and FullName fields may be specified on Flow…"`. (`validate-flow` is lenient; `save` enforces it.)
70
+ - **WARNING: The `recordId` String input variable is REQUIRED** and may be missing from a UI screenshot — add it explicitly (the Route Work `recordId` input is an `elementReference` to it).
71
+
72
+ **Activate — Tooling `FlowDefinition` PATCH is the reliable path (NOT `/flowbuilder/.../activate`).** Walk this ladder:
73
+ 1. **Primary (the path that returns 204):** query `FlowDefinition` by DeveloperName (`SELECT Id, DeveloperName, ActiveVersionId FROM FlowDefinition WHERE DeveloperName='<apiName>'` → the `300`-prefix def Id), then `PATCH /tooling/sobjects/FlowDefinition/{defId}` `{"Metadata":{"activeVersionNumber":N}}` (N = version, usually 1) → **204**. Deactivate with `activeVersionNumber:0`.
74
+ 2. **Optional native endpoint:** `POST /flowbuilder/flow/{flowId}/actions/activate?builderType=FlowBuilder` — not reliably available (it 404s on some orgs). If preferred, try it first and **fall back to the FlowDefinition PATCH on a 404**. Do **NOT** use `PATCH /tooling/sobjects/Flow/{flowId}` `{Metadata:{status:'Active'}}` — that overwrites the version body and returns `400 INVALID_STATUS` once a version has been active.
75
+ 3. **UI last:** Setup → Flows → activate.
76
+
77
+ Then verify on `FlowDefinitionView` (`SELECT ApiName, IsActive, ActiveVersionId FROM FlowDefinitionView WHERE ApiName='<apiName>'` → `IsActive:true`). If any leg fails, fall back to building/activating the flow in the UI (Setup → Flows → New → *Omni-Channel Flow*).
78
+
79
+ **Route Work element inputs (both flows):** *How Many Work Records* = **Single**; *Record ID Variable* = `{!recordId}`; *Service Channel* = **Messaging**; *Fallback Queue* = the per-agent queue from sub-step 3.
80
+
81
+ **WARNING: The Route Work agent parameter encoding DIFFERS by agent type** — do not reuse the Service-agent field for an Employee agent:
82
+ - **Service / ASA (unauthenticated):** `routingType:"Copilot"`; agent → **`copilotId`** setupReference (the `BotDefinition` DeveloperName) + `copilotLabel`.
83
+ - **Employee / AEA (authenticated):** `routingType:"AgentforceEmployeeAgent"`; agent → **`agentforceEmployeeAgentId`** setupReference (the `BotDefinition` DeveloperName) + `agentforceEmployeeAgentLabel`; **leave `copilotId` empty.**
84
+ - **Both share:** `recordId` input (elementReference to the `recordId` variable); the service channel as **three** inputs — `serviceChannelId` setupReference `sfdc_livemessage` (setupReferenceType `ServiceChannel`) + `serviceChannelDevName` **stringValue** `sfdc_livemessage` + `serviceChannelLabel:"Messaging"`; `queueId` as a plain **stringValue** (the 18-char `00G…` queue Id, NOT a setupReference) + `queueLabel`.
85
+
86
+ - **Service / ASA (unauthenticated) — minimal.** The ASA runs as the Einstein Agent User service account with no end-user to resolve, so route straight through:
87
+ ```text
88
+ Start → Route to ASA Agent (Route Work) → End
89
+ ```
90
+ - **Employee / AEA (authenticated) — user-resolution chain before Route Work.** Resolve the verified end-user to their Contact and stamp it on the Messaging User before routing:
91
+ ```text
92
+ Start
93
+ → Get Messaging Session (Get Records; Messaging Session ID = {!recordId})
94
+ → Get Messaging User (Messaging User ID = {!Get_Messaging_Session.MessagingEndUserId})
95
+ → Get User (User ID = {!Get_Messaging_User.AuthenticatedEndUserId})
96
+ → Update Messaging User (find by Messaging User ID = {!Get_Messaging_Session.MessagingEndUserId};
97
+ set Contact ID = {!Get_User.ContactId})
98
+ → Route to AEA Agent (Route Work)
99
+ → End
100
+ ```
101
+ Element API names (underscore form, matching the platform's own emitted flow): `Get_Messaging_Session`, `Get_Messaging_User`, `Get_User`, `Update_Messaging_User`, `Route_to_AEA_Agent` (ASA uses `Route_to_ASA_Agent`). The `elementReference` expressions above must use these exact names.
102
+
103
+ ## Verify deployment (concrete calls — run after channel setup)
104
+
105
+ `/query` and `/headless/metadata` GET route over `dispatch_readonly` (tier 1) — attempt tier 1 first for each read, falling back to tier 2 (`sf`) or a tier-3 UI check. **For verifying a specific record you just created (known Id), prefer an sObject GET-by-Id (`/sobjects/<Type>/<Id>` over `dispatch_readonly`) over a `/query` filter** — it is the more robust cold-read for a known Id and confirms the persisted field values (including an inline FK like `Group.QueueRoutingConfigId`) directly. Use `/query` for the population/existence sweeps below where no Id is known yet.
106
+
107
+ ```bash
108
+ # Tier 1 first: dispatch_readonly /query with the equivalent SOQL below; fall back to tier 2 (sf).
109
+ # Omni-Channel enabled (headless GET; confirm enableOmniChannel true in the xmlRep).
110
+ # Experience Cloud sites (one per agent, Live):
111
+ sf data query -q "SELECT Id, Name, Status FROM Network" --target-org <alias>
112
+ # Messaging channels (one per agent) — NOTE: no ChannelType column:
113
+ sf data query -q "SELECT Id, MasterLabel, MessageType, MessagingPlatformKey FROM MessagingChannel" --target-org <alias>
114
+ # Per-agent fallback queues (Group), their supported objects (expect MessagingSession + MessagingEndUser), and members:
115
+ sf data query -q "SELECT Id, DeveloperName, Type, QueueRoutingConfigId FROM Group WHERE Type='Queue'" --target-org <alias>
116
+ sf data query -q "SELECT QueueId, SobjectType FROM QueueSobject" --target-org <alias>
117
+ sf data query -q "SELECT GroupId, UserOrGroupId FROM GroupMember WHERE Group.Type='Queue'" --target-org <alias>
118
+ # Per-agent routing configs:
119
+ sf data query -q "SELECT Id, DeveloperName FROM QueueRoutingConfig" --target-org <alias>
120
+ # Inbound routing flows active (query by ApiName; ProcessType RoutingFlow):
121
+ sf data query -q "SELECT ApiName, ProcessType, IsActive FROM FlowDefinitionView WHERE ProcessType='RoutingFlow'" --target-org <alias>
122
+ ```
123
+ Confirm one site, one messaging channel, one queue, one routing config, and one active `RoutingFlow` **per agent**, and the sites are `Live`.
124
+
125
+ ## Step 13 — Final structural verification
126
+
127
+ Run the headless structural roll-up and summarize; **do not wait on any manual action.** This is the last skill-run step — everything here is queryable, so it never blocks on the user.
128
+
129
+ **Structural roll-up (headless, tier 1):** confirm the agent is active, all subagents are present, the ASA flows are active, and the channel + site are up — via `/query` / `/tooling/query` over `dispatch_readonly` (the per-layer verify queries above plus the agent/subagent checks in `agent-and-subagents.md`). Then summarize which tier each step landed on (headless / `sf` CLI / manual UI) and list anything left manual on the T3-only steps.
130
+
131
+ **Conversational smoke test — hand to the user, do NOT verify inline.** Messaging the deployed agent (subagents respond, Learning Program + Knowledge grounding answer, the record-creating actions fire) needs a live channel session that can't be driven headlessly — and polling for records the user hasn't created yet would hang. So **finish the skill on the structural roll-up** and leave the user a short checklist to run themselves once live:
132
+
133
+ - Message each subagent — Admissions and Enrollments FAQ, Admissions Application, Campus Tours, Visits, and Events Registration, Request for Information, and Escalation — and confirm it responds.
134
+ - Ask a program/FAQ question and confirm grounded, cited answers come back.
135
+ - Exercise Create Inquiry / Campus Tour Registration / Admissions Application / Academic Interest, then confirm the records landed (list view / report, or a `SELECT … ORDER BY CreatedDate DESC` query if they have a shell).
136
+
137
+ **Do not create customer data during or after this build** — this skill wires configuration and grounding, not org content. Once the structural roll-up is done, close with this guidance to the customer:
138
+
139
+ - *"The agent is configured and ready to answer questions from what's already in Knowledge and Data Cloud. To keep FAQ answers current, keep adding Knowledge articles — newly published ones are picked up automatically, no re-wire needed."*
140
+ - *"To support Request for Information and Campus Tours, make sure your Recruitment & Admissions data is populated — Learning Programs, Academic Terms, and the Campaigns tied to campus tours/events. Without that data, those subagents have nothing to retrieve or register against."*
141
+ - If the customer then asks Claude to create a specific program, term, or campaign for them, that's outside this skill's scope — say so rather than building it inline here.
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: experience-cms-brand-apply
3
- description: "Extracts, retrieves, and applies CMS brand guidelines (voice, tone, style, colors, typography) to generated content. Use this skill ANY TIME a user request involves branding, brand voice, brand tone, brand guidelines, brand identity, brand styling, or applying a brand to content. Triggers for requests like \"apply my brand\", \"use our brand voice\", \"match our brand guidelines\", \"find my brand\", \"search for brand\", \"get brand instructions\", \"apply brand tone\". Handles the full workflow: searching for brands in Salesforce CMS, extracting brand instructions, and applying brand voice/tone/guidelines to generated content. Does not apply to media/image search (use experience-content-media-search skill), logo search, or creating new brand definitions."
3
+ description: "Extracts, retrieves, and applies CMS brand guidelines (voice, tone, style, colors, typography) to generated content. Use this skill ANY TIME a user request involves branding, brand voice, brand tone, brand guidelines, brand identity, brand styling, or applying a brand to content. Triggers for requests like \"apply my brand\", \"use our brand voice\", \"match our brand guidelines\", \"find my brand\", \"search for brand\", \"get brand instructions\", \"apply brand tone\". Handles the full workflow: searching for brands in Salesforce CMS, extracting brand instructions, and applying brand voice/tone/guidelines to generated content. Does not apply to media/image search (use experience-search-coordinate skill), logo search, or creating new brand definitions."
4
4
  metadata:
5
5
  version: "1.0"
6
6
  domains: ["Experience"]
7
7
  relatedSkills:
8
8
  - "experience-cms-brand-create"
9
- - "experience-content-media-search"
9
+ - "experience-search-coordinate"
10
10
  ---
11
11
 
12
12
  # Applying CMS Brand
@@ -26,7 +26,7 @@ Universal skill for searching, extracting, and applying CMS brand guidelines to
26
26
  - Apply brand styling, tone, or voice to a page, component, or app
27
27
 
28
28
  **DO NOT use this skill when the user wants to:**
29
- - Search for images or media (use experience-content-media-search skill)
29
+ - Search for images or media (use experience-search-coordinate skill)
30
30
  - Create a new brand from scratch (use experience-cms-brand-create skill)
31
31
  - Edit brand definitions in CMS
32
32
  - Generate logos or visual brand assets
@@ -72,9 +72,9 @@ Brands are stored as CMS content of type `sfdc_cms__brand`. Search for them by
72
72
  querying the CMS channels with the brand content type.
73
73
 
74
74
  > **Note:** Brand content search (`contentTypeFqn=sfdc_cms__brand`) is explicitly
75
- > excluded from the `experience-content-media-search` skill's scope. Calling
75
+ > excluded from the `experience-search-coordinate` skill's scope. Calling
76
76
  > `search_media_cms_channels` directly here is correct and intentional — do not
77
- > route brand search through `experience-content-media-search`.
77
+ > route brand search through `experience-search-coordinate`.
78
78
 
79
79
  **Process:**
80
80
 
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: experience-cms-brand-create
3
- description: "Author a Salesforce Digital Experience brand (a \"brand.json\") so the VS Code Brand Toolkit can load, edit, and preview it. Use this skill whenever someone wants to: create a brand, make a new brand, generate a brand from a description or a color/logo/mood, add a brand to a project so the Brand Toolkit picks it up, scaffold a brand.json, theme a Digital Experience site, or turn a brand idea (\"a dark luxury brand\", \"match our logo\", \"coral + rounded + friendly\") into a loadable brand. Also use it when the user mentions \"Brand Toolkit\", \"theme manager brand\", \"brand token\", \"colorScheme\", \"primaryAccent\", \".digitalExperience/brands\", \"sfdc_cms:title\", or a \"brand.json\" that should show up in the Brand Toolkit. Do NOT use this skill to apply an existing brand's voice, tone, or guidelines to generated content (use experience-cms-brand-apply), to search Salesforce CMS for existing brands, or to search for images, media, or logos (use experience-content-media-search)."
3
+ description: "Author a Salesforce Digital Experience brand (a \"brand.json\") so the VS Code Brand Toolkit can load, edit, and preview it. Use this skill whenever someone wants to: create a brand, make a new brand, generate a brand from a description or a color/logo/mood, add a brand to a project so the Brand Toolkit picks it up, scaffold a brand.json, theme a Digital Experience site, or turn a brand idea (\"a dark luxury brand\", \"match our logo\", \"coral + rounded + friendly\") into a loadable brand. Also use it when the user mentions \"Brand Toolkit\", \"theme manager brand\", \"brand token\", \"colorScheme\", \"primaryAccent\", \".digitalExperience/brands\", \"sfdc_cms:title\", or a \"brand.json\" that should show up in the Brand Toolkit. Do NOT use this skill to apply an existing brand's voice, tone, or guidelines to generated content (use experience-cms-brand-apply), to search Salesforce CMS for existing brands, or to search for images, media, or logos (use experience-search-coordinate)."
4
4
  metadata:
5
5
  version: "1.0"
6
6
  domains: ["Experience"]
7
7
  relatedSkills:
8
8
  - "experience-cms-brand-apply"
9
- - "experience-content-media-search"
9
+ - "experience-search-coordinate"
10
10
  ---
11
11
 
12
12
  # Create a Brand for the Brand Toolkit
@@ -7,6 +7,7 @@ metadata:
7
7
  minApiVersion: "64.0"
8
8
  relatedSkills:
9
9
  - "experience-cms-content-type-generate"
10
+ - "experience-cms-content-render"
10
11
  cliTools:
11
12
  - tool: ["sf"]
12
13
  semver: ">=2.0.0"