service-itsm-agentic-setup-agent-runtime-access-assign

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Grant 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:
  1. 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.
  2. A custom "Agent Access" permission set. Create (or reuse) Agent Access, grant the activated agents the user chooses (one
    SetupEntityAccess
    per 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.
ITSM Agent(Fulfiller或Employee)可以被创建并激活,但在打开的瞬间就会失败——因为它的操作调用了用户无法执行的平台功能。该Skill通过一次确认后的两个可写入步骤,填补激活后的这一缺口:
  1. 运行时操作执行权限。检测已配置的功能权限集,允许用户为每个功能选择一个权限层级(用户/Agent或管理员)以及要授予权限的用户,然后完成分配——如果是许可证 gated 的层级,先分配许可证
  2. 自定义「Agent Access」权限集。创建(或复用)Agent Access权限集,为用户选择的已激活Agent授予权限(每个Agent对应一条
    SetupEntityAccess
    记录),然后将该权限集分配给相同的用户。
已验证的功能→层级→权限集矩阵存放在
references/permset-topology.md
中。没有任何组织会同时拥有这三个功能——仅分配已配置的功能,其余功能报告为不可用,永远不会因功能缺失而失败。
所有读写操作均通过**Salesforce CLI(
sf
)**执行——无需元数据XML、无需提取令牌、无需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_Access
    permission set; adding a
    SetupEntityAccess
    grant per chosen activated agent; assigning
    Agent_Access
    to 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.
  • 包含范围:检测已配置的平台功能权限集;按功能选择权限层级;询问要授予权限的用户(提供当前运行用户选项,绝不静默执行)并解析用户信息;按PSL优先的方式分配权限集(许可证 gated 层级)且支持幂等;创建/复用自定义
    Agent_Access
    权限集;为所选已激活Agent添加
    SetupEntityAccess
    权限授予;将
    Agent_Access
    分配给用户;通过回读验证分配结果。
  • 排除范围(对应负责Skill已标注):Agentforce for IT Service的Go开关/Studio配置(
    service-itsm-agentic-setup-agentforce-studio-configure
    );创建或激活Employee(
    service-itsm-agentic-setup-employee-agent-configure
    )或Fulfiller(
    service-itsm-agentic-setup-fulfiller-agent-configure
    )Agent;Fulfiller激活操作显示缺口(创建/激活时,而非本次运行时缺口——
    service-itsm-agentic-setup-itsm-agentforce-permset-assign
    );CMDB访问权限分配(
    service-itsm-agentic-setup-cmdb-access-assign
    );通用非ITSM权限集分配;功能权限集的编写/编辑。

Helper scripts (all invoked via
Bash
) hold every deterministic decision (A9)

辅助脚本(均通过
Bash
调用)处理所有确定性决策(A9)

Full I/O contracts in
references/helper-contracts.md
.
  • scripts/classify-platform-permset-availability.mjs
    — which features are provisioned, each tier's
    present
    +
    needsPsl
    , and the org's own display label per tier.
  • scripts/resolve-target-user.mjs
    — running-user Id from the API-root
    identity
    URL (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 (BotDefinition
    InternalCopilot
    with ≥1
    Active
    BotVersion).
  • scripts/classify-agent-access-state.mjs
    — whether
    Agent_Access
    must be created and which chosen agents still need a grant (idempotency).
  • scripts/classify-assignment-state.mjs
    — per user+permset idempotency; pass the sentinel
    NO-PSL
    when the selected tier's
    needsPsl:false
    .

完整的I/O契约存放在
references/helper-contracts.md
中。
  • scripts/classify-platform-permset-availability.mjs
    ——检测哪些功能已配置,每个层级的
    present
    +
    needsPsl
    状态,以及组织中每个层级的显示标签。
  • scripts/resolve-target-user.mjs
    ——从API根目录
    identity
    URL获取当前运行用户ID(若格式错误则终止)。
  • scripts/rank-candidate-users.mjs
    ——提供最多5个真实的非服务候选用户,按受众排序(Fulfiller Agent优先选择标准许可证用户,Employee Agent优先选择Unified Employee用户)。
  • scripts/gate-unified-catalog-tiers.mjs
    ——针对每个目标用户,提供可分配的Unified Catalog层级(社区用户→Unified Employee;管理员→系统管理员),否则为该用户省略UC选项。
  • scripts/classify-activated-agents.mjs
    ——已激活Agent候选列表(BotDefinition类型为
    InternalCopilot
    且至少有一个
    Active
    状态的BotVersion)。
  • scripts/classify-agent-access-state.mjs
    ——判断是否需要创建
    Agent_Access
    权限集,以及哪些所选Agent仍需授予权限(支持幂等)。
  • scripts/classify-assignment-state.mjs
    ——按用户+权限集判断幂等状态;当所选层级的
    needsPsl:false
    时,传入标记
    NO-PSL

Preconditions

前置条件

  1. sf
    CLI 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.
  2. API v67.0+.
  3. 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.

  1. 已安装
    sf
    CLI并已认证到目标组织
    sf org display -o <alias>
    显示已连接)。所有调用均使用
    --target-org <alias>
    ;绝不手动提取或传递访问令牌。
  2. API版本v67.0+
  3. node
    版本≥18
    且已添加到PATH环境变量。
若前置条件不满足,
sf
会显示认证错误或
401
/
403
/
404
错误;直接报告原始响应并终止——切勿伪造状态。

Clarifying questions

澄清问题

Ask only what cannot be inferred from conversation:
  • Target org — the
    sf
    alias. Default to
    sf config get target-org
    if 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
    AskUserQuestion
    before any write.

仅询问无法从对话中推断出的信息:
  • 目标组织——
    sf
    别名。若未设置,默认使用
    sf config get target-org
    的结果。
  • 目标用户——绝不使用静默默认值:若未指定名称,必须通过
    AskUserQuestion
    询问(见第二阶段);若已指定名称,则按指定执行。
  • 每个已配置功能的权限层级——针对每个已配置功能,询问权限层级(轻量的用户/Agent或完整的管理员);绝不自动选择。
  • 哪些已激活Agent——从已激活Agent列表中多选;若仅激活了一个Agent,仍需确认。
  • 确认写入操作——提供一个包含所有写入操作的汇总确认,在执行任何写入操作前,需通过
    AskUserQuestion
    获取明确的“yes”确认。

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
.
所有调用均通过
sf
执行;将
<alias>
替换为目标组织别名。所有脚本路径均使用Skill的绝对目录。具体命令格式见:
references/cli-invocation.md

Phase 1 — Read: what is provisioned, and what is activated?

第一阶段——读取:已配置哪些功能,已激活哪些Agent?

  1. 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.json
    The 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.
  2. 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
    verdict:"AGENTS-FOUND"
    ⇒ present
    activatedAgents[]
    for the multi-select;
    verdict:"NONE-ACTIVE"
    ⇒ there is nothing for
    Agent_Access
    to grant (report it; if
    NONE-PROVISIONED
    also holds there is no work — stop).
  1. 查询六个平台功能权限集,保存到文件并分类:
    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"
    表示至少有一个功能已配置;
    verdict:"NONE-PROVISIONED"
    表示没有可分配的功能权限集(仍需继续处理Agent Access相关事宜);
    verdict:"CANNOT-CONFIRM"
    表示显示原始错误并终止。
  2. 查询已激活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)

第二阶段——选择目标用户(绝不使用静默默认值)

  1. 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>
    On
    verdict:"RESOLVED"
    keep
    userId
    ; take its
    Name
    from
    /tmp/itsm-running-user.json
    for the label; on
    CANNOT-CONFIRM
    surface 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) or
    employee
    (prefer Unified Employee users), else
    any
    — inferring it from the agent named in the request/handoff or the Phase-1 activated set;
    rank-candidate-users.mjs
    returns up to five real, non-service candidates ranked for that audience. Present an
    AskUserQuestion
    (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 by
    Username
    (query shape in
    references/cli-invocation.md
    , capturing each to its own file); skip inactive/unknown with a note. The confirmed user Ids drive every assignment below.
  1. 解析当前运行用户(作为可选选项)并查询组织中的活跃用户,以便辅助脚本按受众排序真实的非服务候选用户——绝不使用未明确说明的默认值:
    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
    作为标签;若
    CANNOT-CONFIRM
    则显示原因并终止。如果提示中已指定目标用户(如“授予我权限”或提供用户名),则直接按指定执行,无需询问。否则根据要授予权限的Agent设置
    <audience>
    ——
    fulfiller
    (优先选择标准许可证用户)或**
    employee
    (优先选择Unified Employee用户),若无法确定则设为
    any
    ——从请求/移交中指定的Agent或第一阶段的已激活Agent集合推断;
    rank-candidate-users.mjs
    返回最多5个针对该受众排序的真实非服务候选用户。通过
    AskUserQuestion
    (多选)呈现这些用户作为可直接选择的选项——绝不仅要求输入用户名
    :当前运行用户(标签为
    「我 — <姓名>」,或仅「我」;推荐使用)加上排名前三的候选用户。选择器允许四个选项,因此提供「我」+排名前三的候选用户**;内置的**「其他」**选项可输入未列出的任何用户名。通过
    Username
    解析每个选定/输入的用户(查询格式见
    references/cli-invocation.md
    ,每个用户保存到单独文件);跳过非活跃/未知用户并提示说明。确认后的用户ID将驱动后续所有分配操作。

Phase 3 — Selections (no writes)

第三阶段——选择操作(无写入)

  1. For each provisioned feature, ask the tier (user/agent vs admin) via
    AskUserQuestion
    and 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 — run
    scripts/gate-unified-catalog-tiers.mjs
    once per user against that user's own capture and offer only its
    offer[]
    tiers: Community User only to a Unified Employee user, Admin only to a System Administrator; on
    omit
    , skip Unified Catalog for that user as "not applicable for this user's license/profile — skipped" — never offered, never a failed write.
  2. Ask which activated agents to add to
    Agent_Access
    via
    AskUserQuestion
    (multi-select). Record their BotDefinition Ids as a comma-separated list.
  1. 针对每个已配置的功能,通过
    AskUserQuestion
    询问权限层级(用户/Agent或管理员)并记录所选层级的
    { name, Id, LicenseId, needsPsl }
    ;将每个未配置的功能报告为“此组织未配置该功能——已跳过”。Unified Catalog的权限层级针对每个选定用户有许可证形态限制——针对每个用户运行
    scripts/gate-unified-catalog-tiers.mjs
    ,仅提供其
    offer[]
    中的层级:仅为Unified Employee用户提供社区用户层级,仅为系统管理员提供管理员层级;若返回
    omit
    则为该用户省略Unified Catalog选项,报告为“该用户的许可证/配置文件不适用——已跳过”——绝不提供该选项,也不会出现写入失败。
  2. 通过
    AskUserQuestion
    (多选)询问要添加到
    Agent_Access
    权限集的已激活Agent。记录其BotDefinition ID为逗号分隔的列表。

Phase 4 — Idempotency reads (no writes)

第四阶段——幂等性读取(无写入)

  1. Agent Access state. Query the
    Agent_Access
    permset and (only if it exists) its existing
    BotDefinition
    grants — capture to
    /tmp/agent-access.json
    and
    /tmp/sea.json
    (query shapes in
    references/cli-invocation.md
    → Phase 4) — then classify against the chosen agent Ids:
    bash
    node "<skill_dir>/scripts/classify-agent-access-state.mjs" /tmp/agent-access.json <sea.json|NO-PERMSET> "<chosenAgentIds-csv>"
    Pass
    NO-PERMSET
    for the second arg when
    Agent_Access
    does not exist yet. The classifier returns
    { permsetExists, permsetId, missingAgentIds, needsCreate, needsGrants, verdict }
    .
  2. Per user + permset. For each target user × (each selected feature tier and
    Agent_Access
    ), read existing assignments (
    PermissionSetAssignment
    , plus
    PermissionSetLicenseAssign
    only when
    needsPsl:true
    ; shapes in
    references/cli-invocation.md
    ) and classify.
    Agent_Access
    is standalone (
    needsPsl:false
    NO-PSL
    ); a feature tier uses
    needsPsl
    from its own row. If step 6 flagged
    Agent_Access
    absent (
    needsCreate:true
    ), skip its keyed
    PermissionSetAssignment
    read
    — no permset ⇒ verdict
    NEEDS-WRITE
    ; Phase 6 creates it, then assigns by name. Run the keyed read for
    Agent_Access
    only when step 6 returned an existing
    permsetId
    :
    bash
    node "<skill_dir>/scripts/classify-assignment-state.mjs" /tmp/psa.json </tmp/psla.json|NO-PSL>
  1. Agent Access状态。查询
    Agent_Access
    权限集,若存在则查询其现有的
    BotDefinition
    权限授予——保存到
    /tmp/agent-access.json
    /tmp/sea.json
    (查询格式见
    references/cli-invocation.md
    →第四阶段),然后根据所选Agent ID进行分类:
    bash
    node "<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 }
  2. 按用户+权限集。针对每个目标用户 ×(每个选定功能层级 以及
    Agent_Access
    ),读取现有分配记录(
    PermissionSetAssignment
    ,若
    needsPsl:true
    则同时读取
    PermissionSetLicenseAssign
    ;格式见
    references/cli-invocation.md
    )并分类。
    Agent_Access
    为独立权限集(
    needsPsl:false
    →传入
    NO-PSL
    );功能层级使用自身的
    needsPsl
    值。如果步骤6标记
    Agent_Access
    不存在(
    needsCreate:true
    ),则跳过其
    PermissionSetAssignment
    读取
    ——无权限集则返回
    verdict:NEEDS-WRITE
    ;第六阶段将创建该权限集,然后按名称分配。仅当步骤6返回已存在的
    permsetId
    时,才读取
    Agent_Access
    的相关记录:
    bash
    node "<skill_dir>/scripts/classify-assignment-state.mjs" /tmp/psa.json </tmp/psla.json|NO-PSL>

Phase 5 — Confirm-to-write checkpoint (REQUIRED)

第五阶段——写入前确认检查点(必填)

  1. Present ONE consolidated summary — every target user, each feature tier to assign (and each absent feature being skipped), whether
    Agent_Access
    will be created and which agents it will grant, and every permset assignment — and require an explicit "yes" via
    AskUserQuestion
    . 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.
  1. 呈现一个汇总信息——所有目标用户、要分配的每个功能层级(以及每个被跳过的未配置功能)、是否将创建
    Agent_Access
    权限集以及将为哪些Agent授予权限、所有权限集分配操作——并通过
    AskUserQuestion
    要求明确的“yes”确认。若用户回答“no”,则终止并报告计划状态,不执行任何写入操作。分配许可证 gated 的层级会消耗一个许可证席位,并对实时会话生效。

Phase 6 — Writes (only what Phase 4 flagged as needed)

第六阶段——写入操作(仅执行第四阶段标记为需要的操作)

  1. Agent Access permset (once): if
    needsCreate
    , POST to
    /sobjects/PermissionSet
    {"Name":"Agent_Access","Label":"Agent Access"}
    and capture the new
    id
    . Then for each Id in
    missingAgentIds
    , POST to
    /sobjects/SetupEntityAccess
    {"ParentId":"<permsetId>","SetupEntityId":"<agentId>"}
    do not send
    SetupEntityType
    (it is not createable; it is derived from the
    0Xx
    key prefix).
    DUPLICATE_VALUE
    on a grant ⇒ already granted, treat as success.
  2. Feature tiers, per user, for each tier whose Phase 4 verdict was
    NEEDS-WRITE
    , ordered by
    needsPsl
    :
    • needsPsl:true
      — POST the PSL to
      /sobjects/PermissionSetLicenseAssign
      (using the tier's own
      LicenseId
      ) FIRST, then
      sf org assign permset --name <tierName>
      (running user: omit
      --on-behalf-of
      ; named user:
      --on-behalf-of "<username>"
      ).
    • needsPsl:false
      — skip the PSL POST; run
      sf org assign permset
      only.
  3. 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 was
    NEEDS-WRITE
    .
    --on-behalf-of
    resolves by
    Username
    , never a
    005
    Id or a
    $USERNAME
    shell var (see
    references/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 in
    references/cli-invocation.md
    .)
  1. Agent Access权限集(仅执行一次):若
    needsCreate
    为true,则向
    /sobjects/PermissionSet
    发送POST请求
    {"Name":"Agent_Access","Label":"Agent Access"}
    并捕获新的
    id
    。然后针对
    missingAgentIds
    中的每个ID,向
    /sobjects/SetupEntityAccess
    发送POST请求
    {"ParentId":"<permsetId>","SetupEntityId":"<agentId>"}
    ——请勿发送
    SetupEntityType
    (该字段不可创建;由
    SetupEntityId
    的键前缀自动推导)。若授予时返回
    DUPLICATE_VALUE
    错误,则表示已授予权限,视为成功。
  2. 功能层级,按用户执行,针对每个第四阶段返回
    NEEDS-WRITE
    的层级,按
    needsPsl
    顺序执行:
    • needsPsl:true
      ——先向
      /sobjects/PermissionSetLicenseAssign
      发送PSL POST请求(使用该层级自身的
      LicenseId
      ),然后执行
      sf org assign permset --name <tierName>
      (当前运行用户:省略
      --on-behalf-of
      ;指定用户:
      --on-behalf-of "<username>"
      )。
    • needsPsl:false
      ——跳过PSL POST请求;仅执行
      sf org assign permset
  3. Agent Access分配,按用户执行:当第四阶段返回
    NEEDS-WRITE
    时,执行
    sf org assign permset --name Agent_Access
    (当前运行用户:省略
    --on-behalf-of
    ;指定用户:
    --on-behalf-of "<username>"
    )。
    --on-behalf-of
    通过
    Username
    解析,绝不使用
    005
    ID或
    $USERNAME
    shell变量(见
    references/cli-invocation.md
    )。
    响应处理(所有写入操作):成功→完成;
    DUPLICATE_VALUE
    /
    already has
    →幂等成功;PSL POST请求返回
    INSUFFICIENT_ACCESS
    /席位耗尽→终止并告知用户无可用席位;其他错误→直接显示原始错误,标记为FAILED。(完整错误分类见
    references/cli-invocation.md
    。)

Phase 7 — Verify + aggregate

第七阶段——验证+汇总

  1. Re-read the assignments written (
    PermissionSetAssignment
    /
    PermissionSetLicenseAssign
    for the target user(s);
    SetupEntityAccess
    for
    Agent_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.

  1. 重新读取已写入的分配记录(目标用户的
    PermissionSetAssignment
    /
    PermissionSetLicenseAssign
    Agent_Access
    SetupEntityAccess
    )并确认每条预期记录均存在。然后报告一个汇总结果:
    • ASSIGNED——至少执行了一次写入操作,且所有回读均确认成功。
    • ALREADY-ASSIGNED——无需执行任何写入操作;所有预期状态已存在。
    • PARTIAL——部分分配成功,至少一个分配失败或未回读成功。列出成功和失败的项。
    • NONE-PROVISIONED——无已配置功能且无已激活Agent:无操作可执行。指向创建/启用相关Skill。
    • FAILED——所有尝试的写入操作均返回非重复错误。报告原始错误。

Rules / Constraints

规则/约束

ConstraintRationale
Detect provisioned features before assigning; report absent features as "not provisioned", never fail on themNo org has all three; an absent permset errors and masks real state
Ask the tier (user/agent vs admin) per provisioned feature — never auto-selectThe 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 accountsThe 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 proseThey 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 writeThe 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 ASSIGNEDA POST return code alone doesn't prove the row is present
Never extract the access token; never use an MCP dispatcherExtracting a token leaks a bearer credential
Report exact error text from the CLI responseEnables support to diagnose failures

约束理由
分配前先检测已配置功能;将未配置功能报告为“未配置”,绝不因功能缺失失败没有组织会拥有全部三个功能;权限集缺失会导致错误并掩盖真实状态
针对每个已配置功能询问权限层级(用户/Agent或管理员)——绝不自动选择轻量层级已足够使用功能;管理员层级会过度授权
Fulfiller Agent优先提供标准许可证用户,Employee Agent优先提供Unified Employee用户;排序器会排除服务/机器人账户错误的用户群体提供的用户无法运行对应的Agent
仅向符合条件的用户提供Unified Catalog层级(社区用户→Unified Employee;管理员→系统管理员),否则为该用户省略该选项——通过
scripts/gate-unified-catalog-tiers.mjs
实现
UC的PSL受许可证形态限制;不符合条件的层级会导致写入时硬失败,而非席位不足
所有可用性/幂等性/激活决策均由辅助脚本处理,绝不通过文本描述判断这些决策会控制写入操作/成功状态;脚本具有确定性,文本描述则不具备(A9)
needsPsl
从所选层级自身的
LicenseId
读取;PSL POST请求使用该
LicenseId
——绝不使用硬编码的PSL名称
不同组织的许可证形态不同;错误的
PermissionSetLicenseId
会分配错误的席位
needsPsl:true
时,先分配PSL再分配权限集
权限集基于许可证;需先占用席位
Agent_Access
仅为已激活Agent授予权限,通过
SetupEntityAccess
记录实现,其中
SetupEntityId
BotDefinition
ID
权限授予方式与Apex类权限相同——每个Agent对应一条权限授予记录
发送
SetupEntityAccess
POST请求时仅包含
ParentId
+
SetupEntityId
——绝不包含
SetupEntityType
该字段不可创建——由
SetupEntityId
的键前缀自动推导;发送该字段会导致错误
通过标准数据API POST请求
/sobjects/PermissionSet
创建
Agent_Access
——绝不使用Tooling/Metadata XML
仅需
Name
+
Label
即可通过数据API创建;无需部署
在执行任何写入操作前,提供一个汇总确认完整计划(消耗的席位、对实时会话的影响)必须经过一次批准
DUPLICATE_VALUE
/
already has
视为所有写入操作的幂等成功
重新执行必须安全;重复值表示状态已存在
报告ASSIGNED前需通过回读验证POST返回码本身无法证明记录已存在
绝不提取访问令牌;绝不使用MCP调度器提取令牌会泄露Bearer凭证
报告CLI响应中的准确错误文本支持团队可据此诊断故障

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 from
    scripts/rank-candidate-users.mjs
    + "Other"), never silent. Running user via
    scripts/resolve-target-user.mjs
    ; named by
    Username
    .
  • Agent_Access
    create/grant decided by
    scripts/classify-agent-access-state.mjs
    ;
    SetupEntityAccess
    POSTs sent
    ParentId
    +
    SetupEntityId
    only.
  • Per user+permset idempotency classified by
    scripts/classify-assignment-state.mjs
    before any write.
  • The selected tier's own
    LicenseId
    drove the PSL POST when
    needsPsl:true
    , POSTed before the permset.
  • One consolidated confirm-to-write gate preceded every write.
  • DUPLICATE_VALUE
    /
    already has
    treated as success; other errors surfaced verbatim.
  • Assignments verified by read-back; one aggregate verdict reported (see Phase 7).

  • 通过
    scripts/classify-platform-permset-availability.mjs
    分类已配置功能;未配置功能报告为“未配置”,而非失败。
  • 针对每个已配置功能选择了权限层级——无自动选择;通过
    scripts/gate-unified-catalog-tiers.mjs
    针对每个用户限制Unified Catalog层级。
  • 通过
    scripts/classify-activated-agents.mjs
    分类已激活Agent;仅提供有活动版本的Agent。
  • 已确认目标用户——若未指定名称,通过
    AskUserQuestion
    询问(当前运行用户+
    scripts/rank-candidate-users.mjs
    返回的按受众排序的用户+“其他”选项),绝不静默执行。当前运行用户通过
    scripts/resolve-target-user.mjs
    解析;通过
    Username
    指定用户。
  • 通过
    scripts/classify-agent-access-state.mjs
    决定
    Agent_Access
    的创建/授予;
    SetupEntityAccess
    POST请求仅包含
    ParentId
    +
    SetupEntityId
  • 执行写入操作前,通过
    scripts/classify-assignment-state.mjs
    按用户+权限集判断幂等状态。
  • needsPsl:true
    时,所选层级自身的
    LicenseId
    驱动PSL POST请求,且先于权限集分配。
  • 所有写入操作前有一个汇总确认检查点。
  • 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,
DUPLICATE_VALUE
, object/dev names) out of user-facing output.

text
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_VALUE
、对象/开发名称)。

Reference File Index

参考文件索引

FileWhen 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
文件阅读场景
references/permset-topology.md
功能/层级矩阵变更时——六个平台权限集、其层级、PSL以及
Agent_Access
/
SetupEntityAccess
Agent访问机制
references/cli-invocation.md
每个阶段——准确的
sf data query
/
sf api request rest
POST/
sf org assign permset
命令格式、
--json
规则、绝不提取令牌规则、响应包以及错误分类
references/helper-contracts.md
所有七个辅助脚本的输入/输出格式以及如何解读每个结果