service-agentforce-human-escalation-configure
service-agentforce-human-escalation-configure について
Agentforce から Omni-Channel キューを通じて有人エージェントへ引き継ぐ設定を行い、検証する Salesforce スキルです。classic と NGA の作成モデルに対応し、機械可読な判定を返すほか、本番組織への書き込みを拒否します。
主な機能
- 01有人キューの作成または既存利用
- 02QueueBased 出力ルーティングフローの設定
- 03Agentforce エスカレーション設定の検証
- 04classic と NGA の作成モデルに対応
- 05本番組織への書き込みを拒否
- 06機械可読な判定の出力
活用シーン
- 01Agentforce から有人キューへの引き継ぎ設定
- 02キューのメンバーとルーティング準備状況の確認
- 03デプロイ後のエスカレーション設定の検証
- 04評価用の失敗しきい値ディレクティブの記録
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill service-agentforce-human-escalation-configureインストール後、Claude Code で/service-agentforce-human-escalation-configureを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/escalation-thresholds.instructions.mdpackage.xmlsfdx-project.jsonassets/force-app/main/default/flows/Human_Escalation_Outbound_Flow.flow-meta.xmlreferences/classifier-contracts.mdescalation-mechanism.mdfailure-policy.mdnga-escalation.mdruntime-verification.mdscripts/classify-agent-active.mjsclassify-nga-escalation.mjsextract-outbound-route.mjspatch-escalation-surfaces.mjsverify-and-configure.shverify-escalation-config.mjsscripts/tests/__init__.py_bootstrap.pytest_escalation_contracts.py詳細
Agentforce エージェントから人間の担当者へのエスカレーションを設定する
Agentforce エージェントが Omni-Channel キューを通じて会話を人間の担当者に引き継げるように接続します。このスキルはエスカレーションに関する設定箇所を設定・検証し、機械可読な単一の JSON 判定結果を返します。開発者名ごとに冪等で、本番組織への書き込みは拒否します。単独で実行することも、より大きなセットアップフローのステージとして(エージェントの作成と有効化後に)実行することもできます。
エージェント、キュー、アウトバウンドフロー名、ルーティング対象のコンテキストオブジェクト、サービスチャネル、失敗しきい値はすべて入力値です。そのため、同じスキルであらゆるシナリオ(IT 従業員のサポート、顧客とのメッセージングなど)に対応できます。呼び出し元がシナリオ固有の識別子を渡します。
このスキルは、エージェントから人間の担当者への(アウトバウンド)エスカレーションの正式な管理元です。service-agentforce-channel-configure は、インバウンドチャネルのセットアップと同じ処理で基本的なアウトバウンドフローと connection ブロックを設定することがありますが、エスカレーション全体の設定と検証はここに委任します。
正直に定める境界 — 確定的な項目、指示による項目、実行時の項目
Agentforce のエスカレーションは、検証可能性が異なる設定箇所を組み合わせて構成されます。
- 確定的な項目(このスキルが Metadata/Data API を介して書き込み、かつ/または書き込み後に再取得して検証します):エスカレーショントピックの
canEscalate=true(GenAiPlugin);エージェントの Messaging プランナー設定箇所にあるoutboundRouteConfigs(GenAiPlannerBundle)。同じブロック内でoutboundRouteNameとoutboundRouteType=OmniChannelFlowを Messaging クラスの設定箇所に結び付けます;ActiveVersionIdが null ではない QueueBased アウトバウンドRoutingFlow;コンテキストオブジェクトに対するQueueSobject、キューに結び付けられたQueueRoutingConfig、および少なくとも 1 人の有効な人間のメンバーを持つ人間の担当者用キュー(メンバーが 0 人のキューでは人間の担当者にエスカレーションをルーティングできないため、CONFIGUREDには到達しません);再公開後に有効になったエージェント。 - 指示/ネイティブポリシー(メタデータのカウンターではなく、Agent Script の指示として作成):既定の連続 2 回の失敗というしきい値と、トピックごとのオーバーライド(例:パスワードリセットは 1 回の失敗)。失敗したターン数をカウントするメタデータフィールドはありません。しきい値は指示テキストであり、実行時の読み取りではなく、ADK 評価ルーブリックで検証します。references/failure-policy.md を参照してください。
- 実行時/手動のみ:実際の会話でのトリガー、
AgentWorkの作成、同一セッションのコンテキスト保持です。これらはヘッドレスで実行できないため、手動テストと評価ルーブリックとして記載されています。references/runtime-verification.md を参照してください。
作成モデル — クラシックと次世代(NGA)
Salesforce では 2 種類の Agentforce 作成モデルが提供されており、Phase 1b ではメタデータ型から組織がどちらをサポートしているかを自動検出します。ルーティングの基盤(キュー、QueueSobject、メンバー、QueueRoutingConfig、送信 RoutingFlow)はどちらも同一です。異なるのはエージェント側のエスカレーションの仕組みだけです。
- classic — 組織では
GenAiPluginとGenAiPlannerBundleが公開されています。エージェント側の仕組みは、トピックのcanEscalateと、プランナーの Messaging 側のoutboundRouteConfigsです。この仕組みは Phase 4 で作成され(手動編集、または任意のAUTHOR_SURFACES=1パスを使用)、Phase 7 でラウンドトリップ検証されます。 - nga — 組織では
AiAuthoringBundle(Agent Script)が公開され、GenAiPlannerBundleはありません。outboundRouteConfigsメタデータはなく、エージェント側の仕組みは、到達可能な@utils.escalateアクション(Service エージェント)またはレコード作成アクション(@utils.escalateを使用できない Employee エージェント)です。キューのルーティングは、決定論的なルーティング部分だけで処理されます。このスキルは、取得したバンドルからその仕組みを検証し、作成はagentforce-generateに委任します。 - none — どちらの仕組みも公開されていない場合 → 書き込み前にスキルはフェイルクローズします。
両方が共存する場合は、AUTHORING_MODEL_OVERRIDE=classic|nga で検出結果を固定できます。詳細なルール、Service と Employee の違い、NGA の判定結果一覧については、references/nga-escalation.md を参照してください。
対象範囲
- 対象:エスカレーショントピック(
canEscalate)の有効化、GenAiPlannerBundleの Messaging 側へのoutboundRouteConfigsの設定、バンドルされた QueueBased 送信RoutingFlowのデプロイ、人間対応キュー(コンテキストオブジェクトのQueueSobject)とそのQueueRoutingConfigの作成または既存設定の採用、失敗しきい値のディレクティブの作成、再公開と再有効化、決定論的な設定のラウンドトリップ判定。冪等な再実行が可能です。 - 対象外:エージェントの作成/有効化、受信チャネルのトランスポート(
MessagingChannelのsessionHandlerAsa)とエージェントの送信connectionブロック(service-agentforce-channel-configureの管理対象)、メッセージングチャネル自体のプロビジョニング(service-digital-engagement-channel-configure)、より広範な Omni-Channel ルーティング基盤、エスカレーションのコンテキスト外での単独キューのプロビジョニング、本番組織への書き込み。
入力
| 入力 | 位置引数 | 環境変数 | デフォルト |
|---|---|---|---|
| 組織エイリアス | 1(必須) | — | — |
| エージェントの開発者名 | 2 | AGENT_DEVELOPER_NAME | Support_Agent |
| キューの開発者名 | 3 | QUEUE_DEVELOPER_NAME | Human_Support_Queue |
| エスカレーショントピックの API 名 | 4 | ESCALATION_TOPIC_API_NAME | (未設定 — 仕組みは未検証) |
| プランナーバンドルの API 名 | 5 | PLANNER_BUNDLE_API_NAME | (未設定 — 仕組みは未検証) |
| 送信フローの開発者名 | — | FLOW_DEVELOPER_NAME | Human_Escalation_Outbound_Flow |
| 送信フローのラベル | — | FLOW_LABEL | フロー名の _ をスペースに置換 |
| コンテキストオブジェクト(ルーティング対象の sObject) | — | CONTEXT_OBJECT | MessagingSession |
| サービスチャネルの開発者名/ラベル | — | SERVICE_CHANNEL_DEV_NAME / SERVICE_CHANNEL_LABEL | sfdc_livemessage / Messaging |
| 空の場合に追加する人間対応のメンバー | — | QUEUE_MEMBER_USERNAMES | (未設定) |
| 失敗しきい値(引き継ぎ前の連続失敗回数) | — | DEFAULT_FAILURE_THRESHOLD | 2 |
| しきい値ディレクティブの作成済み状態(外部設定フラグ) | — | THRESHOLD_AUTHORED | 0 |
MessagingSession 以外のコンテキストオブジェクト(例:Case、VoiceCall)の場合は、対応する SERVICE_CHANNEL_DEV_NAME/SERVICE_CHANNEL_LABEL を指定してください。
前提条件
sfCLI がインストールされ、対象組織で認証済みであること(sf org display -o <alias>で Connected と表示されること)。すべての呼び出しで--target-org <alias>を使用します。node≥ 18 とjqが PATH に含まれていること(決定論的な分類器と JSON の組み立てに使用します)。- **エージェントが存在し、最新の
BotVersionが Active であること。**このスキルは、条件を満たさない場合は処理を中止します。 - **
MessagingSessionの引き継ぎでは、アクティブなMessagingChannelが存在すること。**見つからない場合、このスキルは処理を中止します。その他のコンテキストオブジェクトでは異なるトランスポートを使用するため、MessagingChannelは条件になりません。 - **Sandbox/trial CDO/Developer Edition の組織であること。**実際の本番顧客組織では、このスキルはエスカレーションの設定を拒否します。
前提条件を満たさない場合、sf が生のエラーを表示します。状態を捏造せず、エラーを表示して停止してください。
ワークフロー
フェーズ 0 — 本番環境への書き込みガード(必須、最初の書き込みゲート)
書き込みを行う前に、オーケストレーターが Organization(IsSandbox、TrialExpirationDate、OrganizationType)をクエリし、safe_to_write を算出します。組織が実際の本番顧客組織の場合、スキルは status: "BLOCKED" を出力して停止します。これは scripts/verify-and-configure.sh で強制されます。決して回避しないでください。
フェーズ 1 — 前提条件(読み取り専用、条件を満たさない場合は中止)
- エージェントが Active — SOQL
BotDefinition(および最新のBotVersion)を、scripts/classify-agent-active.mjs によって決定論的に分類します。見つからない場合、または非アクティブの場合は、アクティベーションのクリック手順を示してブロックします。 - トランスポートチャネルが存在する —
MessagingSessionの場合、SOQLMessagingChannel WHERE IsActive=trueを実行します。行が 0 件の場合は、service-digital-engagement-channel-configureを参照してブロックします。
フェーズ 2 — 担当者キュー(作成または既存のものを採用)とメンバー
DeveloperName でキューを解決します。存在しない場合は、標準的な Metadata API 要素の順序(doesSendEmailToMembers、name、queueSobject)で Queue をデプロイし、CONTEXT_OBJECT 用の QueueSobject を作成します。既存のキューにバインディングがない場合は、Data API でコンテキストオブジェクトを追加します。QueueRoutingConfig がなければ作成してキューにバインドし(Group.QueueRoutingConfigId)、再クエリしてバインディングが保持されたことを確認します。
**メンバー(人間へのルーティング可能性):**エスカレーションが空のキューにルーティングされないように、キューには少なくとも 1 人のアクティブな人間のメンバーが必要です。このスキルは、アクティブな User に該当する GroupMember 行を数えます。該当者がいない場合に QUEUE_MEMBER_USERNAMES(カンマ区切りのユーザー名)を渡すと、まず各ユーザー名がユーザー名の文法に合致することを検証し、アクティブな User を解決して GroupMember を POST します。その後、再度件数を確認します。キューにアクティブな人間のメンバーが 1 人もいない場合、判定結果は INCOMPLETE となり、missing に queueHasActiveDirectUserMember が含まれます(アクティブな直接ユーザーは、人間へのルーティングに必要ですが、それだけでは不十分です。Omni の権限セットとプレゼンスステータスの適格性は、実行時にのみ確認できます)。適格なメンバーがいない場合、このスキルは QueueRoutingConfig のバインディングとアウトバウンドフローのアクティベーションもスキップし、空のキューが決して接続されないようにします。より高度なメンバー調整が必要な場合は、承認済みの Omni プロビジョニングワークフローを使用してください。
フェーズ 3 — QueueBased RoutingFlow のアウトバウンドフロー
同梱のアウトバウンドフローテンプレート assets/force-app/main/default/flows/Human_Escalation_Outbound_Flow.flow-meta.xml をデプロイし、フロー名/ラベル、キューの DeveloperName、およびサービスチャネルのトークンを置き換えます。このフローは実行時に DeveloperName でキューを検索するため、移植可能で、Id がハードコードされていません。デプロイ後、FlowDefinitionView.ActiveVersionId が null でない必要があります。
フェーズ 4 — エスカレーショントピック + プランナーのアウトバウンドルート(ドキュメントに基づく編集)
この 2 つの編集には組織ごとのトピック/バンドルの検出が必要なため、明示的に作成(取得 → 編集 → デプロイ)し、トピック/バンドルの API 名を渡すとオーケストレーターが検証します。references/escalation-mechanism.md に従ってください。
- エスカレーショントピック(
GenAiPlugin)を取得し、<canEscalate>true</canEscalate>を設定して、デプロイします。 - エージェントの
GenAiPlannerBundleを取得し、Messaging プランナーサーフェスにoutboundRouteConfigs(escalationMessage、outboundRouteName=<FLOW_DEVELOPER_NAME>、outboundRouteType=OmniChannelFlow)を追加して、デプロイします。検証ツールは Messaging クラスのサーフェス上の同じブロック内で名前とタイプを組み合わせて検証します(scripts/extract-outbound-route.mjs を参照)。適切な名前があっても、無関係なブロックにOmniChannelFlowタイプが記述されているだけのバンドルでは合格しません。
フェーズ 5 — 失敗しきい値のディレクティブ(ネイティブポリシー)
失敗しきい値とトピックごとのオーバーライドは強制されるカウンターではなく、ディレクティブです。失敗したターンをカウントするメタデータフィールドはありません(references/failure-policy.md を参照)。オーケストレーターはこれらをエージェントに書き込みません。ローカルのディレクティブテンプレート assets/escalation-thresholds.instructions.md に DEFAULT_FAILURE_THRESHOLD(デフォルトは 2)を反映するだけです。3 回試行するシナリオでは、たとえば DEFAULT_FAILURE_THRESHOLD=3 を渡してください。オーケストレーターは、この値を判定の証拠として threshold.default_failures(threshold.directive_rendered を含む)に報告します。レンダリングされたディレクティブをエージェントの Agent Script に作成する作業は手動/帯域外の手順です。検証の実行時に THRESHOLD_AUTHORED=1 を設定すると、threshold.authored=true として記録されます。ディレクティブは eval で検証され、ヘッドレス実行時には読み取られないため、決定論的な判定を妨げることはありません。
フェーズ 6 — 再公開 + 再有効化
フェーズ 4/5 の編集後、エージェントを再公開して再有効化し、変更を反映させます。これらは手作業で編集する場合の手動オペレーターコマンドです。オーケストレーター自体がエージェントを公開/無効化/再有効化するのは、任意の AUTHOR_SURFACES=1 パス内だけです(「実行方法」を参照)。
sf agent validate authoring-bundle --api-name "$AGENT_DN" --target-org "$ORG" --json
sf agent publish authoring-bundle --api-name "$AGENT_DN" --target-org "$ORG" --json
sf agent activate --api-name "$AGENT_DN" --target-org "$ORG"
フェーズ 7 — 決定論的な検証(単一の JSON 判定)
オーケストレーターは決定論的な各サーフェスをラウンドトリップして証拠オブジェクトを組み立て、scripts/verify-escalation-config.mjs で次の 3 つの状態のいずれかに分類します。これにより、エスカレーションポリシーが存在しないのに完全に設定済みと誤認されることはありません。
CONFIGURED— すべての決定論的なサーフェスが満たされ、かつ失敗しきい値のディレクティブが作成されています。ROUTING_CONFIGURED_POLICY_PENDING— ルーティングとエージェントのエスカレーションサーフェスは検証済みですが、失敗しきい値のディレクティブ(thresholdAuthored)はまだ確認されていません。ディレクティブを作成し(AUTHOR_SURFACES=1/THRESHOLD_AUTHORED=1)、再実行するとCONFIGUREDになります。INCOMPLETE— 1 つ以上の決定論的なサーフェスが不足しています(missing[]を参照)。
NGA エスカレーションサーフェスの検出(scripts/classify-nga-escalation.mjs)はアドバイザリーの事前チェックです。作成バンドル内に到達可能な @utils.escalate/レコード作成アクションがあるかを照合しますが、トピックから実行時に到達可能であることを証明するものではありません。NGA サーフェスチェックに合格した場合は強い兆候として扱い、エンドツーエンドの実行時証明とは見なさないでください。フェーズ 8 の実行時手順で、ライブの引き継ぎを確認してください。
フェーズ 8 — 実行時/手動での証明(ヘッドレスの対象外)
ライブの会話で、会話トリガー、AgentWork の作成、同じセッション内でのコンテキスト維持を確認してください。references/runtime-verification.md を参照してください。
実行方法
bash scripts/verify-and-configure.sh <org-alias> \
[<agent-developer-name>] [<queue-developer-name>] \
[<escalation-topic-api-name>] [<planner-bundle-api-name>]
- 位置引数 2~5 も環境変数から読み取ります(Inputs テーブルを参照)。追加のシナリオ入力は環境変数のみです:
FLOW_DEVELOPER_NAME、FLOW_LABEL、CONTEXT_OBJECT、SERVICE_CHANNEL_DEV_NAME、SERVICE_CHANNEL_LABEL、QUEUE_MEMBER_USERNAMES。 PLAN_ONLY=1を指定すると、プレビュー(読み取り専用)を行い、書き込みの前に停止します。THRESHOLD_AUTHORED=1を指定すると、判定においてディレクティブポリシーを作成済みとして扱います。AUTHOR_SURFACES=1(任意、実行モード)を指定すると、XML を手動編集する代わりに、Agentforce のライフサイクルに従って、ドキュメント主導の 2 つのサーフェスを決定論的に作成します。agentforce-generate/references/known-issues.md(Issue 18)を参照してください:公開(コンパイル済みバンドルを再生成)→ 取得(--target-metadata-dir … --unzipを指定し、GenAiPluginトピックとGenAiPlannerBundleをメタデータ形式で取得)→ 無効化(エージェントが有効な状態ではデプロイに失敗します)→ スキーマを認識し、XSD 順に従った、損失のない、冪等なパッチ(scripts/patch-escalation-surfaces.mjs)を適用します。これにより、canEscalate=true(aiPluginUtterancesの後、descriptionの前)を設定し、outboundRouteConfigs(outboundRouteType=OmniChannelFlow、Messaging クラスのプランナーサーフェス上で<surface>の前に挿入し、アウトバウンドフローを指定)を挿入します。→--metadata-dirを指定してデプロイ → 有効化(フェイルクローズ方式。エージェントが無効なまま気づかれずに残ることはありません)→ 最新のBotVersionを再読み込みし、判定に新たに作成されたバージョンが反映されるようにします。トピックおよび/またはバンドルの API 名が必要です。また、メンバーシップゲートの通過後にのみ実行されます(空のキューを決して接続しません)。安全で XSD 順に従ったパッチ箇所を見つけられない場合、推測せずに拒否(ブロック)します。省略すると、このスキルは検証のみを行います。canEscalateおよびoutboundRouteConfigsのサーフェスは、<escalation-topic-api-name>/<planner-bundle-api-name>を渡した場合にのみ検証されます(これらは Phase 4 でドキュメント主導の編集によって作成されます)。
一般的な 2 段階のフロー:最初に実行して、キューとアウトバウンドフローを作成し、前提条件を整えます。Phase 4/5/6 のドキュメント主導の編集を行った後、トピックとバンドルの API 名、および THRESHOLD_AUTHORED=1 を指定して再実行し、CONFIGURED に到達します。
出力仕様
標準出力に単一の JSON オブジェクトを出力します:
{
"skill": "service-agentforce-human-escalation-configure",
"status": "CONFIGURED",
"agent": { "developer_name": "Support_Agent", "active": true },
"queue": { "developer_name": "Human_Support_Queue", "id": "00G...", "active_direct_user_member_count": 1 },
"outbound_flow": { "api_name": "Human_Escalation_Outbound_Flow", "active_version_id": "301..." },
"escalation_topic": "Escalate_To_Human",
"planner_bundle": "Support_Agent",
"config_verification": {
"verdict": "CONFIGURED",
"deterministicPass": true,
"directivePass": true,
"checks": [],
"missing": []
},
"next_steps": [],
"manual_actions": [],
"blocking_issue": null
}
status:すべての決定論的なサーフェスが満たされている場合はCONFIGURED、config_verification.missingが一部存在する場合はINCOMPLETE、入力/認証/本番環境/前提条件に問題がある場合はBLOCKED(終了コード 1)。- すでに設定済みの組織で再実行すると、何も変更せず
CONFIGUREDを返します(冪等)。
冪等性
既存のキュー、QueueSobject、QueueRoutingConfig、キューメンバー、およびすでに有効なアウトバウンドフローは再利用され、新たに作成されることはありません(メンバーは、キューに有効なメンバーが 0 人で、QUEUE_MEMBER_USERNAMES が指定されている場合にのみ追加されます。すでに存在するメンバーには変更を加えません)。ドキュメント主導の編集(canEscalate、outboundRouteConfigs)は、未設定の場合にのみ行われます。完全に設定済みの組織に対する 2 回目の実行では、書き込みは行われず、CONFIGURED が返されます。
分類器の仕様
上記で参照されている決定論的な Node 分類器(scripts/classify-agent-active.mjs、scripts/verify-escalation-config.mjs、scripts/extract-outbound-route.mjs、scripts/classify-nga-escalation.mjs)を調査または変更する前に、references/classifier-contracts.md を読み、それぞれの正確な入出力仕様を確認してください。
検証
このスキルまたはそのスクリプトを変更した後は、同梱のエスカレーション仕様テストを実行してください:
python3 scripts/tests/test_escalation_contracts.py