@forcedotcom/service-itsm-agentic-setup-employee-agent-configure
@forcedotcom/service-itsm-agentic-setup-employee-agent-configure — AI coding skill
| name | service-itsm-agentic-setup-employee-agent-configure |
| description | Create and activate an IT Service Employee agent as a Next-Gen Authoring (NGA) native agent from an ITSM Employee agent template's Agent Script, via the Salesforce CLI (sf): read the template, check idempotency, create the NGA bundle then publish and activate, verify live. Defaults to the broad IT Service Employee template; when the user names a specialized Employee template (Password Manager Assistance, Certificate Management, Onboarding, Hardware Request, and ~47 others catalogued in references/specialized-templates.md — all under the `svc_emp_intelligence__` namespace), pins that one instead. Idempotent per developer name. TRIGGER when the user asks to create/set up/provision/activate the Employee agent, the IT Service Employee agent, or a specialized Employee agent (password manager, certificate, onboarding, hardware request, etc.). DO NOT TRIGGER: prerequisite checks (service-itsm-agentic-setup-agentforce-studio-validate), CMDB CRUD, Fulfiller setup (service-itsm-agentic-setup-fulfiller-agent-configure). |
| metadata | service-itsm-agentic-setup-agent-runtime-access-assign, service-itsm-agentic-setup-agentforce-studio-configure, service-itsm-agentic-setup-agentforce-studio-validate, service-itsm-agentic-setup-fulfiller-agent-configure |
| allowed-tools | | |
Create an IT Service Employee Agent (broad or specialized)
Create and activate an IT Service Employee Agent as a Next-Gen Authoring (NGA) native agent — Agent-Script-based (AiAuthoringBundleDefVer/bundle), appearing natively in Agentforce Studio's Agents list with no external-link icon — entirely through the Salesforce CLI (sf). This skill does not call the legacy /connect/service-itsm/createAgent; instead it reuses a shipped ITSM Employee template's agentScript field and feeds it into the NGA bundle pipeline: POST /nextgen-authoring/bundles → POST /nextgen-authoring/bundle-versions/{id}/publish → POST /nextgen-authoring/bundle-versions/{id}/activate. Commands: sf api request rest for Connect API GET/POST; sf data query for the SOQL idempotency + verify reads.
GET /connect/service-itsm/agent-templates?agentType=AgentforceEmployeeAgent returns the broad IT Service Employee template plus ~47 specialized Employee templates under the svc_emp_intelligence__ namespace as siblings in data[]. Every specialized template ships the same agentScript shape with the same config.developer_name/config.agent_label substitution points, so the same NGA sequence works for any of them — only the masterLabel that Phases 1 and 4 pin against changes. Full catalog + namespace filter + disambiguation rules live in references/specialized-templates.md.
Helper scripts (invoked via Bash) hold every JSON-parsing / decision rule so the model never eyeballs a response body (A9): classify-preflight.mjs, classify-agent-existence.mjs, build-create-body.mjs (HTML-decodes + substitutes the template's agentScript and writes the body to a JSON file so large content and free-text quotes never hit an inline shell string), render-report.mjs (deterministic report renderer).
Template selection (before Phase 1). Resolve the <masterLabel> this run pins: (1) no specialization named ⇒ pin IT Service Employee (id svc_emp_intelligence__ItEmployeeAssistance) — the backwards-compatible default; (2) user names a specialization ⇒ keyword-match against references/specialized-templates.md, single unambiguous match ⇒ pin that masterLabel and derive developerName from id after __ (snake-cased); ambiguous ⇒ AskUserQuestion keyed on id; (3) filter data[] to svc_emp_intelligence__ only — svc_itsm_intelligence__* (Fulfiller) redirects to service-itsm-agentic-setup-fulfiller-agent-configure, other namespaces are out of scope. The resolved <masterLabel> is the single knob passed to classify-preflight.mjs (Phase 1) and build-create-body.mjs (Phase 4).
Prerequisites. Creation assumes the org-level Agentforce for IT Service prerequisites are already satisfied (Agentforce Studio access + service-cloud-requestor-agent + service-cloud-it-service-employee-agent). If Phase 1 detects Studio is not accessible — or if any write returns 403 FUNCTIONALITY_NOT_ENABLED — this skill offers to delegate to service-itsm-agentic-setup-agentforce-studio-validate (employee path) then resume; on "no", stops. This skill never enables features itself — enablement is a Setup-UI/admin action.
Scope
- In scope: Reading
agent-templates; extracting an Employee template's Agent Script (broad default or a user-named specialization fromreferences/specialized-templates.md— all undersvc_emp_intelligence__); creating the Employee agent as an NGA-native agent viacreateBundleWithVersion→publish→activate; SOQL-verifying live; idempotent skip on duplicate developer name — all viasf. - Out of scope: The Fulfiller agent (
service-itsm-agentic-setup-fulfiller-agent-configure); enabling org-level feature toggles (validated byservice-itsm-agentic-setup-agentforce-studio-validate); low-level topic/action authoring; perm-set assignment; content-bundle deployment; CMDB CRUD; Discovery / Service Graph; the legacycreateAgentroute; anydata[]entry outsidesvc_emp_intelligence__.
Preconditions
If any of these are unmet, sf surfaces an auth error or a 401/403/404; surface the raw error verbatim and stop — do not fabricate state.
sfCLI authenticated to the target org (sf org display -o <alias>shows Connected). All calls use--target-org <alias>; never extract the access token by hand.- API v67.0+ — pinned in the URL path; do not hand-edit below the minimum.
- ITSM features + templates provisioned — resolved template must be present. If
agent-templatesreturns nothing or the routes 404, runservice-itsm-agentic-setup-agentforce-studio-validate(agent pathemployee). node≥ 18 on PATH.
Operations at a glance
| Concern | Command | Notes |
|---|---|---|
| Studio access (precondition read) | sf api request rest "/services/data/v67.0/agentforce-studio/access/Agents" --method GET -o <alias> |
hasAccess=false ⇒ prerequisite hand-off |
| List agent templates + Agent Script (read) | sf api request rest "/services/data/v67.0/connect/service-itsm/agent-templates?agentType=AgentforceEmployeeAgent" --method GET -o <alias> |
agentType=AgentforceEmployeeAgent required; confirms resolved <masterLabel> template + non-empty agentScript |
| Enumerate existing agent + latest version status (read) | sf data query -q "SELECT Id,DeveloperName,MasterLabel,AgentTemplate,(SELECT Id,Status FROM BotVersions ORDER BY VersionNumber DESC LIMIT 1) FROM BotDefinition WHERE Id='<botDefinitionId>' OR AgentTemplate='<agentTemplate>' OR DeveloperName='<developerName>'" -o <alias> --json |
Keyed PRIMARILY on the template's botDefinitionId (Phase-1 row); OR AgentTemplate= is the first fallback that catches the pre-provisioned broad IT_Service_Employee agent by its OOTB namespaced source template (svc_emp_intelligence__ItEmployeeAssistance = Phase-1 template.id) regardless of the collected DeveloperName guess; OR DeveloperName= is the last fallback for self-created agents (null AgentTemplate) and the guard for a dangling Id link (deleted target). Classified by scripts/classify-agent-existence.mjs; Active latest ⇒ ALREADY-CREATED; Inactive latest ⇒ offer reactivation |
| Create the NGA bundle (write) | sf api request rest "/services/data/v67.0/nextgen-authoring/bundles" --method POST --body @<body-file> -o <alias> |
Body built by scripts/build-create-body.mjs; response id = the bundle version Id |
| Publish the bundle version (write) | sf api request rest "/services/data/v67.0/nextgen-authoring/bundle-versions/<bundleVersionId>/publish" --method POST --body '{}' -o <alias> |
Returns publishedBotId/publishedBotVersionId — creates the underlying BotDefinition/BotVersion |
| Activate the bundle version (write) | sf api request rest "/services/data/v67.0/nextgen-authoring/bundle-versions/<bundleVersionId>/activate" --method POST --body '{}' -o <alias> |
Empty response on success; agent is now live and NGA-native |
| Activate an existing inactive version (write) | sf api request rest "/services/data/v67.0/connect/bot-versions/<latestVersionId>/activation" --method POST --body '{"status":"Active"}' -o <alias> |
Reactivation path only (Phase 2b) — skips create/publish |
| Verify agent is live (read) | sf data query -q "SELECT ... FROM BotDefinition WHERE Id='<verifyId>'" -o <alias> --json |
<verifyId> = create path's publishedBotId (Phase-5) or the Phase-2 classifier's returned live matched Id (its botDefinitionId/agentId) on ALREADY-CREATED / reactivation — not the null Phase-1 template botDefinitionId, never the collected developerName; confirm BotDefinition present + latest version Active |
Full command shapes and the ITSM Connect API reference live in references/cli-invocation.md; the reactivation-path call + idempotency verdict table live in references/reactivation.md; the response-body error codes and recurring gotchas live in references/error-taxonomy.md.
Never extract the access token. Use
sf api request rest/sf data querydirectly — they use the CLI's stored session for the target org. Do not pull theaccessTokenout ofsf org displayand hand-build an HTTP request with it; that bypasses the CLI session and leaks a bearer token into shell context.
--jsonrule.sf data querytakes--json(results come back in a.result.records[]envelope — that's what the classifier expects).sf api request restdoes not — omit--jsonthere; its raw stdout body is already JSON.
Clarifying Questions
Collect from the user (ask only what is not already in conversation context):
| Field | Default |
|---|---|
| Target org | Default org (sf config get target-org) |
Template (masterLabel) |
IT Service Employee (broad umbrella, id svc_emp_intelligence__ItEmployeeAssistance). If the user hints at a specialization (password manager, certificate, onboarding, hardware request, etc.), resolve via references/specialized-templates.md; ambiguous ⇒ AskUserQuestion keyed on id |
| Developer name | Broad: IT_Service_Employee_Agent. Specialized: substring after __ in the picked id, snake-cased (e.g. PasswordManagerAssistance → Password_Manager_Assistance) |
| Label | Broad: IT Service Employee Agent. Specialized: the picked template's masterLabel verbatim (e.g. Password Manager Assistance) |
| Confirm the write | REQUIRED — present resolved template + developerName + label, then require "yes" via AskUserQuestion |
The collected <masterLabel>, <developerName>, <label> are threaded through every call — <masterLabel> selects the row in agent-templates.data[] (which also carries the botDefinitionId idempotency key); <developerName>/<label> are used in the createBundleWithVersion body (both outer apiName/label AND the substituted internal config.developer_name/config.agent_label). The idempotency + verify reads key PRIMARILY on the template's botDefinitionId (or, after a fresh create, the publish response's publishedBotId) and fall back to the BotDefinition's AgentTemplate (the OOTB source template = Phase-1 template.id), then to the collected <developerName>, when that is null. A hardcode/collect mismatch on the create body diverges the bundle's outer identity from the script's internal identity.
Idempotency: keyed PRIMARILY on the template's botDefinitionId (Phase-1 agent-templates row — the platform's authoritative template→BotDefinition link), FALLING BACK first to the BotDefinition's AgentTemplate (the OOTB namespaced source template = Phase-1 template.id) and then to the collected <developerName>. The Phase-2 read is BotDefinition WHERE Id='<botDefinitionId>' OR AgentTemplate='<agentTemplate>' OR DeveloperName='<developerName>' (the OR AgentTemplate= half catches the broad pre-provisioned agent by its platform-stamped source template regardless of what DeveloperName it carries; the OR DeveloperName= half is both the last fallback for self-created agents — whose AgentTemplate is null — AND the guard for a dangling Id link whose target BotDefinition was deleted), + latest BotVersion.Status. Outcomes: no match on any key ⇒ create; Active ⇒ ALREADY-CREATED (skip write); Inactive ⇒ Phase-2b reactivation offer. Why the fallback keys: the broad agent ships pre-provisioned as IT_Service_Employee ≠ the guess IT_Service_Employee_Agent (a null-botDefinitionId template row too), so neither the primary key nor the developerName guess catches it — its AgentTemplate (svc_emp_intelligence__ItEmployeeAssistance) is the reliable, rename-immune key that matches it; and for an agent this skill creates (which back-fills neither botDefinitionId nor AgentTemplate), the developerName fallback is what catches a repeat run. The server does reject a duplicate DeveloperName at publish (unique-constraint → bundle cleanup), but only this read turns a repeat into a graceful skip instead of a DUPLICATE_VALUE.
Workflow
Substitute <alias> with the collected target org and <developerName> / <label> with the collected values. Full command shapes + per-phase verdict-branch handling live in references/workflow-detail.md — the phase summary below names each step and its load-bearing rule; the reference file holds the exact sf / node invocations to copy.
- Phase 0 — Establish
${SCRATCH_DIR}. Before any phase writes a transient JSON file, invoke the deterministic helper (path is skill-root-qualified so it resolves regardless of the shell's CWD):SCRATCH_DIR="$(node "<skill_dir>/scripts/create-scratch-dir.mjs" "${outputDir:-}")". The helper picks the base dir (${TMPDIR}, else/tmp, else the harness${outputDir}last-resort — scratch stays OUT of the scored${outputDir}tree) and emits the created dir's absolute path on stdout. Every subsequent phase writes its transient JSON under${SCRATCH_DIR}; the durable${outputDir}/report.mdstays under the harness dir. - Phase 1 — Preflight. Capture the Studio-access read into
${SCRATCH_DIR}/studio-access.jsonand theagent-templatesread (with the requiredagentType=AgentforceEmployeeAgentquery param) into${SCRATCH_DIR}/agent-templates.json, then classify by passing both file paths, then the label (that arg order):node "<skill_dir>/scripts/classify-preflight.mjs" ${SCRATCH_DIR}/studio-access.json ${SCRATCH_DIR}/agent-templates.json "<masterLabel>"— pass the resolved<masterLabel>("IT Service Employee"for the broad path or the picked specialization'smasterLabel). The classifier emitstemplate.botDefinitionId,template.id, andtemplate.masterLabelfrom the matched row — capture all three;botDefinitionIdis the primary Phase-2 idempotency key,template.id(the BotDefinition'sAgentTemplate) the first fallback, and<developerName>the last fallback;masterLabelis the report's display label, not a key. Branch onverdict:READY⇒ Phase 2;NOT-READY⇒ prerequisite hand-off viaAskUserQuestion(delegate toservice-itsm-agentic-setup-agentforce-studio-validateemployee path on "yes");ERROR⇒ surface + stop;studio.signal="CANNOT-CONFIRM"(confirmed 404) does not block. - Phase 2 — Idempotency (primary key
botDefinitionId, fallbacksAgentTemplatethen<developerName>). Taketemplate.botDefinitionIdandtemplate.idfrom Phase 1. PresentbotDefinitionId⇒ SOQLBotDefinition WHERE Id='<botDefinitionId>' OR AgentTemplate='<agentTemplate>' OR DeveloperName='<developerName>'(+BotVersionssubquery — required, elseneedsActivationis permanently false; theORclauses make a dangling Id link — deleted target — fall back to the live agent instead of a falseexists:false→ duplicate create). Empty/nullbotDefinitionId⇒ do NOT skip to create; readWHERE AgentTemplate='<agentTemplate>' OR DeveloperName='<developerName>'(the broad pre-provisioned agent is recovered by its OOTB source template even when its DeveloperName differs from the guess; a self-created agent carries a nullAgentTemplate, soDeveloperNameis its guard).<agentTemplate>is Phase-1template.id. Either way classify vianode "<skill_dir>/scripts/classify-agent-existence.mjs" ${SCRATCH_DIR}/bot-existing.json "<botDefinitionId-or-empty>" "<developerName>" "<agentTemplate>". Branch:exists:false⇒ Phase 3 (create);exists:true+needsActivation:false⇒ ALREADY-CREATED (skip to Phase 7);exists:true+needsActivation:true⇒ Phase 2b. Non-zero exit ⇒ surface CLI error; never assume absent. Why the fallback keys: the broad agent ships pre-provisioned asIT_Service_Employeewith a null templatebotDefinitionId, so neither the primary key nor thedeveloperNameguess (IT_Service_Employee_Agent) catches it — itsAgentTemplate(svc_emp_intelligence__ItEmployeeAssistance) matches it by the platform-stamped source template; thedeveloperNamefallback catches self-created repeats — a miss on all three re-creates and hitsDUPLICATE_VALUE. - Phase 2b — Reactivation offer.
AskUserQuestion: "Employee agent<developerName>exists but latest version is Inactive. Activate it?". On Yes:POST /connect/bot-versions/<latestVersionId>/activationwith{"status":"Active"}— skips Phases 3–6, straight to Phase 7. Aggregate verdict is ACTIVATED, not CREATED. On No: stop, no writes. - Phase 3 — Confirm-to-Write (REQUIRED, create path only). If
${outputDir}was provided, first render the checkpoint file viarender-report.mjswithverdict:"PENDING CONFIRMATION"(skip for interactive runs). THEN raise theAskUserQuestiongate presenting developerName + label + "NGA-native from the Employee template's Agent Script". Proceed only on explicit "yes"; on "no" (including "hold off on activation" / "not yet" / any decline of the atomic chain), re-render withverdict:"DECLINED"and a one-linereason. - Phase 4 — Create.
scripts/build-create-body.mjs ${SCRATCH_DIR}/agent-templates.json "<masterLabel>" "<developerName>" "<label>" ${SCRATCH_DIR}/create-bundle-body.json(helper re-reads Phase-1 templates JSON, HTML-decodes the matchedagentScript, substitutes internalconfig.developer_name/config.agent_label, writes body to file — pass the same<masterLabel>used in Phase 1), thenPOST /nextgen-authoring/bundles --body @${SCRATCH_DIR}/create-bundle-body.json. Capture responseid— that is thebundleVersionIdfor Phases 5–6, notbundleId.403 FUNCTIONALITY_NOT_ENABLED/404⇒ trigger the Phase-1 hand-off; build-script exit 3 ⇒ surface stderr. - Phase 5 — Publish.
POST /nextgen-authoring/bundle-versions/<bundleVersionId>/publish --body '{}'(empty body required). Success:{ lastPublishedOn, publishedBotId, publishedBotVersionId }— this call creates the underlyingBotDefinition/BotVersion. Any error ⇒ surface verbatim; never activate an unpublished version. - Phase 6 — Activate.
POST /nextgen-authoring/bundle-versions/<bundleVersionId>/activate --body '{}'. Success returns an empty body — check exit code, do not parse a payload. - Phase 7 — Verify. SOQL
BotDefinition WHERE Id='<id>'(+BotVersionssubquery) and classify —<id>is the create path'spublishedBotId(captured from Phase 5) or, on the ALREADY-CREATED / reactivation path, the live matched Id the Phase-2 classifier returned (itsbotDefinitionId/agentIdoutput — the actualBotDefinition.Idof the matched record), not the Phase-1 templatebotDefinitionId(which is null on amatchedBy:"developerName"fallback hit → the verify would runWHERE Id=''and falsely report failure after a successful skip/activation). Confirmexists:true, count:1, latestVersionStatus:"Active". Any discrepancy ⇒ report verbatim, do not fabricate success. - Phase 8 — Aggregate verdict. Emit CREATED / ALREADY-CREATED / ACTIVATED / FAILED (ACTIVATED on the Phase-2b path) +
BotDefinitionId / bundleidby re-invokingrender-report.mjs— the single source of report text. If${outputDir}was provided, overwrite${outputDir}/report.md; otherwise emit stdout as the turn-side report.
Rules / Constraints
| Constraint | Rationale |
|---|---|
All calls go through sf api request rest / sf data query; never extract the access token |
Leaks a bearer token into shell context; the CLI's stored session is the correct surface |
Idempotency + verify reads key PRIMARILY on the template's botDefinitionId (Phase-1 row) / the publish publishedBotId, falling back to the collected <developerName>; that same <developerName>/<label> also thread through the create body (outer apiName/label AND the substituted config.developer_name/config.agent_label) |
botDefinitionId catches the pre-provisioned IT_Service_Employee (≠ the guessed IT_Service_Employee_Agent, so a name-only read would false-negative → DUPLICATE_VALUE); but self-created agents never back-fill it, so the <developerName> fallback catches those. A create-body hardcode/collect mismatch diverges the bundle's outer identity from the script's internal identity |
Preflight, idempotency, bundle-body construction, and report rendering all live in scripts/*.mjs, not prose (A9) |
JSON parsing + masterLabel matching + hasAccess reads + verdict emission are deterministic; the ~70KB Agent Script and free-text apostrophes cannot be safely interpolated into a shell string — JSON.stringify in the helper escapes them |
Three-call sequence: createBundleWithVersion → publish → activate, in that order, on the SAME captured bundleVersionId (response id, not bundleId) |
Platform enforces DRAFT → published → active; response-body / empty-body / --json / agentType / HTML-decode gotchas live in references/error-taxonomy.md |
Resolve <masterLabel> BEFORE Phase 1; filter data[] to svc_emp_intelligence__ only; disambiguate ambiguous keywords via AskUserQuestion keyed on id |
Label-similar pairs exist; other namespaces belong to other flows (svc_itsm_intelligence__* → Fulfiller skill) |
Enumerate BotDefinition with the BotVersions subquery; skip create when Active; offer Phase-2b reactivation when Inactive — never silent skip, never duplicate create |
Subquery is what distinguishes Active/Inactive; the server rejects a duplicate DeveloperName at publish (unique-constraint → bundle cleanup) but not the pre-provisioned broad agent, so this read is what turns a repeat into a graceful skip instead of a hard error |
| REQUIRED confirm-to-write checkpoint before create sequence or reactivation call | Both change live org state — explicit user approval required |
On hasAccess=false / 403 FUNCTIONALITY_NOT_ENABLED, offer the readiness hand-off — never enable features here; never call legacy /connect/service-itsm/createAgent |
Enablement is a Setup-UI/admin action; createAgent produces a Setup-page bot with an external-link icon (wrong kind of agent for this skill) |
| Report exact CLI response text on any error | Enables support to diagnose failures |
Verification Checklist
- Resolved
<masterLabel>before Phase 1 (broad default or specialization fromreferences/specialized-templates.md,data[]filtered tosvc_emp_intelligence__, disambiguated onid). - Preflight classified by
classify-preflight.mjs(PASS or documented CANNOT-CONFIRM); hand-off offered on FAIL; raw error surfaced on ERROR. - Idempotency keyed on the template's
botDefinitionId(Phase-1 row) with the BotDefinition'sAgentTemplate(Phase-1template.id) as the first fallback and the collected developerName as the last;BotDefinition WHERE Id='<botDefinitionId>' OR AgentTemplate='<agentTemplate>' OR DeveloperName='<developerName>'(theORs cover a null/danglingbotDefinitionId, the pre-provisioned broad agent whose DeveloperName differs from the guess, and self-created agents with a nullAgentTemplate) + latestBotVersion.Status(subquery present) read + classified before any write. - If
needsActivation:true, Phase-2b reactivation offer presented — no silent skip, no duplicate create. - Explicit user confirmation at Phase 3 (create) or Phase 2b (reactivation) before any write.
- Bundle body built by
build-create-body.mjs, POSTed via--body @<file>with the collecteddeveloperName/label; or write correctly skipped. - Same
bundleVersionId(responseid) used for publish + activate; reactivation usedPOST /connect/bot-versions/<id>/activation; legacycreateAgentnever called. - Phase-7 verify confirmed
BotDefinitionpresent + latest version Active. - Access token never extracted; final verdict +
BotDefinition/bundle Id reported.
Output Format
The report layout is generated deterministically by scripts/render-report.mjs — the single source of report text for both the chat turn and the harness's ${outputDir}/report.md. Never hand-compose the layout in prose (A9); always shell out to the helper. Full rendered shape, report-state JSON schema, and checkpoint-write rules live in references/report-format.md.
Terminal verdicts: CREATED | ALREADY-CREATED | ACTIVATED | PENDING CONFIRMATION | DECLINED | FAILED. When ${outputDir} is set, write at Phase 2, Phase 6 (or Phase 2b), and Phase 8 — each write overwrites the same file. Skip these writes in interactive/chat surfaces.
Reference File Index
references/specialized-templates.md— catalog + namespace filter +id-based disambiguation (before Phase 1 on any specialization).references/workflow-detail.md— exactsf/nodecommands + full verdict-branch narrative per phase.references/cli-invocation.md— command shapes, never-extract-token rule, ITSM Connect API reference, helper-script contracts.references/reactivation.md— Phase-2b activation call + full idempotency verdict table.references/report-format.md— rendered shape, phase-state JSON schema, three-checkpoint write policy.references/error-taxonomy.md— response-body error codes + recurring foot-guns (any non-2xx / empty body / script non-zero exit).
Loading...
Select a file to preview
Analyzing security...
Checking scan reports and verification data.
Bill of Materials
Everything this skill can do — files, network, commands, and more.