service-itsm-agentic-setup-agent-runtime-access-assign
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGrant Runtime Access for an Activated ITSM Agent
为已激活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 per agent), then assign it to the same user(s).
SetupEntityAccess
The verified feature → tier → permset matrix lives in . No org has all three features — assign only what is provisioned and report the rest as unavailable, never failing on an absent feature.
references/permset-topology.mdEvery read and write runs through the Salesforce CLI () — no metadata XML, no token extraction, no MCP.
sfITSM Agent(Fulfiller或Employee)可以被创建并激活,但在打开的瞬间就会失败——因为它的操作调用了用户无法执行的平台功能。该Skill通过一次确认后的两个可写入步骤,填补激活后的这一缺口:
- 运行时操作执行权限。检测已配置的功能权限集,允许用户为每个功能选择一个权限层级(用户/Agent或管理员)以及要授予权限的用户,然后完成分配——如果是许可证 gated 的层级,先分配许可证。
- 自定义「Agent Access」权限集。创建(或复用)Agent Access权限集,为用户选择的已激活Agent授予权限(每个Agent对应一条记录),然后将该权限集分配给相同的用户。
SetupEntityAccess
已验证的功能→层级→权限集矩阵存放在中。没有任何组织会同时拥有这三个功能——仅分配已配置的功能,其余功能报告为不可用,永远不会因功能缺失而失败。
references/permset-topology.md所有读写操作均通过**Salesforce CLI()**执行——无需元数据XML、无需提取令牌、无需MCP。
sfScope
适用范围
- 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 permission set; adding a
Agent_Accessgrant per chosen activated agent; assigningSetupEntityAccessto the user(s); verifying assignments by read-back.Agent_Access - Out of scope (owning skill parenthesized): the Agentforce for IT Service Go toggles / Studio config (); creating or activating the Employee (
service-itsm-agentic-setup-agentforce-studio-configure) or Fulfiller (service-itsm-agentic-setup-employee-agent-configure) agent; the Fulfiller activation action-surfacing gap (create/activate-time, not this runtime one —service-itsm-agentic-setup-fulfiller-agent-configure); CMDB access (service-itsm-agentic-setup-itsm-agentforce-permset-assign); generic non-ITSM permission-set assignment; authoring/editing feature permsets.service-itsm-agentic-setup-cmdb-access-assign
- 包含范围:检测已配置的平台功能权限集;按功能选择权限层级;询问要授予权限的用户(提供当前运行用户选项,绝不静默执行)并解析用户信息;按PSL优先的方式分配权限集(许可证 gated 层级)且支持幂等;创建/复用自定义权限集;为所选已激活Agent添加
Agent_Access权限授予;将SetupEntityAccess分配给用户;通过回读验证分配结果。Agent_Access - 排除范围(对应负责Skill已标注):Agentforce for IT Service的Go开关/Studio配置();创建或激活Employee(
service-itsm-agentic-setup-agentforce-studio-configure)或Fulfiller(service-itsm-agentic-setup-employee-agent-configure)Agent;Fulfiller激活操作显示缺口(创建/激活时,而非本次运行时缺口——service-itsm-agentic-setup-fulfiller-agent-configure);CMDB访问权限分配(service-itsm-agentic-setup-itsm-agentforce-permset-assign);通用非ITSM权限集分配;功能权限集的编写/编辑。service-itsm-agentic-setup-cmdb-access-assign
Helper scripts (all invoked via Bash
) hold every deterministic decision (A9)
Bash辅助脚本(均通过Bash
调用)处理所有确定性决策(A9)
BashFull I/O contracts in .
references/helper-contracts.md- — which features are provisioned, each tier's
scripts/classify-platform-permset-availability.mjs+present, and the org's own display label per tier.needsPsl - — running-user Id from the API-root
scripts/resolve-target-user.mjsURL (fails closed on a malformed shape).identity - — 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/rank-candidate-users.mjs - — per target user, which Unified Catalog tiers to offer (Community User → Unified Employee; Admin → System Administrator), else omit UC for that user.
scripts/gate-unified-catalog-tiers.mjs - — the activated-agent candidate list (BotDefinition
scripts/classify-activated-agents.mjswith ≥1InternalCopilotBotVersion).Active - — whether
scripts/classify-agent-access-state.mjsmust be created and which chosen agents still need a grant (idempotency).Agent_Access - — per user+permset idempotency; pass the sentinel
scripts/classify-assignment-state.mjswhen the selected tier'sNO-PSL.needsPsl:false
完整的I/O契约存放在中。
references/helper-contracts.md- ——检测哪些功能已配置,每个层级的
scripts/classify-platform-permset-availability.mjs+present状态,以及组织中每个层级的显示标签。needsPsl - ——从API根目录
scripts/resolve-target-user.mjsURL获取当前运行用户ID(若格式错误则终止)。identity - ——提供最多5个真实的非服务候选用户,按受众排序(Fulfiller Agent优先选择标准许可证用户,Employee Agent优先选择Unified Employee用户)。
scripts/rank-candidate-users.mjs - ——针对每个目标用户,提供可分配的Unified Catalog层级(社区用户→Unified Employee;管理员→系统管理员),否则为该用户省略UC选项。
scripts/gate-unified-catalog-tiers.mjs - ——已激活Agent候选列表(BotDefinition类型为
scripts/classify-activated-agents.mjs且至少有一个InternalCopilot状态的BotVersion)。Active - ——判断是否需要创建
scripts/classify-agent-access-state.mjs权限集,以及哪些所选Agent仍需授予权限(支持幂等)。Agent_Access - ——按用户+权限集判断幂等状态;当所选层级的
scripts/classify-assignment-state.mjs时,传入标记needsPsl:false。NO-PSL
Preconditions
前置条件
- CLI installed and authenticated to the target org (
sfshows Connected). All calls usesf org display -o <alias>; never extract or pass the access token by hand.--target-org <alias> - API v67.0+.
- ≥ 18 on PATH.
node
If a precondition fails, surfaces an auth or //; report the raw response verbatim and stop — do not fabricate state.
sf401403404- 已安装CLI并已认证到目标组织(
sf显示已连接)。所有调用均使用sf org display -o <alias>;绝不手动提取或传递访问令牌。--target-org <alias> - API版本v67.0+。
- 版本≥18且已添加到PATH环境变量。
node
若前置条件不满足,会显示认证错误或//错误;直接报告原始响应并终止——切勿伪造状态。
sf401403404Clarifying questions
澄清问题
Ask only what cannot be inferred from conversation:
- Target org — the alias. Default to
sfif unset.sf config get target-org - Target user(s) — never a silent default: if unnamed, ASK via (see Phase 2); if named, honor it.
AskUserQuestion - 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 before any write.
AskUserQuestion
仅询问无法从对话中推断出的信息:
- 目标组织——别名。若未设置,默认使用
sf的结果。sf config get target-org - 目标用户——绝不使用静默默认值:若未指定名称,必须通过询问(见第二阶段);若已指定名称,则按指定执行。
AskUserQuestion - 每个已配置功能的权限层级——针对每个已配置功能,询问权限层级(轻量的用户/Agent或完整的管理员);绝不自动选择。
- 哪些已激活Agent——从已激活Agent列表中多选;若仅激活了一个Agent,仍需确认。
- 确认写入操作——提供一个包含所有写入操作的汇总确认,在执行任何写入操作前,需通过获取明确的“yes”确认。
AskUserQuestion
Workflow
工作流程
All calls go through ; substitute with the target org. Use the skill's absolute directory for every script path. Exact command shapes: .
sf<alias>references/cli-invocation.md所有调用均通过执行;将替换为目标组织别名。所有脚本路径均使用Skill的绝对目录。具体命令格式见:。
sf<alias>references/cli-invocation.mdPhase 1 — Read: what is provisioned, and what is activated?
第一阶段——读取:已配置哪些功能,已激活哪些Agent?
-
Query the six platform feature permsets, capture to a file, and classify:bash
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 }⇒ ≥1 feature is provisioned;verdict:"ASSIGNABLE"⇒ no feature permset can be assigned (still continue to the Agent Access concern);verdict:"NONE-PROVISIONED"⇒ surface the raw error and stop.verdict:"CANNOT-CONFIRM" -
Query the activated agents (BotDefinition + active-version child subquery), capture, and classify:bash
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.json⇒ presentverdict:"AGENTS-FOUND"for the multi-select;activatedAgents[]⇒ there is nothing forverdict:"NONE-ACTIVE"to grant (report it; ifAgent_Accessalso holds there is no work — stop).NONE-PROVISIONED
-
查询六个平台功能权限集,保存到文件并分类:bash
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.json分类器返回。{ features, provisionedFeatures, absentFeatures, verdict }表示至少有一个功能已配置;verdict:"ASSIGNABLE"表示没有可分配的功能权限集(仍需继续处理Agent Access相关事宜);verdict:"NONE-PROVISIONED"表示显示原始错误并终止。verdict:"CANNOT-CONFIRM" -
查询已激活Agent(BotDefinition + 子查询获取活动版本),保存到文件并分类:bash
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.json表示显示verdict:"AGENTS-FOUND"供多选;activatedAgents[]表示没有可通过verdict:"NONE-ACTIVE"授予权限的内容(报告此情况;若同时存在Agent_Access则无操作可执行——终止)。NONE-PROVISIONED
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:bash
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>Onkeepverdict:"RESOLVED"; take itsuserIdfromNamefor the label; on/tmp/itsm-running-user.jsonsurface the reasons and stop. If the prompt already named the target user(s) ("grant me" / a username), honor it without asking. Otherwise setCANNOT-CONFIRMfrom the agent this grant is for —<audience>(prefer standard-license users) orfulfiller(prefer Unified Employee users), elseemployee— inferring it from the agent named in the request/handoff or the Phase-1 activated set;anyreturns up to five real, non-service candidates ranked for that audience. Present anrank-candidate-users.mjs(multi-select) with those users as direct selectable options — never a plain-prose username request: the running user (labelled "Me — <name>", 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 byAskUserQuestion(query shape inUsername, capturing each to its own file); skip inactive/unknown with a note. The confirmed user Ids drive every assignment below.references/cli-invocation.md
-
解析当前运行用户(作为可选选项)并查询组织中的活跃用户,以便辅助脚本按受众排序真实的非服务候选用户——绝不使用未明确说明的默认值:bash
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>若则保留verdict:"RESOLVED";从userId中获取其/tmp/itsm-running-user.json作为标签;若Name则显示原因并终止。如果提示中已指定目标用户(如“授予我权限”或提供用户名),则直接按指定执行,无需询问。否则根据要授予权限的Agent设置CANNOT-CONFIRM——<audience>(优先选择标准许可证用户)或**fulfiller(优先选择Unified Employee用户),若无法确定则设为employee——从请求/移交中指定的Agent或第一阶段的已激活Agent集合推断;any返回最多5个针对该受众排序的真实非服务候选用户。通过rank-candidate-users.mjs(多选)呈现这些用户作为可直接选择的选项——绝不仅要求输入用户名:当前运行用户(标签为「我 — <姓名>」,或仅「我」;推荐使用)加上排名前三的候选用户。选择器允许四个选项,因此提供「我」+排名前三的候选用户**;内置的**「其他」**选项可输入未列出的任何用户名。通过AskUserQuestion解析每个选定/输入的用户(查询格式见Username,每个用户保存到单独文件);跳过非活跃/未知用户并提示说明。确认后的用户ID将驱动后续所有分配操作。references/cli-invocation.md
Phase 3 — Selections (no writes)
第三阶段——选择操作(无写入)
- For each provisioned feature, ask the tier (user/agent vs admin) via and record the selected tier's
AskUserQuestion; report each absent feature as "not provisioned on this org — skipped". Unified Catalog is license-shape gated per selected user — run{ name, Id, LicenseId, needsPsl }once per user against that user's own capture and offer only itsscripts/gate-unified-catalog-tiers.mjstiers: Community User only to a Unified Employee user, Admin only to a System Administrator; onoffer[], skip Unified Catalog for that user as "not applicable for this user's license/profile — skipped" — never offered, never a failed write.omit - Ask which activated agents to add to via
Agent_Access(multi-select). Record their BotDefinition Ids as a comma-separated list.AskUserQuestion
- 针对每个已配置的功能,通过询问权限层级(用户/Agent或管理员)并记录所选层级的
AskUserQuestion;将每个未配置的功能报告为“此组织未配置该功能——已跳过”。Unified Catalog的权限层级针对每个选定用户有许可证形态限制——针对每个用户运行{ name, Id, LicenseId, needsPsl },仅提供其scripts/gate-unified-catalog-tiers.mjs中的层级:仅为Unified Employee用户提供社区用户层级,仅为系统管理员提供管理员层级;若返回offer[]则为该用户省略Unified Catalog选项,报告为“该用户的许可证/配置文件不适用——已跳过”——绝不提供该选项,也不会出现写入失败。omit - 通过(多选)询问要添加到
AskUserQuestion权限集的已激活Agent。记录其BotDefinition ID为逗号分隔的列表。Agent_Access
Phase 4 — Idempotency reads (no writes)
第四阶段——幂等性读取(无写入)
-
Agent Access state. Query thepermset and (only if it exists) its existing
Agent_Accessgrants — capture toBotDefinitionand/tmp/agent-access.json(query shapes in/tmp/sea.json→ Phase 4) — then classify against the chosen agent Ids:references/cli-invocation.mdbashnode "<skill_dir>/scripts/classify-agent-access-state.mjs" /tmp/agent-access.json <sea.json|NO-PERMSET> "<chosenAgentIds-csv>"Passfor the second arg whenNO-PERMSETdoes not exist yet. The classifier returnsAgent_Access.{ permsetExists, permsetId, missingAgentIds, needsCreate, needsGrants, verdict } -
Per user + permset. For each target user × (each selected feature tier and), read existing assignments (
Agent_Access, plusPermissionSetAssignmentonly whenPermissionSetLicenseAssign; shapes inneedsPsl:true) and classify.references/cli-invocation.mdis standalone (Agent_Access→needsPsl:false); a feature tier usesNO-PSLfrom its own row. If step 6 flaggedneedsPslabsent (Agent_Access), skip its keyedneedsCreate:trueread — no permset ⇒ verdictPermissionSetAssignment; Phase 6 creates it, then assigns by name. Run the keyed read forNEEDS-WRITEonly when step 6 returned an existingAgent_Access:permsetIdbashnode "<skill_dir>/scripts/classify-assignment-state.mjs" /tmp/psa.json </tmp/psla.json|NO-PSL>
-
Agent Access状态。查询权限集,若存在则查询其现有的
Agent_Access权限授予——保存到BotDefinition和/tmp/agent-access.json(查询格式见/tmp/sea.json→第四阶段),然后根据所选Agent ID进行分类:references/cli-invocation.mdbashnode "<skill_dir>/scripts/classify-agent-access-state.mjs" /tmp/agent-access.json <sea.json|NO-PERMSET> "<chosenAgentIds-csv>"若尚未存在,则第二个参数传入Agent_Access。分类器返回NO-PERMSET。{ permsetExists, permsetId, missingAgentIds, needsCreate, needsGrants, verdict } -
按用户+权限集。针对每个目标用户 ×(每个选定功能层级 以及),读取现有分配记录(
Agent_Access,若PermissionSetAssignment则同时读取needsPsl:true;格式见PermissionSetLicenseAssign)并分类。references/cli-invocation.md为独立权限集(Agent_Access→传入needsPsl:false);功能层级使用自身的NO-PSL值。如果步骤6标记needsPsl不存在(Agent_Access),则跳过其needsCreate:true读取——无权限集则返回PermissionSetAssignment;第六阶段将创建该权限集,然后按名称分配。仅当步骤6返回已存在的verdict:NEEDS-WRITE时,才读取permsetId的相关记录:Agent_Accessbashnode "<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 will be created and which agents it will grant, and every permset assignment — and require an explicit "yes" via
Agent_Access. 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.AskUserQuestion
- 呈现一个汇总信息——所有目标用户、要分配的每个功能层级(以及每个被跳过的未配置功能)、是否将创建权限集以及将为哪些Agent授予权限、所有权限集分配操作——并通过
Agent_Access要求明确的“yes”确认。若用户回答“no”,则终止并报告计划状态,不执行任何写入操作。分配许可证 gated 的层级会消耗一个许可证席位,并对实时会话生效。AskUserQuestion
Phase 6 — Writes (only what Phase 4 flagged as needed)
第六阶段——写入操作(仅执行第四阶段标记为需要的操作)
-
Agent Access permset (once): if, POST to
needsCreate/sobjects/PermissionSetand capture the new{"Name":"Agent_Access","Label":"Agent Access"}. Then for each Id inid, POST tomissingAgentIds/sobjects/SetupEntityAccess— do not send{"ParentId":"<permsetId>","SetupEntityId":"<agentId>"}(it is not createable; it is derived from theSetupEntityTypekey prefix).0Xxon a grant ⇒ already granted, treat as success.DUPLICATE_VALUE -
Feature tiers, per user, for each tier whose Phase 4 verdict was, ordered by
NEEDS-WRITE:needsPsl- — POST the PSL to
needsPsl:true(using the tier's own/sobjects/PermissionSetLicenseAssign) FIRST, thenLicenseId(running user: omitsf org assign permset --name <tierName>; named user:--on-behalf-of).--on-behalf-of "<username>" - — skip the PSL POST; run
needsPsl:falseonly.sf org assign permset
-
Agent Access assignment, per user:(running user: omit
sf org assign permset --name Agent_Access; named user:--on-behalf-of) when its Phase 4 verdict was--on-behalf-of "<username>".NEEDS-WRITEresolves by--on-behalf-of, never aUsernameId or a005shell var (see$USERNAME).references/cli-invocation.mdResponse handling (all writes): success ⇒ done;/DUPLICATE_VALUE⇒ idempotent success;already has/seat-exhaustion on a PSL POST ⇒ STOP and tell the user no seats are available; any other error ⇒ surface verbatim, mark FAILED. (Full taxonomy inINSUFFICIENT_ACCESS.)references/cli-invocation.md
-
Agent Access权限集(仅执行一次):若为true,则向
needsCreate发送POST请求/sobjects/PermissionSet并捕获新的{"Name":"Agent_Access","Label":"Agent Access"}。然后针对id中的每个ID,向missingAgentIds发送POST请求/sobjects/SetupEntityAccess——请勿发送{"ParentId":"<permsetId>","SetupEntityId":"<agentId>"}(该字段不可创建;由SetupEntityType的键前缀自动推导)。若授予时返回SetupEntityId错误,则表示已授予权限,视为成功。DUPLICATE_VALUE -
功能层级,按用户执行,针对每个第四阶段返回的层级,按
NEEDS-WRITE顺序执行:needsPsl- ——先向
needsPsl:true发送PSL POST请求(使用该层级自身的/sobjects/PermissionSetLicenseAssign),然后执行LicenseId(当前运行用户:省略sf org assign permset --name <tierName>;指定用户:--on-behalf-of)。--on-behalf-of "<username>" - ——跳过PSL POST请求;仅执行
needsPsl:false。sf org assign permset
-
Agent Access分配,按用户执行:当第四阶段返回时,执行
NEEDS-WRITE(当前运行用户:省略sf org assign permset --name Agent_Access;指定用户:--on-behalf-of)。--on-behalf-of "<username>"通过--on-behalf-of解析,绝不使用UsernameID或005shell变量(见$USERNAME)。references/cli-invocation.md响应处理(所有写入操作):成功→完成;/DUPLICATE_VALUE→幂等成功;PSL POST请求返回already has/席位耗尽→终止并告知用户无可用席位;其他错误→直接显示原始错误,标记为FAILED。(完整错误分类见INSUFFICIENT_ACCESS。)references/cli-invocation.md
Phase 7 — Verify + aggregate
第七阶段——验证+汇总
- Re-read the assignments written (/
PermissionSetAssignmentfor the target user(s);PermissionSetLicenseAssignforSetupEntityAccess) and confirm each intended row is present. Then report one aggregate verdict:Agent_Access- 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.
- 重新读取已写入的分配记录(目标用户的/
PermissionSetAssignment;PermissionSetLicenseAssign的Agent_Access)并确认每条预期记录均存在。然后报告一个汇总结果:SetupEntityAccess- ASSIGNED——至少执行了一次写入操作,且所有回读均确认成功。
- ALREADY-ASSIGNED——无需执行任何写入操作;所有预期状态已存在。
- PARTIAL——部分分配成功,至少一个分配失败或未回读成功。列出成功和失败的项。
- NONE-PROVISIONED——无已配置功能且无已激活Agent:无操作可执行。指向创建/启用相关Skill。
- FAILED——所有尝试的写入操作均返回非重复错误。报告原始错误。
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 | 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) |
| Different orgs carry different license shapes; a wrong |
Assign the PSL before the permission set when | The permset is license-backed; hold the seat first |
| Access is granted like Apex-class access — one grant row per agent |
POST | Not createable — derived from the |
Create | Createable over the data API with just |
| One consolidated confirm-to-write before ANY write | The full plan (seats consumed, live-session effect) must be approved once |
Treat | 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 |
| 约束 | 理由 |
|---|---|
| 分配前先检测已配置功能;将未配置功能报告为“未配置”,绝不因功能缺失失败 | 没有组织会拥有全部三个功能;权限集缺失会导致错误并掩盖真实状态 |
| 针对每个已配置功能询问权限层级(用户/Agent或管理员)——绝不自动选择 | 轻量层级已足够使用功能;管理员层级会过度授权 |
| Fulfiller Agent优先提供标准许可证用户,Employee Agent优先提供Unified Employee用户;排序器会排除服务/机器人账户 | 错误的用户群体提供的用户无法运行对应的Agent |
仅向符合条件的用户提供Unified Catalog层级(社区用户→Unified Employee;管理员→系统管理员),否则为该用户省略该选项——通过 | UC的PSL受许可证形态限制;不符合条件的层级会导致写入时硬失败,而非席位不足 |
| 所有可用性/幂等性/激活决策均由辅助脚本处理,绝不通过文本描述判断 | 这些决策会控制写入操作/成功状态;脚本具有确定性,文本描述则不具备(A9) |
| 不同组织的许可证形态不同;错误的 |
当 | 权限集基于许可证;需先占用席位 |
| 权限授予方式与Apex类权限相同——每个Agent对应一条权限授予记录 |
发送 | 该字段不可创建——由 |
通过标准数据API POST请求 | 仅需 |
| 在执行任何写入操作前,提供一个汇总确认 | 完整计划(消耗的席位、对实时会话的影响)必须经过一次批准 |
将 | 重新执行必须安全;重复值表示状态已存在 |
| 报告ASSIGNED前需通过回读验证 | POST返回码本身无法证明记录已存在 |
| 绝不提取访问令牌;绝不使用MCP调度器 | 提取令牌会泄露Bearer凭证 |
| 报告CLI响应中的准确错误文本 | 支持团队可据此诊断故障 |
Verification Checklist
验证清单
- Provisioned features classified by ; absent reported "not provisioned", not failed.
scripts/classify-platform-permset-availability.mjs - 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 ; only active-version agents were offered.
scripts/classify-activated-agents.mjs - Target user(s) confirmed — when unnamed, asked via (running user + audience-ranked users from
AskUserQuestion+ "Other"), never silent. Running user viascripts/rank-candidate-users.mjs; named byscripts/resolve-target-user.mjs.Username - create/grant decided by
Agent_Access;scripts/classify-agent-access-state.mjsPOSTs sentSetupEntityAccess+ParentIdonly.SetupEntityId - Per user+permset idempotency classified by before any write.
scripts/classify-assignment-state.mjs - The selected tier's own drove the PSL POST when
LicenseId, POSTed before the permset.needsPsl:true - One consolidated confirm-to-write gate preceded every write.
- /
DUPLICATE_VALUEtreated as success; other errors surfaced verbatim.already has - Assignments verified by read-back; one aggregate verdict reported (see Phase 7).
- 通过分类已配置功能;未配置功能报告为“未配置”,而非失败。
scripts/classify-platform-permset-availability.mjs - 针对每个已配置功能选择了权限层级——无自动选择;通过针对每个用户限制Unified Catalog层级。
scripts/gate-unified-catalog-tiers.mjs - 通过分类已激活Agent;仅提供有活动版本的Agent。
scripts/classify-activated-agents.mjs - 已确认目标用户——若未指定名称,通过询问(当前运行用户+
AskUserQuestion返回的按受众排序的用户+“其他”选项),绝不静默执行。当前运行用户通过scripts/rank-candidate-users.mjs解析;通过scripts/resolve-target-user.mjs指定用户。Username - 通过决定
scripts/classify-agent-access-state.mjs的创建/授予;Agent_AccessPOST请求仅包含SetupEntityAccess+ParentId。SetupEntityId - 执行写入操作前,通过按用户+权限集判断幂等状态。
scripts/classify-assignment-state.mjs - 当时,所选层级自身的
needsPsl:true驱动PSL POST请求,且先于权限集分配。LicenseId - 所有写入操作前有一个汇总确认检查点。
- 将/
DUPLICATE_VALUE视为成功;其他错误直接显示原始内容。already has - 通过回读验证分配结果;报告一个汇总结果(见第七阶段)。
Output Format
输出格式
text
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, , object/dev names) out of user-facing output.
DUPLICATE_VALUEtext
ITSM Agent 运行时访问权限分配(通过 service-itsm-agentic-setup-agent-runtime-access-assign)
组织: <org-alias> (API v67.0)
目标用户: <username> (<userId>)[, ...]
运行时操作权限:
Prompt Templates ...... <所选层级: User | Manager | 已跳过 | 未配置> -> <已分配 | 已拥有 | 失败>
Data Cloud ............ <所选层级 | 已跳过 | 未配置> -> <已分配 | 已拥有 | 失败>
Unified Catalog ....... <所选层级 | 已跳过 | 未配置> -> <已分配 | 已拥有 | 失败>
Agent Access 权限集:
权限集 ........ <已创建 | 已存在>
已授予权限的Agent .... <逗号分隔的Agent名称,或无>
分配给用户 ....... <已分配 | 已拥有 | 失败>
结果: ASSIGNED | ALREADY-ASSIGNED | PARTIAL | NONE-PROVISIONED | FAILED
原因: <通俗易懂的解释,成功时留空>
后续步骤:
- <若为ASSIGNED / ALREADY-ASSIGNED: "用户现在可以在Agentforce Studio中打开并使用Agent——操作调用将不再因权限缺失失败。">
- <若为PARTIAL: 列出成功和失败的分配项,原始内容。>
- <若为NONE-PROVISIONED: 无操作可执行——先创建/激活Agent并启用其功能。>
- <若为FAILED: 列出观察到的错误(原始内容)+ 补救措施。>用户输出中请勿包含内部术语(记录ID、HTTP代码、、对象/开发名称)。
DUPLICATE_VALUEReference File Index
参考文件索引
| File | When to read |
|---|---|
| Any change to the feature/tier matrix — the six platform permsets, their tiers, PSLs, and the |
| Every phase — exact |
| The input/output shapes of all seven helper scripts and how to interpret each verdict |
| 文件 | 阅读场景 |
|---|---|
| 功能/层级矩阵变更时——六个平台权限集、其层级、PSL以及 |
| 每个阶段——准确的 |
| 所有七个辅助脚本的输入/输出格式以及如何解读每个结果 |