Help & Support
Elevate Your Agents with AgentExchange Solutions
Have Questions?
Service Itsm Agentic Setup Agent Runtime Access Assign
Overview
Grant a user the runtime permissions an activated ITSM agent's actions need so the actions do not fail on permission errors. After a Fulfiller or Employee agent is activated, this skill detects which platform feature permission sets are provisioned (Prompt Templates, Data Cloud, Unified Catalog), lets you pick a tier (user/agent vs admin) per feature and which user(s) to assign, then assigns them (license first when license-gated). It also creates a custom "Agent Access" permission set granting the activated agents you choose and assigns it to the user — all via the Salesforce CLI. Use to grant a user access to an activated agent, to assign prompt-template, data-cloud, or unified-catalog access, or to create an Agent Access permission set. DO NOT TRIGGER for enabling Agentforce for IT Service toggles, creating or activating an agent, the Fulfiller activation action-surfacing gap (service-itsm-agentic-setup-itsm-agentforce-permset-assign), CMDB access, or generic permission-set assignment.
Grant Runtime Access for an Activated ITSM Agent
An ITSM agent (Fulfiller or Employee) can be created and activated, yet fail the moment it's opened — its actions call platform features the user can't execute. This skill closes that gap after activation via two write-capable steps behind one confirmation:
- Runtime action-execution permissions. Detect which feature permission sets are provisioned, let the user pick a tier per feature (user/agent vs admin) and which user(s) to grant, then assign — license first when license-gated.
- A custom "Agent Access" permission set. Create (or reuse) Agent Access, grant the activated agents the user chooses (one
SetupEntityAccessper agent), then assign it to the same user(s).
The verified feature → tier → permset matrix lives in references/permset-topology.md. No org has all three features — assign only what is provisioned and report the rest as unavailable, never failing on an absent feature.
Every read and write runs through the Salesforce CLI (sf) — no metadata XML, no token extraction, no MCP.
Scope
- In scope: detecting which platform feature permsets are provisioned; per-feature tier selection; asking which user(s) to grant (running user offered, never silent) and resolving them; PSL-then-permset assignment (license-gated tiers) idempotently; creating/reusing the custom
Agent_Accesspermission set; adding aSetupEntityAccessgrant per chosen activated agent; assigningAgent_Accessto the user(s); verifying assignments by read-back. - Out of scope (owning skill parenthesized): the Agentforce for IT Service Go toggles / Studio config (
service-itsm-agentic-setup-agentforce-studio-configure); creating or activating the Employee (service-itsm-agentic-setup-employee-agent-configure) or Fulfiller (service-itsm-agentic-setup-fulfiller-agent-configure) agent; the Fulfiller activation action-surfacing gap (create/activate-time, not this runtime one —service-itsm-agentic-setup-itsm-agentforce-permset-assign); CMDB access (service-itsm-agentic-setup-cmdb-access-assign); generic non-ITSM permission-set assignment; authoring/editing feature permsets.
Helper scripts (all invoked via Bash) hold every deterministic decision (A9)
Full I/O contracts in references/helper-contracts.md.
scripts/classify-platform-permset-availability.mjs— which features are provisioned, each tier'spresent+needsPsl, and the org's own display label per tier.scripts/resolve-target-user.mjs— running-user Id from the API-rootidentityURL (fails closed on a malformed shape).scripts/rank-candidate-users.mjs— up to five real, non-service candidate users to offer, ranked by audience (standard-license first for a Fulfiller agent, Unified Employee first for an Employee agent).scripts/gate-unified-catalog-tiers.mjs— per target user, which Unified Catalog tiers to offer (Community User → Unified Employee; Admin → System Administrator), else omit UC for that user.scripts/classify-activated-agents.mjs— the activated-agent candidate list (BotDefinitionInternalCopilotwith ≥1ActiveBotVersion).scripts/classify-agent-access-state.mjs— whetherAgent_Accessmust be created and which chosen agents still need a grant (idempotency).scripts/classify-assignment-state.mjs— per user+permset idempotency; pass the sentinelNO-PSLwhen the selected tier'sneedsPsl:false.
Preconditions
sfCLI installed and authenticated to the target org (sf org display -o <alias>shows Connected). All calls use--target-org <alias>; never extract or pass the access token by hand.- API v67.0+.
node≥ 18 on PATH.
If a precondition fails, sf surfaces an auth or 401/403/404; report the raw response verbatim and stop — do not fabricate state.
Clarifying questions
Ask only what cannot be inferred from conversation:
- Target org — the
sfalias. Default tosf config get target-orgif unset. - Target user(s) — never a silent default: if unnamed, ASK via
AskUserQuestion(see Phase 2); if named, honor it. - Tier per provisioned feature — for EACH provisioned feature, ask which tier (lighter user/agent vs full admin); never auto-select.
- Which activated agents — multi-select from the activated-agent list; if only one is activated, still confirm it.
- Confirm the write — one consolidated confirmation covering every write; require an explicit "yes" via
AskUserQuestionbefore any write.
Workflow
All calls go through sf; substitute <alias> with the target org. Use the skill's absolute directory for every script path. Exact command shapes: references/cli-invocation.md.
Phase 1 — Read: what is provisioned, and what is activated?
Query the six platform feature permsets, capture to a file, and classify:
sf data query \ -q "SELECT Id, Name, Label, LicenseId FROM PermissionSet WHERE Name IN ('EinsteinGPTPromptTemplateUser','EinsteinGPTPromptTemplateManager','GenieUserEnhancedSecurity','GenieAdmin','UnifiedCatalogCommunityUser','UnifiedCatalogAdmin')" \ --target-org <alias> --json > /tmp/itsm-platform-permsets.json 2>/tmp/itsm-platform-permsets.err || true node "<skill_dir>/scripts/classify-platform-permset-availability.mjs" /tmp/itsm-platform-permsets.jsonThe classifier returns
{ features, provisionedFeatures, absentFeatures, verdict }.verdict:"ASSIGNABLE"⇒ ≥1 feature is provisioned;verdict:"NONE-PROVISIONED"⇒ no feature permset can be assigned (still continue to the Agent Access concern);verdict:"CANNOT-CONFIRM"⇒ surface the raw error and stop.Query the activated agents (BotDefinition + active-version child subquery), capture, and classify:
sf data query \ -q "SELECT Id, DeveloperName, MasterLabel, (SELECT Status FROM BotVersions WHERE Status='Active') FROM BotDefinition WHERE Type='InternalCopilot'" \ --target-org <alias> --json > /tmp/itsm-agents.json 2>/tmp/itsm-agents.err || true node "<skill_dir>/scripts/classify-activated-agents.mjs" /tmp/itsm-agents.jsonverdict:"AGENTS-FOUND"⇒ presentactivatedAgents[]for the multi-select;verdict:"NONE-ACTIVE"⇒ there is nothing forAgent_Accessto grant (report it; ifNONE-PROVISIONEDalso holds there is no work — stop).
Phase 2 — Choose target user(s) (never a silent default)
Resolve the running user (to offer as a labelled option) and query active org users so a helper can rank real, non-service candidates to offer as ready picks — never proceed with an unstated default:
sf api request rest "/services/data/v67.0/" --method GET --target-org <alias> > /tmp/api-root.json 2>/tmp/api-root.err || true node "<skill_dir>/scripts/resolve-target-user.mjs" /tmp/api-root.json sf data query -q "SELECT Name, Profile.Name, Profile.UserLicense.Name FROM User WHERE Id='<userId>'" --target-org <alias> --json > /tmp/itsm-running-user.json 2>/dev/null || true sf data query -q "SELECT Id, Name, Username, Profile.Name, Profile.UserLicense.Name FROM User WHERE IsActive = true ORDER BY LastLoginDate DESC NULLS LAST LIMIT 25" --target-org <alias> --json > /tmp/itsm-candidate-users.json 2>/dev/null || true node "<skill_dir>/scripts/rank-candidate-users.mjs" /tmp/itsm-candidate-users.json <audience> <userId>On
verdict:"RESOLVED"keepuserId; take itsNamefrom/tmp/itsm-running-user.jsonfor the label; onCANNOT-CONFIRMsurface the reasons and stop. If the prompt already named the target user(s) ("grant me" / a username), honor it without asking. Otherwise set<audience>from the agent this grant is for —fulfiller(prefer standard-license users) oremployee(prefer Unified Employee users), elseany— inferring it from the agent named in the request/handoff or the Phase-1 activated set;rank-candidate-users.mjsreturns up to five real, non-service candidates ranked for that audience. Present anAskUserQuestion(multi-select) with those users as direct selectable options — never a plain-prose username request: the running user (labelled "Me — ", or just "Me"; recommended) plus the top candidates. The picker allows four options, so offer "Me" + the top three ranked candidates; its built-in "Other" takes any username(s) not listed. Resolve each chosen/typed user byUsername(query shape inreferences/cli-invocation.md, capturing each to its own file); skip inactive/unknown with a note. The confirmed user Ids drive every assignment below.
Phase 3 — Selections (no writes)
- For each provisioned feature, ask the tier (user/agent vs admin) via
AskUserQuestionand record the selected tier's{ name, Id, LicenseId, needsPsl }; report each absent feature as "not provisioned on this org — skipped". Unified Catalog is license-shape gated per selected user — runscripts/gate-unified-catalog-tiers.mjsonce per user against that user's own capture and offer only itsoffer[]tiers: Community User only to a Unified Employee user, Admin only to a System Administrator; onomit, skip Unified Catalog for that user as "not applicable for this user's license/profile — skipped" — never offered, never a failed write. - Ask which activated agents to add to
Agent_AccessviaAskUserQuestion(multi-select). Record their BotDefinition Ids as a comma-separated list.
Phase 4 — Idempotency reads (no writes)
Agent Access state. Query the
Agent_Accesspermset and (only if it exists) its existingBotDefinitiongrants — capture to/tmp/agent-access.jsonand/tmp/sea.json(query shapes inreferences/cli-invocation.md→ Phase 4) — then classify against the chosen agent Ids:node "<skill_dir>/scripts/classify-agent-access-state.mjs" /tmp/agent-access.json <sea.json|NO-PERMSET> "<chosenAgentIds-csv>"Pass
NO-PERMSETfor the second arg whenAgent_Accessdoes not exist yet. The classifier returns{ permsetExists, permsetId, missingAgentIds, needsCreate, needsGrants, verdict }.Per user + permset. For each target user × (each selected feature tier and
Agent_Access), read existing assignments (PermissionSetAssignment, plusPermissionSetLicenseAssignonly whenneedsPsl:true; shapes inreferences/cli-invocation.md) and classify.Agent_Accessis standalone (needsPsl:false→NO-PSL); a feature tier usesneedsPslfrom its own row. If step 6 flaggedAgent_Accessabsent (needsCreate:true), skip its keyedPermissionSetAssignmentread — no permset ⇒ verdictNEEDS-WRITE; Phase 6 creates it, then assigns by name. Run the keyed read forAgent_Accessonly when step 6 returned an existingpermsetId:node "<skill_dir>/scripts/classify-assignment-state.mjs" /tmp/psa.json </tmp/psla.json|NO-PSL>
Phase 5 — Confirm-to-write checkpoint (REQUIRED)
- Present ONE consolidated summary — every target user, each feature tier to assign (and each absent feature being skipped), whether
Agent_Accesswill be created and which agents it will grant, and every permset assignment — and require an explicit "yes" viaAskUserQuestion. On "no", stop and report the planned state with no writes. Assigning a license-gated tier consumes a license seat and takes effect for a live session.
Phase 6 — Writes (only what Phase 4 flagged as needed)
Agent Access permset (once): if
needsCreate, POST to/sobjects/PermissionSet{"Name":"Agent_Access","Label":"Agent Access"}and capture the newid. Then for each Id inmissingAgentIds, POST to/sobjects/SetupEntityAccess{"ParentId":"<permsetId>","SetupEntityId":"<agentId>"}— do not sendSetupEntityType(it is not createable; it is derived from the0Xxkey prefix).DUPLICATE_VALUEon a grant ⇒ already granted, treat as success.Feature tiers, per user, for each tier whose Phase 4 verdict was
NEEDS-WRITE, ordered byneedsPsl:needsPsl:true— POST the PSL to/sobjects/PermissionSetLicenseAssign(using the tier's ownLicenseId) FIRST, thensf org assign permset --name <tierName>(running user: omit--on-behalf-of; named user:--on-behalf-of "<username>").needsPsl:false— skip the PSL POST; runsf org assign permsetonly.
Agent Access assignment, per user:
sf org assign permset --name Agent_Access(running user: omit--on-behalf-of; named user:--on-behalf-of "<username>") when its Phase 4 verdict wasNEEDS-WRITE.--on-behalf-ofresolves byUsername, never a005Id or a$USERNAMEshell var (seereferences/cli-invocation.md).Response handling (all writes): success ⇒ done;
DUPLICATE_VALUE/already has⇒ idempotent success;INSUFFICIENT_ACCESS/seat-exhaustion on a PSL POST ⇒ STOP and tell the user no seats are available; any other error ⇒ surface verbatim, mark FAILED. (Full taxonomy inreferences/cli-invocation.md.)
Phase 7 — Verify + aggregate
- Re-read the assignments written (
PermissionSetAssignment/PermissionSetLicenseAssignfor the target user(s);SetupEntityAccessforAgent_Access) and confirm each intended row is present. Then report one aggregate verdict:- ASSIGNED — at least one write occurred and every read-back confirms it.
- ALREADY-ASSIGNED — nothing needed writing; all intended state was already present.
- PARTIAL — some assignments succeeded and at least one FAILED or didn't read back. List which.
- NONE-PROVISIONED — no feature provisioned AND no agent activated: nothing to assign. Point at the create/enable skills.
- FAILED — every attempted write returned an error other than a duplicate. Report the raw errors.
Rules / Constraints
| Constraint | Rationale |
|---|---|
| Detect provisioned features before assigning; report absent features as "not provisioned", never fail on them | No org has all three; an absent permset errors and masks real state |
| Ask the tier (user/agent vs admin) per provisioned feature — never auto-select | The lighter tier suffices to use the feature; admin over-grants |
| Offer standard-license users for a Fulfiller agent, Unified Employee for an Employee agent; the ranker drops service/bot accounts | The wrong cohort offers users who can't run that agent |
Offer a Unified Catalog tier only to a user who can hold it (Community User → Unified Employee; Admin → System Administrator), else omit for that user — via scripts/gate-unified-catalog-tiers.mjs |
UC PSLs are license-shape gated; an ineligible tier is a hard write-time failure, not a seat shortage |
| All availability / idempotency / activation decisions are made by helper scripts, never by prose | They gate writes/success; scripts are deterministic, prose is not (A9) |
needsPsl is read PER ROW from the selected tier's own LicenseId; the PSL POST uses that LicenseId — never a hard-coded PSL name |
Different orgs carry different license shapes; a wrong PermissionSetLicenseId POSTs the wrong seat |
Assign the PSL before the permission set when needsPsl:true |
The permset is license-backed; hold the seat first |
Agent_Access grants access to activated agents ONLY, via SetupEntityAccess rows whose SetupEntityId is the BotDefinition Id |
Access is granted like Apex-class access — one grant row per agent |
POST SetupEntityAccess with ParentId + SetupEntityId ONLY — never SetupEntityType |
Not createable — derived from the SetupEntityId key prefix; sending it errors |
Create Agent_Access via the standard data API POST to /sobjects/PermissionSet — never Tooling/Metadata XML |
Createable over the data API with just Name+Label; no deploy needed |
| One consolidated confirm-to-write before ANY write | The full plan (seats consumed, live-session effect) must be approved once |
Treat DUPLICATE_VALUE / already has as idempotent success on every write |
Re-running must be safe; a duplicate means the state already holds |
| Verify by read-back before reporting ASSIGNED | A POST return code alone doesn't prove the row is present |
| Never extract the access token; never use an MCP dispatcher | Extracting a token leaks a bearer credential |
| Report exact error text from the CLI response | Enables support to diagnose failures |
Verification Checklist
- Provisioned features classified by
scripts/classify-platform-permset-availability.mjs; absent reported "not provisioned", not failed. - A tier (user/agent vs admin) was chosen per provisioned feature — no auto-selection; Unified Catalog tiers gated per user by
scripts/gate-unified-catalog-tiers.mjs. - Activated agents classified by
scripts/classify-activated-agents.mjs; only active-version agents were offered. - Target user(s) confirmed — when unnamed, asked via
AskUserQuestion(running user + audience-ranked users fromscripts/rank-candidate-users.mjs+ "Other"), never silent. Running user viascripts/resolve-target-user.mjs; named byUsername. -
Agent_Accesscreate/grant decided byscripts/classify-agent-access-state.mjs;SetupEntityAccessPOSTs sentParentId+SetupEntityIdonly. - Per user+permset idempotency classified by
scripts/classify-assignment-state.mjsbefore any write. - The selected tier's own
LicenseIddrove the PSL POST whenneedsPsl:true, POSTed before the permset. - One consolidated confirm-to-write gate preceded every write.
-
DUPLICATE_VALUE/already hastreated as success; other errors surfaced verbatim. - Assignments verified by read-back; one aggregate verdict reported (see Phase 7).
Output Format
ITSM Agent Runtime-Access Assignment (via service-itsm-agentic-setup-agent-runtime-access-assign)
Org: <org-alias> (API v67.0)
Target user(s): <username> (<userId>)[, ...]
Runtime action permissions:
Prompt Templates ...... <tier chosen: User | Manager | skipped | not provisioned> -> <assigned | already-had | FAILED>
Data Cloud ............ <tier chosen | skipped | not provisioned> -> <assigned | already-had | FAILED>
Unified Catalog ....... <tier chosen | skipped | not provisioned> -> <assigned | already-had | FAILED>
Agent Access permission set:
Permission set ........ <created | already existed>
Agents granted ........ <comma-separated agent names, or none>
Assigned to user(s) ... <assigned | already-had | FAILED>
Verdict: ASSIGNED | ALREADY-ASSIGNED | PARTIAL | NONE-PROVISIONED | FAILED
Reason: <plain-language explanation, or empty on success>
Next steps:
- <If ASSIGNED / ALREADY-ASSIGNED: "The user can now open and exercise the agent(s) in Agentforce Studio — action calls should no longer fail on missing permissions.">
- <If PARTIAL: list which assignments succeeded and which failed, verbatim.>
- <If NONE-PROVISIONED: nothing to assign — create/activate an agent and enable its features first.>
- <If FAILED: list the observed error(s) verbatim + remediation.>
Keep internal jargon (record Ids, HTTP codes, DUPLICATE_VALUE, object/dev names) out of user-facing output.
Reference File Index
| File | When to read |
|---|---|
references/permset-topology.md |
Any change to the feature/tier matrix — the six platform permsets, their tiers, PSLs, and the Agent_Access / SetupEntityAccess agent-access mechanism |
references/cli-invocation.md |
Every phase — exact sf data query / sf api request rest POST / sf org assign permset call shapes, the --json rule, the never-extract-token rule, response envelopes, and the error taxonomy |
references/helper-contracts.md |
The input/output shapes of all seven helper scripts and how to interpret each verdict |
Categories
- Domains
- Service CloudAgentforce
Related Skills
Salesforce
Enable the Agentforce for IT Service Salesforce Go feature toggles (Agentforce Studio, Einstein Generative AI, the parent umbrella, and the Fulfiller/Employee agent templates) using the Salesforce CLI (sf). Turns ON org prefs via the Setup Discovery featu
Categories
Agentforce Content
Salesforce
Grant a specific user access to CMDB (Configuration Management Database) data in Service Cloud ITSM against a production or sandbox org by assigning the license-backed CMDB permission sets (Configuration Item Reader, Owner, Type Reader, Type Manager) and
Categories
Agentforce Content
Salesforce
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 acti
Categories
Agentforce Content
Salesforce
Create and activate the IT Service Fulfiller agent as a Next-Gen Authoring (NGA) native agent from the shipped ITSM Fulfiller template's Agent Script, using the Salesforce CLI (sf): read the template, check idempotency, create the NGA bundle then publish
Categories
Agentforce Content
Salesforce
Resolve missing ITSM Intelligence invocable actions so a Fulfiller NGA agent can activate. Reads which of the three Core Fulfiller persona permsets (IncidentFulfiller, ProblemFulfillerPermSet, ChangeRequestFulfillerPermSet) are provisioned, then assigns t