@salesforce/afv-skills 1.58.0 → 1.59.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.
- package/package.json +1 -1
- package/skills/agentforce-bot-upgrade/SKILL.md +3 -1
- package/skills/agentforce-generate/SKILL.md +21 -1
- package/skills/agentforce-generate/references/known-issues.md +51 -1
- package/skills/agentforce-generate/references/legacy-nga-regression-eval.md +547 -0
- package/skills/agentforce-generate/references/upgrade-legacy-agent-to-agentscript.md +577 -0
- package/skills/agentforce-generate/scripts/upgrade-legacy-nga-analyze.py +404 -0
- package/skills/agentforce-generate/scripts/upgrade-legacy-nga-run-trials.sh +58 -0
- package/skills/agentforce-persona-generate/SKILL.md +505 -0
- package/skills/agentforce-persona-generate/assets/checklist-template.md +100 -0
- package/skills/agentforce-persona-generate/assets/persona-encoding-template.md +252 -0
- package/skills/agentforce-persona-generate/assets/persona-template.md +229 -0
- package/skills/agentforce-persona-generate/assets/sample-dialog-template.md +50 -0
- package/skills/agentforce-persona-generate/assets/workshop-outline-template.md +97 -0
- package/skills/agentforce-persona-generate/examples/concierge-persona.md +189 -0
- package/skills/agentforce-persona-generate/examples/concierge-sample-dialog.md +70 -0
- package/skills/agentforce-persona-generate/examples/drover-persona.md +194 -0
- package/skills/agentforce-persona-generate/examples/drover-sample-dialog.md +62 -0
- package/skills/agentforce-persona-generate/examples/steady-hand-persona.md +188 -0
- package/skills/agentforce-persona-generate/examples/steady-hand-sample-dialog.md +68 -0
- package/skills/agentforce-persona-generate/examples/yt-persona.md +195 -0
- package/skills/agentforce-persona-generate/examples/yt-sample-dialog.md +66 -0
- package/skills/agentforce-persona-generate/references/attributions.md +36 -0
- package/skills/agentforce-persona-generate/references/interaction-design-notes.md +30 -0
- package/skills/agentforce-persona-generate/references/persona-encoding-guide.md +566 -0
- package/skills/agentforce-persona-generate/references/persona-framework.md +796 -0
- package/skills/agentforce-persona-generate/references/refinement-mappings.md +31 -0
- package/skills/agentforce-persona-generate/references/scoring-rubric.md +58 -0
- package/skills/agentforce-persona-generate/references/voice-catalog.json +2327 -0
- package/skills/agentforce-persona-generate/references/workshop-question-policy.md +90 -0
- package/skills/agentforce-persona-generate/references/workshop-scenario-seeds.md +119 -0
- package/skills/agentforce-persona-generate/scripts/parse_agent_yaml.py +223 -0
- package/skills/dx-app-analytics-query/SKILL.md +8 -8
- package/skills/experience-ui-bundle-app-coordinate/SKILL.md +12 -12
- package/skills/experience-ui-bundle-app-coordinate/references/phase-completion-validation.md +3 -3
- package/skills/experience-ui-bundle-app-coordinate/references/phase-execution-pattern.md +9 -7
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-dangling-refs.mjs +132 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-hosting-target.mjs +62 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-1-complete.mjs +71 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-4-complete.mjs +95 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-6-ready.mjs +78 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-prerequisites.mjs +21 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-sfdx-project.mjs +28 -0
- package/skills/experience-ui-bundle-custom-app-generate/SKILL.md +3 -1
- package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.mjs +40 -0
- package/skills/experience-ui-bundle-frontend-generate/SKILL.md +7 -5
- package/skills/experience-ui-bundle-frontend-generate/scripts/check-preconditions.mjs +70 -0
- package/skills/experience-ui-bundle-frontend-generate/scripts/resolve-ui-bundle.mjs +76 -0
- package/skills/experience-ui-bundle-frontend-generate/scripts/verify-rules.mjs +115 -0
- package/skills/experience-ui-bundle-metadata-generate/SKILL.md +7 -3
- package/skills/experience-ui-bundle-metadata-generate/references/angular-metadata-generate.md +1 -1
- package/skills/experience-ui-bundle-metadata-generate/references/react-metadata-generate.md +1 -1
- package/skills/experience-ui-bundle-metadata-generate/scripts/check-api-version.mjs +43 -0
- package/skills/experience-ui-bundle-metadata-generate/scripts/detect-framework.mjs +131 -0
- package/skills/experience-ui-bundle-metadata-generate/scripts/verify-bundle-location.mjs +152 -0
- package/skills/experience-ui-bundle-mfa-configure/references/branding.md +10 -6
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-dangling-refs.sh +0 -42
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-hosting-target.sh +0 -26
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-1-complete.sh +0 -35
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-4-complete.sh +0 -47
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-6-ready.sh +0 -33
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-prerequisites.sh +0 -20
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-sfdx-project.sh +0 -15
- package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.sh +0 -30
- package/skills/experience-ui-bundle-frontend-generate/scripts/check-preconditions.sh +0 -37
- package/skills/experience-ui-bundle-frontend-generate/scripts/resolve-ui-bundle.sh +0 -66
- package/skills/experience-ui-bundle-frontend-generate/scripts/verify-rules.sh +0 -58
- package/skills/experience-ui-bundle-metadata-generate/scripts/check-api-version.sh +0 -30
- package/skills/experience-ui-bundle-metadata-generate/scripts/detect-framework.sh +0 -73
- package/skills/experience-ui-bundle-metadata-generate/scripts/verify-bundle-location.sh +0 -118
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
# Upgrade a Legacy Agent to Agent Script (NGA)
|
|
2
|
+
|
|
3
|
+
Workflow for migrating a legacy Salesforce `GenAiPlannerBundle` agent into a
|
|
4
|
+
Next Gen Authoring (NGA) `AiAuthoringBundle` (Agent Script) bundle.
|
|
5
|
+
|
|
6
|
+
> Steps run in order: **Step 1** project setup → **Step 2** pick the legacy
|
|
7
|
+
> agent version → **Step 3** migrate via the Connect API → **Step 4** retrieve
|
|
8
|
+
> the NGA bundle → **Step 5** analyze, optimize, and iterate.
|
|
9
|
+
|
|
10
|
+
> **Narration:** keep progress lines to one short phrase — _"Gathering
|
|
11
|
+
> migratable versions…"_, _"Running the migration call inside a subagent…"_.
|
|
12
|
+
> Don't explain the rationale (why a subagent, what a screen is) inline; the
|
|
13
|
+
> user wants terse status, not a play-by-play.
|
|
14
|
+
|
|
15
|
+
## Contents
|
|
16
|
+
|
|
17
|
+
- [Kickoff — set expectations, then track progress](#kickoff--set-expectations-then-track-progress)
|
|
18
|
+
- [Step 1 — Project setup and requirements](#step-1--project-setup-and-requirements)
|
|
19
|
+
- [Step 2 — Identify the legacy agent version to upgrade](#step-2--identify-the-legacy-agent-version-to-upgrade)
|
|
20
|
+
- [Step 3 — Migrate the legacy agent with the `migrateAgentToNga` Connect API](#step-3--migrate-the-legacy-agent-with-the-migrateagenttonga-connect-api)
|
|
21
|
+
- [Step 4 — Retrieve the new NGA bundle into the project](#step-4--retrieve-the-new-nga-bundle-into-the-project)
|
|
22
|
+
- [Step 5 — Analyze, optimize, and iterate on the migrated Agent Script](#step-5--analyze-optimize-and-iterate-on-the-migrated-agent-script)
|
|
23
|
+
- [5d — Regression-test the draft against the legacy agent](#5d--regression-test-the-draft-against-the-legacy-agent)
|
|
24
|
+
|
|
25
|
+
## Kickoff — set expectations, then track progress
|
|
26
|
+
|
|
27
|
+
Before touching anything, do two things so the user always knows what's coming
|
|
28
|
+
and where they are. Keep both **brief** — no rationale, no sub-steps.
|
|
29
|
+
|
|
30
|
+
**1. Show a high-level overview once, up front:**
|
|
31
|
+
|
|
32
|
+
> Migrating your legacy agent to Agent Script (NGA). The plan:
|
|
33
|
+
> 1. **Set up** — pick the target org and a local project
|
|
34
|
+
> 2. **Choose** — the legacy agent and the version to migrate
|
|
35
|
+
> 3. **Migrate** — one API call; creates a new NGA bundle in your org
|
|
36
|
+
> 4. **Retrieve** — pull the new agent down locally
|
|
37
|
+
> 5. **Optimize** — review and improve the result together
|
|
38
|
+
>
|
|
39
|
+
> The migration produces a **new NGA version** of your agent. Your original
|
|
40
|
+
> agent versions stay available in the legacy builder — nothing is overwritten
|
|
41
|
+
> or removed, so you can always fall back to them.
|
|
42
|
+
>
|
|
43
|
+
> The migration itself is quick — step 5 is where we make it good.
|
|
44
|
+
|
|
45
|
+
**2. Render this checklist now, and re-render it (compact) after each step** so
|
|
46
|
+
the user can see progress at a glance. Mark completed `[x]`, the active step
|
|
47
|
+
`[>]`, and the rest `[ ]`:
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
- [ ] Step 1 — Project & org setup
|
|
51
|
+
- [ ] Step 2 — Pick legacy agent + version
|
|
52
|
+
- [ ] Step 3 — Migrate (Connect API)
|
|
53
|
+
- [ ] Step 4 — Retrieve NGA bundle
|
|
54
|
+
- [ ] Step 5 — Analyze & optimize
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Re-render only the checklist between steps — don't re-explain finished work. At
|
|
58
|
+
the end of each step below you'll find a **Checklist** cue: advance the marker
|
|
59
|
+
and show the updated list before starting the next step.
|
|
60
|
+
|
|
61
|
+
## Step 1 — Project setup and requirements
|
|
62
|
+
|
|
63
|
+
The workflow needs a local **Salesforce DX project** to hold retrieved
|
|
64
|
+
metadata — the legacy `botVersion-meta.xml` files read in Step 2 and the
|
|
65
|
+
migrated `AiAuthoringBundle` pulled down in Step 4 all land here. Establish this
|
|
66
|
+
once, up front.
|
|
67
|
+
|
|
68
|
+
### Gather requirements
|
|
69
|
+
|
|
70
|
+
Collect two things. **Never assume a default for either — always confirm.**
|
|
71
|
+
|
|
72
|
+
1. **Target org** — the org that holds the legacy agent and will receive the
|
|
73
|
+
migrated bundle (used as `<org-alias>` throughout). **Never silently use the
|
|
74
|
+
default org.** Show the user the current default and the alternatives, then
|
|
75
|
+
**require an explicit confirmation or choice** before proceeding — Step 3 is a
|
|
76
|
+
mutating call, so the wrong org creates a bundle in the wrong place.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
sf config get target-org --json # the current default, if any
|
|
80
|
+
sf org list --json # all authenticated orgs to choose from
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Present the authenticated orgs as a selectable menu** (e.g. an
|
|
84
|
+
`AskUserQuestion` pick-list) — the user should **choose**, never type an
|
|
85
|
+
alias by hand. Mark the current default so it's obvious (e.g.
|
|
86
|
+
`mk-sandbox (default)`) but still require an explicit pick. Use the chosen
|
|
87
|
+
alias as `<org-alias>` everywhere below.
|
|
88
|
+
2. **DX project** — the path to the DX project to work in. If they don't have
|
|
89
|
+
one, offer to create it and ask for a name/location.
|
|
90
|
+
|
|
91
|
+
Once the org is chosen, resolve **its** API version rather than pinning a
|
|
92
|
+
literal (versions bump every release, so a hardcoded number goes stale). Use it
|
|
93
|
+
as `<apiVersion>` in the endpoint paths below:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
sf org display --target-org <org-alias> --json 2>/dev/null \
|
|
97
|
+
| sed -E 's/\x1b\[[0-9;]*m//g' | jq -r '.result.apiVersion' # e.g. 67.0
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
> **Minimum:** `migrateAgentToNga` (Step 3) requires **API v67.0+**. If the org
|
|
101
|
+
> reports lower, it predates the endpoint — stop and surface that.
|
|
102
|
+
|
|
103
|
+
### Use an existing project, or create one
|
|
104
|
+
|
|
105
|
+
A DX project is any directory containing an `sfdx-project.json`. Verify:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
test -f <project-path>/sfdx-project.json && echo "DX project OK" || echo "no project here"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
If none exists, create one and set `sourceApiVersion` to the org's
|
|
112
|
+
`<apiVersion>` resolved above (must be `67.0`+ for the Step 3 endpoint):
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
sf project generate --name <project-name> --output-dir <parent-dir>
|
|
116
|
+
# then, in sfdx-project.json, set "sourceApiVersion": "<apiVersion>"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Resolve the package directory — never assume `force-app`
|
|
120
|
+
|
|
121
|
+
Retrieved metadata lands under the project's **default package directory**. That
|
|
122
|
+
directory is declared in `sfdx-project.json` and is **not always `force-app`** —
|
|
123
|
+
`sf project generate` defaults to it, but existing projects often rename it or
|
|
124
|
+
declare several. Resolve it once from the project and use the result as
|
|
125
|
+
`<package-dir>` in every path below (the `default: true` entry, falling back to
|
|
126
|
+
the first `packageDirectories` entry):
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
jq -r '(.packageDirectories[] | select(.default == true) | .path) // .packageDirectories[0].path' \
|
|
130
|
+
<project-path>/sfdx-project.json # e.g. force-app
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**All subsequent `sf project retrieve start` commands must be run from inside
|
|
134
|
+
this project directory** (`cd <project-path>`), so retrieved metadata is written
|
|
135
|
+
under its `<package-dir>/main/default/` tree — including
|
|
136
|
+
`aiAuthoringBundles/` (the migrated NGA bundle) and `bots/` (the legacy
|
|
137
|
+
`botVersion-meta.xml` files).
|
|
138
|
+
|
|
139
|
+
> **Checklist:** mark Step 1 done, Step 2 `[>]`, and re-render before continuing.
|
|
140
|
+
|
|
141
|
+
## Step 2 — Identify the legacy agent version to upgrade
|
|
142
|
+
|
|
143
|
+
The `migrateAgentToNga` call in Step 3 takes a single input: a classic
|
|
144
|
+
**`BotVersion`** Id (key prefix `0X9`). This step presents a **two-screen
|
|
145
|
+
selection** — first pick the agent, then pick one of its **non-NGA** versions —
|
|
146
|
+
and resolves the choice to that Id.
|
|
147
|
+
|
|
148
|
+
### Concepts
|
|
149
|
+
|
|
150
|
+
An Agentforce agent is backed by classic Bot SObjects, but as an **Agentforce
|
|
151
|
+
copilot**, not an old Einstein Bot:
|
|
152
|
+
|
|
153
|
+
- **`BotDefinition`** (key prefix `0Xx`) — the agent. For Agentforce agents
|
|
154
|
+
`Type` is **`ExternalCopilot`** or **`InternalCopilot`**. **Do not** pick
|
|
155
|
+
`Type = 'Bot'` records — those are old Einstein Bots, not Agentforce agents.
|
|
156
|
+
- **`BotVersion`** (key prefix `0X9`) — one version of that agent, with a
|
|
157
|
+
`VersionNumber` and a `Status` (`Active` / `Inactive`). This is what you
|
|
158
|
+
migrate.
|
|
159
|
+
- Each version is authored by a **planner**, identified in the version's
|
|
160
|
+
`botVersion-meta.xml` as `<genAiPlannerName>`. That planner's
|
|
161
|
+
**`PlannerType`** (queryable on the `GenAiPlannerDefinition` SObject) is the
|
|
162
|
+
authoritative NGA-vs-legacy discriminator (see below).
|
|
163
|
+
|
|
164
|
+
### Distinguishing NGA from legacy (migratable) versions
|
|
165
|
+
|
|
166
|
+
Only **non-NGA** versions can be migrated — an NGA version is already Agent
|
|
167
|
+
Script. Once an NGA agent is published it *also* gets `Bot`/`BotVersion` records,
|
|
168
|
+
so the presence of a `BotVersion` does **not** mean a version is legacy. The
|
|
169
|
+
reliable signal is the planner's `PlannerType`:
|
|
170
|
+
|
|
171
|
+
| `PlannerType` | Meaning |
|
|
172
|
+
|--------------------------------------------|----------------------------|
|
|
173
|
+
| `Atlas__ConcurrentMultiAgentOrchestration` | **NGA** — already Agent Script; exclude |
|
|
174
|
+
| `AiCopilot__ReAct` | Legacy Agentforce (copilot) — migratable |
|
|
175
|
+
| `SentOS__SearchAgent` | Legacy search agent — migratable |
|
|
176
|
+
| _(anything other than `Atlas__…`)_ | Legacy — migratable |
|
|
177
|
+
|
|
178
|
+
> **Do not** rely on `Bot.agentDSLEnabled` (in `bot-meta.xml`). It exists but is
|
|
179
|
+
> **definition-level and stale** — it can read `false` for an agent whose latest
|
|
180
|
+
> version is already NGA. Classify **per version** via `PlannerType`.
|
|
181
|
+
|
|
182
|
+
### Screen 1 — pick the agent
|
|
183
|
+
|
|
184
|
+
List the Agentforce agents (copilot-typed `BotDefinition`) and let the user pick
|
|
185
|
+
one:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
sf data query \
|
|
189
|
+
--query "SELECT DeveloperName, MasterLabel, Type FROM BotDefinition WHERE Type IN ('ExternalCopilot','InternalCopilot') ORDER BY MasterLabel" \
|
|
190
|
+
--target-org <org-alias> \
|
|
191
|
+
--json
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### Silent gate — reject developer names ending in `_<digits>`
|
|
195
|
+
|
|
196
|
+
**As soon as the agent is chosen, silently check its `DeveloperName` against the
|
|
197
|
+
pattern `_\d+$`** (an underscore followed by one or more digits at the end —
|
|
198
|
+
e.g. `Agent_01`, `Order_Agent_007`). Do **not** narrate this check when it
|
|
199
|
+
passes; just continue.
|
|
200
|
+
|
|
201
|
+
If it **matches**, the migration produces a bundle that can't be worked on from
|
|
202
|
+
the terminal (broken version handling) — see
|
|
203
|
+
[known-issues.md](known-issues.md) **Issue 21**. **Stop the migration here.** Do
|
|
204
|
+
not proceed to Screen 2 or the Step 3 call. Tell the user, concisely:
|
|
205
|
+
|
|
206
|
+
- The agent's developer name ends in `_<digits>`, which hits a known migration
|
|
207
|
+
bug (link Issue 21).
|
|
208
|
+
- The fix is to rename the developer name to break up the trailing digits
|
|
209
|
+
(e.g. `Agent_01` → `Agent_v01`), **then** restart this workflow.
|
|
210
|
+
- Renaming has ripple effects — Email Configurations, `package.xml` /
|
|
211
|
+
`AiAuthoringBundle` deploy configs, and any Agent API integrations reference
|
|
212
|
+
the agent by name and must be updated to match. (Point them at Issue 21 for
|
|
213
|
+
the full list.)
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
# silent detection — no output unless it matches
|
|
217
|
+
printf '%s\n' "<agent-name>" | grep -Eq '_[0-9]+$' && echo "BLOCKED: see Issue 21"
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Screen 2 — pick a non-NGA version
|
|
221
|
+
|
|
222
|
+
For the chosen agent, gather its versions and each version's planner type, then
|
|
223
|
+
present **only the non-NGA versions**, ordered by `VersionNumber` **ascending**.
|
|
224
|
+
|
|
225
|
+
1. **Versions + Ids** (ascending) — the `0X9…` Id per version:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
sf data query \
|
|
229
|
+
--query "SELECT Id, VersionNumber, Status FROM BotVersion WHERE BotDefinition.DeveloperName = '<agent-name>' AND BotDefinition.Type IN ('ExternalCopilot','InternalCopilot') ORDER BY VersionNumber ASC" \
|
|
230
|
+
--target-org <org-alias> \
|
|
231
|
+
--json
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
2. **Per-version planner link** — retrieve all versions' metadata at once and
|
|
235
|
+
read `<genAiPlannerName>` from each `vN.botVersion-meta.xml`:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
sf project retrieve start --metadata "BotVersion:<agent-name>.*" --target-org <org-alias> --json
|
|
239
|
+
# each: <package-dir>/main/default/bots/<agent-name>/vN.botVersion-meta.xml
|
|
240
|
+
# → <conversationDefinitionPlanners><genAiPlannerName>…</genAiPlannerName>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
3. **Planner types** — resolve every planner's `PlannerType`:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
sf data query \
|
|
247
|
+
--query "SELECT DeveloperName, PlannerType FROM GenAiPlannerDefinition" \
|
|
248
|
+
--target-org <org-alias> \
|
|
249
|
+
--json
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Join version → `genAiPlannerName` → `PlannerType`, drop any version whose
|
|
253
|
+
`PlannerType` is `Atlas__ConcurrentMultiAgentOrchestration` (NGA), and present
|
|
254
|
+
the rest ascending, e.g.:
|
|
255
|
+
|
|
256
|
+
```text
|
|
257
|
+
Agent: Search_Agent
|
|
258
|
+
v1 Inactive (legacy: SentOS__SearchAgent)
|
|
259
|
+
v6 Inactive (legacy: SentOS__SearchAgent)
|
|
260
|
+
# v2–v5, v7 hidden — already NGA (Atlas)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
The `Id` (`0X9…`) of the version the user picks is the `botVersionId` you pass to
|
|
264
|
+
`migrateAgentToNga` in Step 3.
|
|
265
|
+
|
|
266
|
+
> **Checklist:** mark Step 2 done, Step 3 `[>]`, and re-render before continuing.
|
|
267
|
+
|
|
268
|
+
## Step 3 — Migrate the legacy agent with the `migrateAgentToNga` Connect API
|
|
269
|
+
|
|
270
|
+
Salesforce Core exposes a Connect REST endpoint that converts a classic
|
|
271
|
+
`BotVersion` into an NGA Agent Script bundle:
|
|
272
|
+
|
|
273
|
+
```text
|
|
274
|
+
POST /services/data/v<apiVersion>/connect/migrateAgentToNga # <apiVersion> from Step 1, v67.0+
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Warning: This is a mutating call.** It does not validate/preview — a successful call
|
|
278
|
+
*creates* a new NGA bundle in the org (a real `AiAuthoringBundle`, key prefix
|
|
279
|
+
`1bY`, with a bundle version, key prefix `1bZ`). Confirm the target org and the
|
|
280
|
+
`botVersionId` before running it.
|
|
281
|
+
|
|
282
|
+
### Preferred: call it through the `sf` CLI
|
|
283
|
+
|
|
284
|
+
Invoke the Connect endpoint with `sf api request rest` — no manual token
|
|
285
|
+
handling. **`sf api request rest` has no `--json` flag** (passing it errors with
|
|
286
|
+
`Nonexistent flag: --json`). It streams the raw response *body* to stdout — for
|
|
287
|
+
this endpoint that body is already JSON — and prints a beta-command warning to
|
|
288
|
+
stderr. The body is ANSI-colorized even when piped, so strip the color codes
|
|
289
|
+
before reading or feeding it to `jq`:
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
sf api request rest "/services/data/v<apiVersion>/connect/migrateAgentToNga" \
|
|
293
|
+
--method POST \
|
|
294
|
+
--body '{"botVersionId":"<botVersionId>"}' \
|
|
295
|
+
--target-org <org-alias> \
|
|
296
|
+
2>/dev/null | sed -E 's/\x1b\[[0-9;]*m//g'
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
- `botVersionId` — the classic `BotVersion` Id (`0X9…`) selected in Step 2.
|
|
300
|
+
- The stripped stdout is the full JSON response. Pipe it to `jq` after the `sed`
|
|
301
|
+
strip to pull individual fields.
|
|
302
|
+
|
|
303
|
+
#### Warning: Do the call in a subagent — the response can be huge
|
|
304
|
+
|
|
305
|
+
A newer version of this endpoint returns an **`agentScript`** field containing
|
|
306
|
+
the *entire* generated Agent Script inline. Reading the raw response into the
|
|
307
|
+
main context would bloat it badly. **Make the `migrateAgentToNga` call inside a
|
|
308
|
+
subagent** and have the subagent return only the small fields you need:
|
|
309
|
+
`bundleVersionApiName`, `bundleId`, `bundleVersionId`, `agentVersionFromNumber`,
|
|
310
|
+
`bundleVersionToNumber`, `conversionWarnings`, and `agentResponse`. Never return
|
|
311
|
+
`agentScript` up to the caller; the full script comes down through the Step 4
|
|
312
|
+
retrieve instead.
|
|
313
|
+
|
|
314
|
+
#### Response fields
|
|
315
|
+
|
|
316
|
+
The response shape is expanding. Handle the new fields **if present**, and fall
|
|
317
|
+
back to the older shape when they are absent:
|
|
318
|
+
|
|
319
|
+
| Field | Use |
|
|
320
|
+
|-------|-----|
|
|
321
|
+
| `bundleVersionApiName` | **Preferred.** The metadata `fullName` of the new bundle version — pass **directly** to the Step 4 retrieve, skipping the `bundleVersionId → fullName` lookup. |
|
|
322
|
+
| `bundleVersionId` (`1bZ…`) | Fallback join key when `bundleVersionApiName` is absent (see Step 4). |
|
|
323
|
+
| `bundleId` (`1bY…`) | The bundle (not version) Id. |
|
|
324
|
+
| `conversionWarnings` | List of warnings; review in Step 5. Often non-empty. |
|
|
325
|
+
| `agentResponse` | Notes/fixes from an agent that reviewed the generated script — useful input for Step 5 optimization. |
|
|
326
|
+
| `agentScript` | The full generated script inline — **do not** surface it; retrieve the bundle in Step 4 instead. |
|
|
327
|
+
| `agentVersionFromNumber` (Integer) | The legacy agent version that was migrated **from**. Use in the success message below. |
|
|
328
|
+
| `bundleVersionToNumber` (Integer) | The NGA bundle version that was created **to**. Use in the success message below. |
|
|
329
|
+
|
|
330
|
+
#### Report the result — always present the builder link
|
|
331
|
+
|
|
332
|
+
**On any successful migration, present the builder deep link so the user can
|
|
333
|
+
open the new agent immediately.** The link needs only `bundleId` and
|
|
334
|
+
`bundleVersionId`, which are present in **both** the old and new response shapes
|
|
335
|
+
— so the link is unconditional, never gated on the newer fields.
|
|
336
|
+
|
|
337
|
+
Confirm in one line, then hand over the link:
|
|
338
|
+
|
|
339
|
+
```text
|
|
340
|
+
Migrated <agent> to a new NGA agent. Open it in the builder: <builderUrl>
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
When the newer fields (`agentVersionFromNumber`, `bundleVersionToNumber`) are
|
|
344
|
+
present, use the more specific wording; otherwise fall back to the generic line
|
|
345
|
+
above:
|
|
346
|
+
|
|
347
|
+
```text
|
|
348
|
+
Legacy <agent> version <agentVersionFromNumber> has been migrated to NGA version <bundleVersionToNumber>.
|
|
349
|
+
Open in the builder: <builderUrl>
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
The builder URL is the org's Lightning host + the agent-authoring app, with the
|
|
353
|
+
**bundle** as the `project` and the **bundle version** as the `projectVersion`
|
|
354
|
+
(`project == bundle`):
|
|
355
|
+
|
|
356
|
+
```text
|
|
357
|
+
https://<lightning-host>/AgentAuthoring/agentAuthoringBuilder.app#/project?projectId=<bundleId>&projectVersionId=<bundleVersionId>
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
- `projectId` = `bundleId` (`1bY…`); `projectVersionId` = `bundleVersionId` (`1bZ…`) — both from the Step 3 response.
|
|
361
|
+
- Derive `<lightning-host>` from the chosen org, don't hardcode it:
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
sf org display --target-org <org-alias> --json 2>/dev/null \
|
|
365
|
+
| sed -E 's/\x1b\[[0-9;]*m//g' | jq -r '.result.instanceUrl'
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
Use that host as-is; if it's a `*.my.salesforce.com` domain it redirects to the
|
|
369
|
+
matching `*.lightning.force.com` builder.
|
|
370
|
+
|
|
371
|
+
> **Always call through `sf api request rest`.** It keeps authentication
|
|
372
|
+
> internal to the CLI. **Do not** hand-roll a `curl` call that extracts the org
|
|
373
|
+
> access token (e.g. `jq -r '.result.accessToken'`) — pulling a session token
|
|
374
|
+
> into a shell variable is prohibited in agent-executed workflows because it can
|
|
375
|
+
> surface in the transcript, context, or traces, even when it is never echoed.
|
|
376
|
+
|
|
377
|
+
#### Response shapes
|
|
378
|
+
|
|
379
|
+
A successful migration returns **HTTP 201**. The **current** shape (older
|
|
380
|
+
endpoint) looks like:
|
|
381
|
+
|
|
382
|
+
```json
|
|
383
|
+
{
|
|
384
|
+
"bundleId": "1bYak000000LoRdEAK",
|
|
385
|
+
"bundleVersionId": "1bZak000000dXCDEA2",
|
|
386
|
+
"conversionWarnings": [
|
|
387
|
+
"WARNING: Subagent TestSubAgent007 could not be resolved from standard subagents or has no actions. Is this expected?"
|
|
388
|
+
]
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
The **newer** shape adds `bundleVersionApiName`, `agentScript`, `agentResponse`,
|
|
393
|
+
and version-number fields:
|
|
394
|
+
|
|
395
|
+
```json
|
|
396
|
+
{
|
|
397
|
+
"bundleId": "1bYak000000LoRdEAK",
|
|
398
|
+
"bundleVersionId": "1bZak000000dXCDEA2",
|
|
399
|
+
"bundleVersionApiName": "Agentforce_Service_Agent_4",
|
|
400
|
+
"conversionWarnings": ["WARNING: …"],
|
|
401
|
+
"agentScript": "system:\n instructions:| … (full script — do not surface)",
|
|
402
|
+
"agentResponse": "Reviewed the generated script; adjusted …",
|
|
403
|
+
"bundleVersionToNumber": 4,
|
|
404
|
+
"agentVersionFromNumber": 1
|
|
405
|
+
}
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
`conversionWarnings` is often non-empty. Common entries flag subagents that
|
|
409
|
+
resolved to no actions during conversion (e.g. `Escalation`, custom test
|
|
410
|
+
subagents) — review them in Step 5 when refining the migrated script; they do
|
|
411
|
+
**not** fail the migration.
|
|
412
|
+
|
|
413
|
+
> **Checklist:** mark Step 3 done, Step 4 `[>]`, and re-render before continuing.
|
|
414
|
+
|
|
415
|
+
## Step 4 — Retrieve the new NGA bundle into the project
|
|
416
|
+
|
|
417
|
+
Pull the freshly-created `AiAuthoringBundle` into the DX project from Step 1 so
|
|
418
|
+
it can be reviewed and refined locally. Retrieval is by metadata **fullName**.
|
|
419
|
+
|
|
420
|
+
### Get the retrievable fullName
|
|
421
|
+
|
|
422
|
+
**Preferred (newer endpoint):** Step 3's response already includes
|
|
423
|
+
**`bundleVersionApiName`** — that *is* the metadata `fullName`. Use it directly
|
|
424
|
+
and **skip the lookup below**.
|
|
425
|
+
|
|
426
|
+
**Fallback (older endpoint, no `bundleVersionApiName`):** map the
|
|
427
|
+
`bundleVersionId` to a `fullName`. `sf org list metadata` reports each
|
|
428
|
+
`AiAuthoringBundle`'s `id`, and that `id` equals the **`bundleVersionId`**
|
|
429
|
+
(`1bZ…`) from Step 3 — **not** the `bundleId` (`1bY…`). Match on it:
|
|
430
|
+
|
|
431
|
+
```bash
|
|
432
|
+
sf org list metadata --metadata-type AiAuthoringBundle --target-org <org-alias> --json \
|
|
433
|
+
2>/dev/null | sed -E 's/\x1b\[[0-9;]*m//g' \
|
|
434
|
+
| jq -r --arg id "<bundleVersionId>" '.result[] | select(.id == $id) | .fullName'
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
Either path yields a versioned name like `Agentforce_Service_Agent_4`.
|
|
438
|
+
|
|
439
|
+
### Retrieve into the project
|
|
440
|
+
|
|
441
|
+
Run from **inside the Step 1 project directory** so the bundle lands under
|
|
442
|
+
`<package-dir>/main/default/aiAuthoringBundles/` (the `<package-dir>` resolved in
|
|
443
|
+
Step 1):
|
|
444
|
+
|
|
445
|
+
```bash
|
|
446
|
+
cd <project-path>
|
|
447
|
+
sf project retrieve start --metadata "AiAuthoringBundle:<fullName>" --target-org <org-alias>
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
> **Note on the on-disk name.** You pass the *versioned* `fullName` (e.g.
|
|
451
|
+
> `Agentforce_Service_Agent_4`), but the retrieve normalizes the local folder to
|
|
452
|
+
> the bundle's **`developer_name`** (its base name, e.g.
|
|
453
|
+
> `Agentforce_Service_Agent`). The result is:
|
|
454
|
+
>
|
|
455
|
+
> ```text
|
|
456
|
+
> <package-dir>/main/default/aiAuthoringBundles/<developer_name>/
|
|
457
|
+
> <developer_name>.agent # the Agent Script (YAML)
|
|
458
|
+
> <developer_name>.bundle-meta.xml # <bundleType>AGENT</bundleType>
|
|
459
|
+
> ```
|
|
460
|
+
|
|
461
|
+
The `.agent` file is the migrated Agent Script — `system:` instructions,
|
|
462
|
+
`config:`, `variables:`, subagents, and actions — ready for review in Step 5.
|
|
463
|
+
|
|
464
|
+
> **Checklist:** mark Step 4 done, Step 5 `[>]`, and re-render before continuing.
|
|
465
|
+
|
|
466
|
+
## Step 5 — Analyze, optimize, and iterate on the migrated Agent Script
|
|
467
|
+
|
|
468
|
+
`migrateAgentToNga` produces a **basic, mechanical transformation** of the
|
|
469
|
+
legacy agent metadata into Agent Script. It maps the old subagents/actions across
|
|
470
|
+
but does **not** leverage any of the primitives that make Agent Script powerful —
|
|
471
|
+
deterministic flow control, wired data flow, proper reference syntax, structured
|
|
472
|
+
escalation, etc. The migrated `.agent` is a *starting point*, not a finished
|
|
473
|
+
agent. This step hands off to the existing capabilities of the
|
|
474
|
+
**`agentforce-generate`** skill to understand it, then improve it.
|
|
475
|
+
|
|
476
|
+
Work against the retrieved bundle from Step 4
|
|
477
|
+
(`<package-dir>/main/default/aiAuthoringBundles/<developer_name>/<developer_name>.agent`).
|
|
478
|
+
Available inputs to inform the work:
|
|
479
|
+
|
|
480
|
+
- The retrieved `.agent` file (Step 4) — the migrated script itself.
|
|
481
|
+
- Step 3 `conversionWarnings` — unresolved subagents / actions to address.
|
|
482
|
+
- Step 3 `agentResponse` (newer endpoint only) — fixes/comments from an agent
|
|
483
|
+
that already reviewed the generated script; a useful starting checklist.
|
|
484
|
+
|
|
485
|
+
### 5a — Understand what was produced
|
|
486
|
+
|
|
487
|
+
Route into the skill's **"Comprehend an Existing Agent"** task domain (see
|
|
488
|
+
[SKILL.md](../SKILL.md)). It reverse-engineers an Agent Spec, produces a Subagent
|
|
489
|
+
Map diagram, and flags anti-patterns — establishing what the mechanical
|
|
490
|
+
conversion actually built before you change it. Core references:
|
|
491
|
+
[Core Language](agent-script-core-language.md),
|
|
492
|
+
[Subagent Map Diagrams](agent-subagent-map-diagrams.md).
|
|
493
|
+
|
|
494
|
+
### 5b — Optimize to leverage Agent Script primitives
|
|
495
|
+
|
|
496
|
+
Route into the skill's **"Optimize an Agent"** task domain (see
|
|
497
|
+
[SKILL.md](../SKILL.md)) — this is the heart of turning a mechanical conversion
|
|
498
|
+
into a real Agent Script agent. It scans every subagent and applies:
|
|
499
|
+
|
|
500
|
+
- **Pattern 1 — Wire action outputs to deterministic consumers**
|
|
501
|
+
([Data Flow](optimization-pattern-1-data-flow.md)).
|
|
502
|
+
- **Pattern 2 — Extract requirement-backed deterministic logic**
|
|
503
|
+
([Deterministic Logic](optimization-pattern-2-deterministic-logic.md)) — the
|
|
504
|
+
biggest lever on migrated agents, which encode all logic as model judgment.
|
|
505
|
+
In particular, **any consequential or state-changing action** (order/status
|
|
506
|
+
updates, writes, refunds, cancellations) must be **structurally gated** with
|
|
507
|
+
`available when @variables.<trusted_state>` over verified state — do not leave
|
|
508
|
+
the guard as a prose instruction like "only update for a verified customer,"
|
|
509
|
+
which the model can ignore. For example, gate an `UpdateOrderStatus` alias with
|
|
510
|
+
`available when @variables.verified` rather than trusting reasoning text.
|
|
511
|
+
- **Pattern 3 — Fix variable/action reference syntax**
|
|
512
|
+
([Reference Syntax](optimization-pattern-3-reference-syntax.md)) —
|
|
513
|
+
`{!@variables.X}` / `{!@actions.X}` instead of bare references.
|
|
514
|
+
- **Pattern 4 — Repair promised human handoff**
|
|
515
|
+
([Escalation](optimization-pattern-4-escalation.md)) — resolves the
|
|
516
|
+
unresolved-`Escalation`-subagent warnings commonly seen in `conversionWarnings`.
|
|
517
|
+
- **Pattern 5 — Voice-readiness** ([Voice Modality](voice-modality-reference.md))
|
|
518
|
+
if the agent has a `modality voice:` block.
|
|
519
|
+
|
|
520
|
+
The domain presents an `## Optimization Report`, **stops for explicit approval**,
|
|
521
|
+
then applies approved edits. For deeper judgment on what "good" looks like, see
|
|
522
|
+
[Zen of AgentScript](zen-of-agentscript.md),
|
|
523
|
+
[Posture & Determinism](posture-and-determinism.md), and the
|
|
524
|
+
[Scoring Rubric](scoring-rubric.md).
|
|
525
|
+
|
|
526
|
+
### 5c — Validate, preview, and iterate
|
|
527
|
+
|
|
528
|
+
After edits, validate and confirm behavior — then loop 5b/5c until satisfied:
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
sf agent validate authoring-bundle --json --api-name <developer_name>
|
|
532
|
+
sf agent preview start --json --use-live-actions --authoring-bundle <developer_name>
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
See [Validation & Debugging](agent-validation-and-debugging.md) for the
|
|
536
|
+
preview/trace loop and [Safety Review](safety-review-reference.md) for the
|
|
537
|
+
7-category safety pass. When the agent is ready to release, continue into the
|
|
538
|
+
skill's **"Deploy, Publish, and Activate"** task domain.
|
|
539
|
+
|
|
540
|
+
### 5d — Regression-test the draft against the legacy agent
|
|
541
|
+
|
|
542
|
+
For higher assurance — especially before release, or when 5b changed routing or
|
|
543
|
+
actions — run a **side-by-side regression eval** that previews the migrated NGA
|
|
544
|
+
draft and the legacy agent against a fixed utterance suite and compares them.
|
|
545
|
+
This confirms the draft routes to the same subagents, calls the same actions, and
|
|
546
|
+
returns equivalent (ideally improved) responses. Full mechanism, scripts, and the
|
|
547
|
+
utterance-suite format are in
|
|
548
|
+
[legacy-nga-regression-eval.md](legacy-nga-regression-eval.md).
|
|
549
|
+
|
|
550
|
+
**When to run:** after the draft compiles and previews cleanly (5c), when you want
|
|
551
|
+
objective evidence that the migration preserved behavior — not on every tiny edit.
|
|
552
|
+
It requires the legacy agent to still have an **Active** `BotVersion` and `sf` CLI
|
|
553
|
+
**≥ 2.149.9**.
|
|
554
|
+
|
|
555
|
+
Two bundled scripts do the mechanical work:
|
|
556
|
+
|
|
557
|
+
- `scripts/upgrade-legacy-nga-run-trials.sh` — collects fresh-session preview
|
|
558
|
+
trials for a subject (`legacy` | `draft`) × utterance (agent/org from
|
|
559
|
+
`EVAL_AGENT` / `EVAL_ORG`).
|
|
560
|
+
- `scripts/upgrade-legacy-nga-analyze.py` — reads the local plan traces and emits
|
|
561
|
+
the comparison report (mechanical Rubric #1 + verbatim responses + an LLM-judge
|
|
562
|
+
prompt for Rubric #2).
|
|
563
|
+
|
|
564
|
+
> **Safety.** Live utterances that fire real side effects (escalation, customer
|
|
565
|
+
> email, lead capture) must be tagged and default to **simulated** mode or
|
|
566
|
+
> explicit per-utterance confirmation — never run repeatedly in live mode without
|
|
567
|
+
> opt-in. Draft-only otherwise: **no publish/activate/deploy** without explicit
|
|
568
|
+
> human approval.
|
|
569
|
+
|
|
570
|
+
**Stop condition:** every utterance's oracle-triangle verdict is `PASS` or
|
|
571
|
+
`PASS + LEGACY-DEFECT` (no open `DRAFT-REGRESSION`; any `SPEC-REVIEW` /
|
|
572
|
+
`ADJUDICATE` resolved), drift is `none` against a deliberately-approved baseline,
|
|
573
|
+
and the Rubric #2 judgment is `EQUIVALENT` / `IMPROVED` (no open `REGRESSION`). A
|
|
574
|
+
`LEGACY-DEFECT` is a **pass** — don't chase legacy parity when legacy was wrong.
|
|
575
|
+
|
|
576
|
+
> **Checklist:** mark Step 5 done — all five steps complete. Confirm the
|
|
577
|
+
> migration is finished and point the user at the optimized bundle.
|