关于 service-itsm-agentic-setup-itsm-agentforce-permset-assign
该 skill 通过 Salesforce CLI 为目标用户分配 ITSM Fulfiller 角色权限集及所需许可证,并验证提示模板操作是否可用。若组织未配置相关角色权限集,则转交 AddOn 配置检查。
主要功能
- 01检测三类 Fulfiller 权限集
- 02检查并分配许可证与权限集
- 03支持运行用户或指定用户
- 04验证提示模板操作是否可用
- 05未配置时转交 AddOn 检查
适用场景
- 01为 Fulfiller Agent 配置提示模板操作访问权限
- 02检查分配状态并避免重复写入
- 03确认组织是否需要先启用 ITSM AddOn
MCP 相关
该 skill 使用 Salesforce CLI(sf)执行操作,不使用 MCP。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill service-itsm-agentic-setup-itsm-agentforce-permset-assign安装后在 Claude Code 中输入/service-itsm-agentic-setup-itsm-agentforce-permset-assign确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/cli-invocation.mdhelper-contracts.mdpermset-topology.mdscripts/classify-action-surface.mjsclassify-assignment-state.mjsclassify-permset-availability.mjsresolve-target-user.mjs详细介绍
分配 ITSM 执行者角色权限集(提示词模板访问权限)
为当前运行用户授予 Core 随附的某个执行者角色权限集,使其能够在目标组织上使用 svc_itsm_intelligence__* 提示词模板可调用操作——执行者 NGA Agent 脚本会通过 source: / target: generatePromptResponse://... 引用这些操作。如果当前运行用户无法通过 /services/data/v67.0/actions/custom/generatePromptResponse 获取这些可调用操作,执行者 Agent 配置技能的 Phase 6 activate 调用就会返回 HTTP 200,但响应正文会静默包含 {success:false, messages:[{... "does not exist"}]},导致 Agent 无法使用。此技能会通过分配正确的执行者角色权限集(以及在存在时分配其关联许可证)来弥补这一缺口;如果组织上完全未配置执行者角色权限集,则转交给 Agentforce Studio 配置/验证技能,以便先启用 ITSM AddOn(s)。
三个执行者角色权限集、对应的 AddOn、PSL 及其授予的 userPerms 记录在 references/permset-topology.md 中。它们均由 Core 随附,命名空间为 force——此功能没有托管软件包命名空间下的权限集。
Employee Agent 不在范围内。 Employee NGA Agent 的访问模型独立存在(基于组织偏好设置和不同的角色层),与这三个角色权限集无关。
每次调用都会通过 Salesforce CLI(sf) 执行:
sf api request rest— 经过身份验证的 Connect API GET 请求(身份信息、验证读取权限)。sf data query— 对PermissionSet执行 SOQL 查询(检查角色是否存在),对PermissionSetAssignment/PermissionSetLicenseAssign执行查询(确保操作幂等)。sf org assign permset— 为当前运行用户分配权限集。- 从不提取令牌;不使用 MCP。
范围
- 范围内:检测组织上配置了三个执行者角色权限集(
IncidentFulfiller、ProblemFulfillerPermSet、ChangeRequestFulfillerPermSet)中的哪些;让用户选择要分配的角色;检查现有分配;为当前运行用户(或指定用户)分配权限集许可证(角色受许可证限制时)和权限集;通过后续读取/actions/custom/generatePromptResponse验证目标svc_itsm_intelligence__*可调用操作是否已显示。 - 范围外:Employee Agent 访问权限(访问模型不同,使用不同技能);安装/启用 ITSM AddOn(s) 或内容捆绑包(转交给
service-itsm-agentic-setup-agentforce-studio-validate);启用组织级 Agentforce 功能开关;创建权限集;创建或激活执行者 Agent(由service-itsm-agentic-setup-fulfiller-agent-configure负责);CMDB 访问权限(service-itsm-agentic-setup-cmdb-access-assign);通用的非 ITSM 权限集分配(dx-org-permission-set-assign)。
机制
首先执行只读检测步骤,然后按结果进入以下两个分支:
- 分支 A — 组织上存在一个或多个执行者角色权限集。 询问用户要分配哪个角色(不要自动选择——执行者通常只需要一个角色)。幂等分配:如果角色受许可证限制,先分配 PSL,再分配权限集;通过回读和后续读取
/actions/custom/generatePromptResponse进行验证。 - 分支 B — 组织上不存在三个执行者角色权限集中的任何一个。 ITSM AddOn(s) 尚未配置;分配权限集不会产生任何效果。停止并转交给
service-itsm-agentic-setup-agentforce-studio-validate,以便先启用 AddOn(s)。
有意采用这两个分支——activate 时出现“svc_itsm_intelligence__X does not exist”这一失败特征,无论角色已存在但尚未分配,还是 AddOn 完全缺失,表现都相同,无法仅凭 activate 响应加以区分。预先检查这三个角色 PermissionSet 名称,才能判明具体情况。
四个辅助脚本(均通过 Bash 调用)负责所有确定性判断(A9)。完整的 I/O 契约见 references/helper-contracts.md;下面汇总工作流级别的用法:
scripts/classify-permset-availability.mjs— 判断分支 A 或 B,并确定每种角色的needsPsl标记。返回完整的candidates[](组织中实际存在的角色),供调用方提示用户选择。scripts/resolve-target-user.mjs— 从 API 根目录的identityURL 中提取005…格式的运行用户 Id。遇到任何格式错误时都会安全失败。scripts/classify-assignment-state.mjs— 判断幂等性;如果所选角色的needsPsl:false,则用哨兵值NO-PSL代替 PSLA 路径。scripts/classify-action-surface.mjs— 根据/actions/custom/generatePromptResponse捕获结果给出 Phase 4 验证判定(可选提供预期操作 CSV)。
前置条件
- 已安装
sfCLI,且已通过身份验证连接到目标组织(sf org display -o <alias>显示 Connected)。所有调用均使用--target-org <alias>;切勿手动提取或传递访问令牌。 - API v67.0+。
- PATH 中有
node≥ 18。
如果任何前置条件不满足,sf 会返回身份验证错误或 401/403/404;请原样报告原始响应并停止。
澄清问题
只询问无法从对话中推断的信息:
- 目标组织 —
sf别名。如果未设置,默认使用sf config get target-org。 - 目标用户 — 默认使用运行用户(通过
scripts/resolve-target-user.mjs解析)。如果用户要求代表指定用户分配,则先通过Username查找该用户。 - 要使用哪种 Fulfiller 角色? Incident / Problem / Change。只询问组织中实际已配置的角色(来自
candidates[])。不要自动选择——即使组织中已配置其他角色,Fulfiller 通常也只需要一种角色(例如 Incident)。 - 确认写入操作 — 分配权限集许可证会占用一个名额,并会对当前用户会话立即生效。请向用户显示目标用户、组织和角色权限集名称,并在写入前通过
AskUserQuestion要求用户明确回复 “yes”。
工作流
所有调用均通过 sf 进行;将 <alias> 替换为目标组织。
Phase 1 — 读取:此组织中配置了哪些 Fulfiller 角色权限集?
-
查询
PermissionSet,查找三个已知的 Fulfiller 角色 DeveloperName:sf data query \ -q "SELECT Id, Name, Label, LicenseId FROM PermissionSet WHERE Name IN ('IncidentFulfiller','ProblemFulfillerPermSet','ChangeRequestFulfillerPermSet')" \ --target-org <alias> --json > /tmp/itsm-personas.json 2>/tmp/itsm-personas.err || true(这三项的
PermissionSet命名空间均为force——不要按NamespacePrefix进行筛选。) -
分类:
node "<skill_dir>/scripts/classify-permset-availability.mjs" /tmp/itsm-personas.json分类器会打印
{ personasFound, personasMissing, candidates, verdict, reasons },其中每一行candidates[]的格式为{Id, Name, Label, LicenseId, needsPsl}:verdict:"ASSIGN"(至少存在一种角色)⇒ 继续执行 Phase 2。通过AskUserQuestion向用户展示personasFound列表并让其选择角色;记录其Id、LicenseId和needsPsl——这些信息决定 Phase 2b/2d 是否需要操作 PSL。verdict:"HAND-OFF"(三个角色均不存在)⇒ 此组织无法执行 Phase 2;转到 Phase 3(分支 B 移交)。verdict:"CANNOT-CONFIRM"(查询失败)⇒ 原样显示原始 CLI 错误;停止。
阶段 2 — 分配路径(分支 A)
2a. **解析目标用户。**读取身份 URL,然后通过解析器提取用户 Id(不要手动解析 URL;不要使用 USER_ID()——仅限 Apex,REST 会拒绝;不要依赖 /chatter/users/me——Chatter 关闭时会返回 403):
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
解析器会输出 { userId, identity, verdict, reasons }。当 verdict:"RESOLVED" 时,将 userId 用作当前操作用户;当 verdict:"CANNOT-CONFIRM" 时,原样呈现原因并停止——不要猜测。
如果用户要求代替某个指定用户进行分配,则按 Username 解析:
sf data query \
-q "SELECT Id, Username, Name, IsActive FROM User WHERE Username = '<username>'" \
--target-org <alias> --json > /tmp/user-lookup.json 2>/tmp/user-lookup.err || true
2b. **幂等性读取。**查询目标用户与所选角色的 Id 对应的 PermissionSetAssignment(SOQL 格式见 references/cli-invocation.md),然后根据所选角色的 needsPsl 进行分支:
-
needsPsl:true— 查询目标用户与该角色LicenseId对应的PermissionSetLicenseAssign,然后分类:node "<skill_dir>/scripts/classify-assignment-state.mjs" /tmp/psa-existing.json /tmp/psla-existing.json -
needsPsl:false— 完全跳过 PSLA 查询;传入哨兵值:node "<skill_dir>/scripts/classify-assignment-state.mjs" /tmp/psa-existing.json NO-PSL
分类器会输出 { permsetAssigned, licenseAssigned, needsWrite, verdict, reasons }。如果 needsWrite:false ⇒ 转到阶段 4(仅验证)。否则继续执行阶段 2c。
2c. **写入确认检查点(必需)。**展示目标用户、组织和角色权限集名称,并通过 AskUserQuestion 要求用户明确回答“是”。如果回答“否”,则停止并报告当前状态,不进行任何写入。
2d. 分配 — 顺序取决于所选角色的 needsPsl:
needsPsl:true— 先将 PSL POST 到/sobjects/PermissionSetLicenseAssign,然后运行sf org assign permset --name <permsetName> --on-behalf-of <userId>。未先分配 PSL 就分配权限集,会导致分配记录保留,但其许可证不会生效。具体调用格式见references/cli-invocation.md。needsPsl:false— 完全跳过 PSL POST;仅运行sf org assign permset。(其PermissionSet没有关联LicenseId的角色不受许可证限制——没有需要占用的 PSL 席位,因此仅分配权限集就是正确且完整的写入。)_防御性保留:_目前所有已发布角色都有 PSL 支持(needsPsl按行根据LicenseId推导),因此当前已发布数据不会触发此false分支及其NO-PSL连接;保留此分支是为了兼容未来不带关联LicenseId的PermissionSet角色。
响应处理:
- POST 返回
201/sf org assign permset返回success:true⇒ 已分配。 - PSL POST 返回
400 DUPLICATE_VALUE⇒ 用户已拥有该许可证;视为成功,不是错误。 - PSL POST 返回
400 INSUFFICIENT_ACCESS/ 席位耗尽错误 ⇒ 停止此次写入;告知用户 PSL 没有可用席位。
阶段 3 — 移交路径(分支 B:未配置 Fulfiller 角色)
-
当阶段 1 返回
verdict:"HAND-OFF"时,当前组织不存在三个 Fulfiller 角色权限集中的任何一个——尚未配置 ITSM AddOn。处于此状态时,权限集分配操作不会产生任何效果。通过AskUserQuestion呈现发现结果:“此组织未配置任何 Fulfiller 角色权限集(Incident、Problem、Change)——无法通过权限集授予对尚不存在操作的访问权限。是否运行
service-itsm-agentic-setup-agentforce-studio-validate,以诊断需要启用哪个 AddOn?”(选项:是,运行就绪检查 / 否,到此为止)。- 选择是:委派给
service-itsm-agentic-setup-agentforce-studio-validate,并让其建议 configure/bundle-deploy 技能。 - 选择否:停止并报告当前状态(未配置角色,无法分配)——不进行任何写入。
- 选择是:委派给
阶段 4 — 验证
-
无论是写入还是跳过,都要重新读取
/actions/custom/generatePromptResponse,并通过 helper 分类(绝不能通过搜索文本分类 — A9)。CSV 格式和两种调用形式见references/helper-contracts.md/references/cli-invocation.md:sf api request rest "/services/data/v67.0/actions/custom/generatePromptResponse" \ --method GET --target-org <alias> > /tmp/generate-prompt-response.json 2>/tmp/generate-prompt-response.err || true node "<skill_dir>/scripts/classify-action-surface.mjs" /tmp/generate-prompt-response.json [expectedActions-csv]helper 会输出
{ present, missing, totalItsmActionsSeen, verdict, reasons }。若结果为SURFACED,则进入阶段 5;若成功分配后结果为PARTIAL/MISSING,则告知用户写入成功,但这些操作未显示 — 可能需要刷新会话,或当前角色不正确。不得谎报成功。若结果为CANNOT-CONFIRM,则原样展示原因。
阶段 5 — 汇总结论
- 报告以下其中一项:
- ASSIGNED — 分支 A 已写入,验证确认目标操作已显示。
- ALREADY-ASSIGNED — 分支 A 发现
needsWrite:false;验证确认目标操作已显示。(分配已完成;无需写入。) - HAND-OFF — 分支 B;未配置 Fulfiller 角色。已指出后续技能。
- VERIFY-INCONCLUSIVE — 写入已完成,但验证读取未显示预期的操作集。原样展示观察到的状态;不得报告成功。
- FAILED — 阶段 2d 的任何写入返回了
DUPLICATE_VALUE以外的错误。报告原始错误。
规则 / 约束
| 约束 | 原因 |
|---|---|
在写入任何权限集之前,通过三个固定的 PermissionSet.Name 值检测是否存在 Fulfiller 角色 | 激活时出现的失败特征(“action does not exist”)对于 AddOn 缺失和未分配权限集的情况完全相同;只有预检查才能区分二者。这三个角色由 force 命名空间随 Core 一同提供,因此 NamespacePrefix 筛选永远不会返回它们 |
| 询问用户要分配哪个角色——绝不自动选择 | Fulfiller 通常只需要一个角色(例如 Incident)。自动分配返回的第一行会导致授权过度 |
| 所有决策均由辅助脚本作出,绝不通过文字描述作出 | 分配和幂等逻辑是确定性的;文字解读则不是(A9) |
仅当所选角色的 needsPsl:true 时,先分配 PSL,再分配权限集 | 权限集由许可证支持;许可证席位必须先被占用,分配才会生效。所选角色没有 LicenseId 时,needsPsl:false,会完全跳过 PSL POST |
按行从所选角色的 LicenseId 读取 needsPsl——绝不通过命名空间范围的 PSL 查询读取 | 同一 org 上不同角色的许可证形态可能不同;若回退到命名空间范围的 PSL,会 POST 错误的 PermissionSetLicenseAssign |
使用 scripts/resolve-target-user.mjs 解析当前运行用户的 Id——绝不通过文字解析 identity URL | identity URL 的路径段格式(005…,15 或 18 个字符)是硬性规则;分类器会验证并在验证失败时安全终止 |
使用 scripts/classify-action-surface.mjs 对 Phase 4 的操作面进行分类——绝不通过 grep 响应中的文字进行判断 | Verify 是报告 SUCCESS 还是 VERIFY-INCONCLUSIVE 的关卡;决策必须是确定性的 |
将 PSL POST 返回的 400 DUPLICATE_VALUE 视为成功 | 这表示该用户已拥有该分配——这是幂等结果,不是错误 |
| 绝不创建或编辑权限集 | 此技能仅分配标准 Fulfiller 角色权限集;编写权限集不在范围内 |
| 绝不安装 AddOn/绝不切换 org 级别的 Agentforce 功能 | 这属于 service-itsm-agentic-setup-agentforce-studio-validate / -configure 的范围;此技能负责移交,不负责启用 |
写入后通过 /actions/custom/generatePromptResponse 验证——绝不只相信 POST 返回码 | 分配可能成功,但目标操作面仍可能不包含 Fulfiller 模板所需的内容(角色错误、缓存) |
| 在 Phase 2d 之前设置写入确认检查点 | 权限集分配会占用一个许可证席位,并对实时用户会话生效 |
| 绝不提取访问令牌 | 使用 sf api request rest / sf data query / sf org assign permset——这些命令使用 CLI 中存储的会话 |
| 准确报告 CLI 响应中的错误文本 | 便于支持人员诊断故障 |
验证清单
- 通过
scripts/classify-permset-availability.mjs根据三个固定的 persona Name 判定 persona 是否可用,绝不扫描查询输出中的文本。 - 请用户从
personasFound[]中选择一个 persona,不得自动选择。 - 通过
scripts/resolve-target-user.mjs解析目标用户 Id,绝不通过拆分身份 URL 来获取。 - 所选 persona 的
needsPsl决定 Phase 2b/2d 的处理方式:值为true时执行 PSL SOQL 查询和 POST,值为false时跳过。 - PSL POST 使用的
permsetLicenseId来自所选 persona 自身的LicenseId,绝不使用命名空间范围查询中的备用值。 - 在 Branch A 上:写入前通过
sf data query读取现有分配,并由scripts/classify-assignment-state.mjs判定状态(needsPsl:false时使用NO-PSLsentinel)。 - 在 Branch A 上:用户在 Phase 2c 检查点确认了写入操作。
- 在 Branch A 且
needsPsl:true时:先 POST PSL,再分配权限集。 - 将 PSL POST 返回的
DUPLICATE_VALUE视为成功,而非失败。 - 在 Branch B 上:未尝试写入;已提供移交给
service-itsm-agentic-setup-agentforce-studio-validate的选项。 - Phase 4 验证通过
scripts/classify-action-surface.mjs判定;只有 helper 返回verdict:"SURFACED"时才能报告 ASSIGNED。 - 报告汇总判定结果(ASSIGNED / ALREADY-ASSIGNED / HAND-OFF / VERIFY-INCONCLUSIVE / FAILED)。
输出格式
ITSM Fulfiller Persona Permset Assignment (via service-itsm-agentic-setup-itsm-agentforce-permset-assign)
Org: <org-alias> (API v67.0)
Target user: <username> (<userId>)
Persona: <Incident | Problem | Change>
PermSet: <DeveloperName>
Personas provisioned on org ...... <comma-separated list | none>
Existing PSL assignment .......... <yes | no | n/a>
Existing permset assignment ...... <yes | no>
Write PSL ........................ <succeeded | already-had | skipped | FAILED>
Write permset .................... <succeeded | already-had | skipped | FAILED>
Verify actions surface ........... <yes | partial | no>
Verdict: ASSIGNED | ALREADY-ASSIGNED | HAND-OFF | VERIFY-INCONCLUSIVE | FAILED
Reason: <plain-language explanation, or empty on success>
Next steps:
- <If ASSIGNED / ALREADY-ASSIGNED: "Re-run service-itsm-agentic-setup-fulfiller-agent-configure — the invocable actions should now surface, and the activate call will succeed.">
- <If HAND-OFF: "No Fulfiller persona is provisioned on this org. Run service-itsm-agentic-setup-agentforce-studio-validate to identify which AddOn needs enabling.">
- <If VERIFY-INCONCLUSIVE: list the observed state verbatim; a session refresh or a different persona may be required>
- <If FAILED: list the observed error verbatim + remediation>
面向用户的输出中不得包含内部术语(record Id、HTTP 状态码、FUNCTIONALITY_NOT_ENABLED、DUPLICATE_VALUE、对象/开发者名称、sf api request rest)。
参考文件索引
| 文件 | 何时阅读 |
|---|---|
references/permset-topology.md | 每当 persona 列表发生变化时——三个随 Core 提供的 Fulfiller 权限集、它们的 AddOns/PSLs/userPerms,以及固定查找发现查询 |
references/cli-invocation.md | 每个阶段——确切的 sf api request rest / sf data query / sf org assign permset 调用格式、绝不提取令牌的规则、响应封装结构 |
references/helper-contracts.md | 四个 helper 脚本(classify-permset-availability.mjs、resolve-target-user.mjs、classify-assignment-state.mjs、classify-action-surface.mjs)的输入/输出格式,以及如何解读各项判定结果 |