service-itsm-agentic-setup-itsm-agentforce-permset-assign について
Salesforce CLI を使い、ITSM Fulfiller の権限セットと必要なライセンスをユーザーに割り当て、プロンプトテンプレートのアクションを検証します。権限セットが組織にない場合は、AddOn の有効化確認に引き継ぎます。
主な機能
- 013 種類の Fulfiller 権限セットを検出
- 02ライセンスと権限セットを確認・割り当て
- 03実行ユーザーまたは指定ユーザーに対応
- 04プロンプトテンプレートのアクションを検証
- 05AddOn がない場合は確認に引き継ぎ
活用シーン
- 01Fulfiller Agent にプロンプトテンプレートアクションへのアクセスを付与
- 02変更前に割り当て状態を確認
- 03先に ITSM AddOn の有効化が必要かを判定
MCP 対応
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 Fulfiller ペルソナの権限セットを割り当てる(プロンプトテンプレートへのアクセス)
実行中のユーザーに、ターゲット組織上で svc_itsm_intelligence__* プロンプトテンプレートの呼び出し可能アクションを公開する、Core に同梱されたFulfiller ペルソナ権限セットのいずれかを付与します。これらのアクションは、Fulfiller NGA エージェントのスクリプトで source: / target: generatePromptResponse://... を通じて参照されています。実行中のユーザーに対してこれらの呼び出し可能アクションが /services/data/v67.0/actions/custom/generatePromptResponse に表示されない場合、Fulfiller エージェント設定スキルの Phase 6 activate 呼び出しは、サイレントな {success:false, messages:[{... "does not exist"}]} 本文を伴う HTTP 200 を返し、エージェントは利用可能になりません。このスキルは、適切な Fulfiller ペルソナ権限セット(存在する場合はその基盤となるライセンスも)を割り当てて、この不足を解消します。あるいは、組織に Fulfiller ペルソナ権限セットがまったくプロビジョニングされていない場合は、Agentforce Studio の設定/検証スキルに引き継ぎ、先に ITSM AddOn を有効にできるようにします。
3 つの Fulfiller ペルソナ権限セット、その AddOn、PSL、および付与する userPerms については、references/permset-topology.md に記載されています。これらはすべて force 名前空間の Core に同梱されたものであり、この機能にはマネージドパッケージの名前空間付き権限セットはありません。
Employee エージェントは対象外です。 Employee NGA エージェントのアクセスモデルは別個のもの(組織設定+別のペルソナレイヤー)であり、これら 3 つのペルソナ権限セットには対応しません。
すべての呼び出しは Salesforce CLI(sf) を通じて実行されます。
sf api request rest— 認証済み Connect API GET(ID の取得、読み取りの検証)。sf data query—PermissionSet(ペルソナの有無)、PermissionSetAssignment/PermissionSetLicenseAssign(冪等性)に対する SOQL。sf org assign permset— 実行中のユーザーへの権限セットの割り当て。- トークンを抽出することはありません。MCP も使用しません。
範囲
- 対象範囲内:3 つの Fulfiller ペルソナ権限セット(
IncidentFulfiller、ProblemFulfillerPermSet、ChangeRequestFulfillerPermSet)のうち、どれが組織にプロビジョニングされているかを検出すること、ユーザーに割り当てるペルソナを選んでもらうこと、既存の割り当てを確認すること、ペルソナにライセンス制限がある場合は権限セットライセンスを実行中のユーザー(または指定されたユーザー)に割り当てること、ターゲットのsvc_itsm_intelligence__*呼び出し可能アクションが後続の/actions/custom/generatePromptResponse読み取りで表示されることを検証すること。 - 対象範囲外:Employee エージェントへのアクセス(アクセスモデルが異なるため、別のスキルを使用)、ITSM AddOn またはコンテンツバンドルのインストール/有効化(
service-itsm-agentic-setup-agentforce-studio-validateに引き継ぎます)、組織レベルの Agentforce 機能トグルの有効化、権限セットの作成、Fulfiller エージェントの作成または有効化(これはservice-itsm-agentic-setup-fulfiller-agent-configureの役割です)、CMDB アクセス(service-itsm-agentic-setup-cmdb-access-assign)、ITSM 以外の一般的な権限セットの割り当て(dx-org-permission-set-assign)。
仕組み
まず読み取り専用の検出ステップを実施し、その結果に応じて 2 つの分岐に進みます。
- 分岐 A — 1 つ以上の Fulfiller ペルソナ権限セットが組織に存在する。 割り当てるペルソナをユーザーに選んでもらいます(自動選択はしません。Fulfiller が必要とするペルソナは通常 1 つだけです)。冪等に割り当てます。ペルソナにライセンス制限がある場合は、まず PSL を割り当て、続いて権限セットを割り当てます。読み戻しと、後続の
/actions/custom/generatePromptResponse読み取りで検証します。 - 分岐 B — 3 つの Fulfiller ペルソナ権限セットがいずれも組織に存在しない。 ITSM AddOn がプロビジョニングされていないため、権限セットの割り当ては何も行いません。停止し、
service-itsm-agentic-setup-agentforce-studio-validateに引き継いで、先に AddOn を有効にできるようにします。
この 2 分岐の構成には明確な理由があります。activate で "svc_itsm_intelligence__X does not exist" が返る場合、ペルソナは存在するが未割り当ての場合と、AddOn 自体が存在しない場合とで、エラーの特徴は同じです。また、activate の応答だけでは両者を判別できません。3 つのペルソナ PermissionSet 名に対する事前チェックによって、両者を区別できます。
4 つのヘルパースクリプトが、すべての決定論的な判断を担います(いずれも Bash 経由で実行、A9)。完全な入出力契約は 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の場合は、PSLA パスの代わりにセンチネル値NO-PSLを渡します。scripts/classify-action-surface.mjs—/actions/custom/generatePromptResponseのキャプチャを基に、Phase 4 の検証結果を判定します(任意の expected-actions CSV に対応)。
前提条件
sfCLI がインストールされ、対象組織に認証されていること(sf org display -o <alias>で Connected と表示されること)。すべての呼び出しで--target-org <alias>を使用します。アクセストークンを手作業で抽出したり、渡したりしないでください。- API v67.0 以降。
node≥ 18 が PATH 上にあること。
前提条件を満たさない場合、sf は認証エラーまたは 401/403/404 を返します。応答を一字一句そのまま報告し、処理を中止してください。
確認事項
会話から推測できないことだけを確認してください。
- 対象組織 —
sfのエイリアスです。未設定の場合はsf config get target-orgをデフォルトとして使用します。 - 対象ユーザー — デフォルトは実行ユーザーです(
scripts/resolve-target-user.mjsで解決)。名前を指定したユーザーに代わって割り当てるよう依頼された場合は、まずUsernameでそのユーザーを解決します。 - どの Fulfiller ペルソナか — Incident/Problem/Change。組織に実際にプロビジョニングされているペルソナ(
candidates[]に含まれるもの)だけを確認します。自動選択しないでください。複数のペルソナがプロビジョニングされていても、Fulfiller が必要とするのは通常 1 つ(例:Incident のみ)です。 - 書き込みの確認 — 権限セットライセンスを割り当てるとシートを消費し、稼働中のユーザーセッションに反映されます。書き込み前に、対象ユーザー、組織、ペルソナの permset 名を提示し、
AskUserQuestionで明示的な「はい」の回答を得てください。
ワークフロー
すべての呼び出しは sf を介して実行します。<alias> は対象組織に置き換えてください。
Phase 1 — 読み取り:この組織にプロビジョニングされている Fulfiller ペルソナの permset はどれか?
-
既知の 3 つの Fulfiller ペルソナの DeveloperName を対象に、
PermissionSetをクエリします。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(3 つすべての
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"(1 つ以上のペルソナが存在)⇒ Phase 2 に進みます。personasFoundの一覧をAskUserQuestionでユーザーに提示し、選択されたペルソナを取得します。そのId、LicenseId、needsPslを記録してください。これらを基に、Phase 2b/2d で PSL にアクセスするかどうかを決めます。verdict:"HAND-OFF"(3 つのペルソナのいずれも存在しない)⇒ この組織では Phase 2 を実行できません。Phase 3(分岐 B の引き継ぎ)に進みます。verdict:"CANNOT-CONFIRM"(クエリに失敗)⇒ CLI のエラーを一字一句そのまま提示し、処理を中止します。
フェーズ 2 — パスを割り当てる(ブランチ A)
2a. 対象ユーザーを解決します。 ID 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. 書き込み前の確認チェックポイント(必須)。 対象ユーザー、組織、ペルソナの permset 名を提示し、AskUserQuestion を通じて明示的な「yes」を求めます。「no」の場合は停止し、書き込みを行わずに現在の状態を報告します。
2d. 割り当て — 順序は選択したペルソナの needsPsl によって異なります。
needsPsl:true— まず/sobjects/PermissionSetLicenseAssignに PSL を POST し、その後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 シートがないため、permset のみを割り当てるのが正しく、これで完了です。)防御的に保持: 現在、提供されているすべてのペルソナは 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"を返した場合、この組織には 3 つの Fulfiller ペルソナ用 permset がどれも存在しません。ITSM AddOn がプロビジョニングされていません。この状態では permset の割り当ては何も行いません。AskUserQuestionを通じて、次の検出結果を提示します。「この組織には、Fulfiller ペルソナの権限セット(Incident、Problem、Change)がプロビジョニングされていません。まだ存在しないアクションへのアクセスを permset で付与することはできません。
service-itsm-agentic-setup-agentforce-studio-validateを実行して、有効化が必要な AddOn を診断しますか?」(選択肢:はい、準備状況を確認する / いいえ、ここで停止する)。- はいの場合:
service-itsm-agentic-setup-agentforce-studio-validateに委任し、設定/バンドルデプロイ用スキルを推奨させます。 - いいえの場合:停止し、現在の状態(ペルソナがプロビジョニングされておらず、割り当てできない)を報告します。書き込みは行いません。
- はいの場合:
フェーズ 4 — 検証
-
書き込みを行ったかスキップしたかにかかわらず、
/actions/custom/generatePromptResponseを再読み込みし、ヘルパーを使って分類します(文章の grep による分類は行いません — 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]ヘルパーは
{ 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以外のエラーが返されました。生のエラーを報告します。
ルール/制約
| 制約 | 理由 |
|---|---|
権限セットへの書き込みを行う前に、3 つの固定値 PermissionSet.Name によって Fulfiller ペルソナの存在を検出します | 失敗時のシグネチャ(有効化時に「action does not exist」と表示される)は、AddOn が存在しない場合と権限セットが割り当てられていない場合で同一です。両者を区別できるのは事前チェックのみです。3 つのペルソナは force 名前空間に含まれているため、NamespacePrefix で絞り込んでも返されません |
| 割り当てるペルソナをユーザーに確認します。自動選択はしません | Fulfiller が必要とするペルソナは通常 1 つだけです(例:Incident)。返された最初の行を自動的に割り当てると、過剰な権限付与になります |
| すべての判断はヘルパースクリプトで行い、文章の解釈に頼りません | 割り当て/冪等性のロジックは決定的ですが、文章の解釈は決定的ではありません(A9) |
選択したペルソナの needsPsl:true の場合に限り、権限セットより先に PSL を割り当てます | 権限セットはライセンスに紐付いているため、割り当てが反映されるには、先にライセンスシートを確保する必要があります。選択したペルソナに LicenseId がない場合、needsPsl:false となり、PSL の POST は完全に省略されます |
needsPsl は選択したペルソナの LicenseId から、行ごとに読み取ります。名前空間全体の PSL クエリから取得してはいけません | 同じ組織内でも、ペルソナによってライセンスの構成が異なる場合があります。名前空間全体の PSL にフォールバックすると、誤った PermissionSetLicenseAssign を POST することになります |
実行ユーザーの Id は scripts/resolve-target-user.mjs で解決します。identity URL を文章から解析してはいけません | identity URL のセグメント形式(005…、15 文字または 18 文字)は厳密なルールです。分類スクリプトが検証し、安全側に失敗します |
フェーズ 4 のアクション対象範囲は scripts/classify-action-surface.mjs で分類します。レスポンスを文章から grep してはいけません | Verify は SUCCESS と VERIFY-INCONCLUSIVE の報告を判定するためのゲートです。この判断は決定的でなければなりません |
PSL の POST で 400 DUPLICATE_VALUE が返された場合は成功として扱います | これは、ユーザーにすでに割り当てられていることを意味します。冪等な状態であり、エラーではありません |
| 権限セットの作成や編集は行いません | このスキルで行うのは、標準の Fulfiller ペルソナ権限セットの割り当てのみです。権限セットの作成は対象外です |
| AddOn のインストールや、組織レベルの Agentforce 機能の切り替えは行いません | これは service-itsm-agentic-setup-agentforce-studio-validate/-configure の対象範囲です。このスキルは引き継ぎを行うものであり、有効化はしません |
書き込み後は /actions/custom/generatePromptResponse で検証します。POST の戻りコードだけを信頼してはいけません | 割り当てが成功しても、対象のアクション範囲に Fulfiller テンプレートが必要とするものが含まれていない場合があります(ペルソナの誤り、キャッシュなど) |
| フェーズ 2d の前に、書き込みの確認を求めます | 権限セットの割り当てはライセンスシートを消費し、稼働中のユーザーセッションに反映されます |
| アクセストークンを取り出してはいけません | sf api request rest/sf data query/sf org assign permset を使用します。これらは CLI に保存されたセッションを使用します |
| CLI のレスポンスに含まれるエラーテキストを正確に報告します | サポート担当者が障害を診断できるようになります |
検証チェックリスト
- ペルソナの利用可否は、クエリ出力の文章をスキャンして判断するのではなく、
scripts/classify-permset-availability.mjsを使い、固定された3つのペルソナ名に照らして分類しました。 -
personasFound[]からペルソナを選ぶようユーザーに求めました。自動選択はしていません。 - 対象ユーザー Id は
scripts/resolve-target-user.mjsで解決しました。ID URL の文章を分割して取得していません。 - 選択されたペルソナの
needsPslに基づいて Phase 2b/2d を実施しました。値がtrueの場合は PSL SOQL と POST を実行し、falseの場合は省略しました。 - PSL POST に使用した
permsetLicenseIdは、選択されたペルソナ自身のLicenseIdから取得しました。名前空間全体を対象にしたクエリからのフォールバックは使用していません。 - Branch A:書き込みを行う前に
sf data queryで既存の割り当てを読み取り、scripts/classify-assignment-state.mjsで分類しました(needsPsl:falseの場合はNO-PSLセンチネルを使用)。 - Branch A:Phase 2c のチェックポイントで、ユーザーが書き込みを確認しました。
- Branch A かつ
needsPsl:true:権限セットを割り当てる前に PSL を POST しました。 - PSL POST での
DUPLICATE_VALUEは失敗ではなく成功として扱いました。 - Branch B:書き込みは試みず、
service-itsm-agentic-setup-agentforce-studio-validateへの引き継ぎを提示しました。 - Phase 4 の検証は
scripts/classify-action-surface.mjsで分類しました。このヘルパーが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>
内部向けの専門用語(レコード Id、HTTP ステータスコード、FUNCTIONALITY_NOT_ENABLED、DUPLICATE_VALUE、オブジェクト名/開発者名、sf api request rest)をユーザー向けの出力に含めないでください。
参考ファイル一覧
| ファイル | 読み込むタイミング |
|---|---|
references/permset-topology.md | ペルソナ一覧を変更するとき。Core に同梱されている3つの Fulfiller 権限セット、その AddOns/PSL/userPerms、固定検索の検出クエリについて |
references/cli-invocation.md | すべてのフェーズ。sf api request rest/sf data query/sf org assign permset の正確な呼び出し形式、トークンを抽出しないルール、レスポンスのエンベロープについて |
references/helper-contracts.md | 4つのヘルパースクリプト(classify-permset-availability.mjs、resolve-target-user.mjs、classify-assignment-state.mjs、classify-action-surface.mjs)の入力/出力形式と、各判定の解釈について |