【必読】なぜ今、Aura ではなく LWR を選ぶべきなのか?

Agentforceから有人オペレーターへのシームレスな引き継ぎ:カスタムEscalationトピックを用いたエスカレーション実装ガイド

カスタマーサービスの領域は今、従来のルールベースのチャットボットから、自律的に思考して行動するAIエージェントの時代へと劇的な進化を遂げています。Salesforceが提供するAgentforceは、このパラダイムシフトを牽引する存在であり、顧客対応をより柔軟で適応力の高いものへと変革します

しかし、どれほどAIが賢くなっても、すべての問い合わせを自己完結できるわけではありません。複雑な契約変更、感情的になっている顧客への対応、VIP顧客からの特別な要望など、人間の「共感力」と「専門的な判断」が不可欠な場面は必ず存在します 。従来のボットシステムでは、AIが処理の限界に達した瞬間に単なる「緊急回避(フェイルオーバー)」としてオペレーターへ会話が投げ出されることが多く、結果として顧客に同じ説明を二度手間させ、フラストレーションを与えてしまう課題がありました

AgentforceとAgentforce Service (Service Cloud)のアーキテクチャが目指すのは、このような分断された体験ではありません。AIエージェントが単なる自動応答ツールではなく、優秀な「ゲートキーパー」として機能することが重要です 。ユーザーの意図を汲み取り、事前情報の収集や、会話履歴を要約したケースレコードの作成といった「事前準備」を完了させた上で、最適な人間のオペレーターにバトンを渡す「ダイナミックエスカレーション」こそが、これからのカスタマーサポートの鍵を握ります 。

エスカレーションを単なるエラー対応ではなく、コンテキストが維持された質の高い「戦略的な送客」へと昇華させることで、放棄呼を減らし、顧客満足度を大幅に向上させることが可能になります

本記事では、Salesforceの「拡張チャット v2(Enhanced Chat v2)」環境において、Agentforceエージェントから有人オペレーターへ会話をシームレスに転送する具体的な実装方法を解説します。
標準のエスカレーション機能に頼るのではなく、「カスタムトピック」とオムニチャネルフローを組み合わせることで、自社のビジネスロジックに沿った理想的なハンドオフを構築する手順を画像を組み合わせながらステップ・バイ・ステップで見ていきましょう。

LWRって何?どんなメリットがあるの?
そんな疑問を解決するにはまずは以下の記事をご覧ください。
Salesforce LWRとは? Experience Cloudの次世代ランタイムを徹底解説

Step 0: 人間オペレーター転送のための事前準備

人間側が転送を受け入れるための事前準備をしておきます。

ルーティング設定

有人対応用のルーティング設定を作成します。
[設定] > [ルーティング設定] から Human というルーティングを、優先度 2 で作成します。

キュー設定

続いて、有人対応用のキューを作成します。
[設定] > [キュー] から、先ほど作成したルーティング Human を指定して新規キューを作成します。
オブジェクトに「メッセージングセッション」を選択し、ユーザーを含めておいてください。

Service Cloud ユーザー権限を付与

キューに含めたユーザーに対して、Service Cloud ユーザー の権限を付与します。
{設定} > [ユーザー] から、対象のユーザーを編集して、「Service Cloud ユーザー」にチェックを入れて保存します。

プレゼンス状況のアクセス有効化

キューに含めたユーザーに割り当たっているプロファイルまたは権限セットで、「サービスプレゼンス状況のアクセスを有効化」にオンラインのプレゼンスを含めます。

アプリケーションマネージャー設定

[設定] > [アプリケーションマネージャー] からコンソールのアプリ設定を開き、ユーティリティ項目に Omni-Channel を追加します。

Step 1: 感情分析プロンプトテンプレートの作成

[Agentforce スタジオ] > [プロンプトテンプレート] から「プロンプトビルダー」を開き、プロンプトテンプレートを作成します。

  1. [新規プロンプトテンプレート] ボタンを押す。
  2. プロンプトテンプレート種別に「Flex」を選び、情報を入力して [次へ]
    • プロンプトテンプレート名: AnalyzeCustomerSentiment
    • 説明: 顧客の発話を分析して数値スコアを返す。
    • 入力値: utterance (utterance) 自由テキスト

次に、プロンプトを書きましょう。

## 指示
以下の顧客の発話を分析し、最もネガティブな状態を0.0、フラットな状態を0.5、最もポジティブな状態を1.0として、数値(例: 0.15)のみを出力してください。分析の思考を正確に行う必要がありますが、テキストによる説明は一切含めないでください。
なお、顧客が伝えている発生事象のポジティブ/ネガティブではなく、感情のポジティブ/ネガティブを分析してください。

## 顧客の発話
{!$Input:utterance}
  • 新規プロンプトテンプレート
  • 情報を入力
  • 動作確認

最後に有効化します。

Step 2: フローの作成

①自動起動フローの作成

Agentforce から呼び出すフローは、画面を持たない 「自動起動フロー (Autolaunched Flow)」 である必要があります。

  • 名前: AnalyzeCustomerSentiment
  • 説明: 顧客の発話を受け取り、感情スコアを返す。
  • 入力変数: input_Text_Utterance (テキスト / 入力で使用可能)
  • 出力変数: output_Number_SentimentScore (数値(1) / 出力で使用可能)
  • 数式変数: fx_Numeric_QuantifiedSentimentScore (数値(1))
  • 入力変数
  • 出力変数
  • 数式変数
VALUE({!AnalyzeCustomerSentiment.promptResponse})

フローのロジック構築

  1. プロンプトテンプレート アクション:
    • プロンプトテンプレート: AnalyzeCustomerSentiment
    • 入力値: utterance = {!input_Text_Utterance}
  2. 割り当て:
    • プロンプトテンプレートAnalyzeCustomerSentimentから返却される感情スコアを出力変数に数値変換して割り当てます。
    • {!output_Number_SentimentScore} 次の文字列に一致する {!fx_Numeric_QuantifiedSentimentScore}
  • アクション
  • 割り当て
DXforce Point

Q. どうしてAgentforceから直接プロンプトテンプレートを呼び出さずにフローを経由しているの?

A. Agentforceからプロンプトテンプレートを直接呼び出すのではなく、一度フロー(Autolaunched Flowなど)を経由させるアーキテクチャを採用する主な理由は、出力データの厳密な型変換と、プロンプトを実行する前に必要なデータの事前取得(前処理)を確実に行うためです。

  1. データ型の変換と成形(テキストから数値へのキャスト)
    プロンプトテンプレートがLLMから受け取って出力する結果(Prompt Response)は、基本的に「テキスト(String)型」として返されます。 今回のセンチメント分析の例では、Agent Script内で if @variables.customer_sentiment_score < 0.3: という不等号を使った決定論的な数値比較を行っています。LLMが “0.15” と出力したとしても、それがテキスト型のままだとスクリプト側で正しく条件判定できないリスクがあります。そのため、フローを経由して数式等で明示的に「数値型(Number)」に変換し、Agent Scriptがそのまま安全に評価できる形に成形して返す必要があります。
  2. スクリプトのシンプル化と例外処理のカプセル化
    フロー内でプロンプトテンプレートアクションを呼び出すと、処理が正常に完了したパスだけでなく、LLMの処理がタイムアウトした場合などのエラーハンドリングをフロー内で細かく定義することができます。データ取得やエラー処理といった複雑なロジックをフロー側に閉じ込める(カプセル化する)ことで、Agent Script自体は「フローを呼び出して結果を受け取り、分岐する」というルーティング制御に専念でき、スクリプトが肥大化してメンテナンスが困難になるのを防ぐことができます。

最後に有効化します。

②オムニチャネルフローの作成

エスカレーションが起動した際、そのリクエストを受け取り、適切なスキルセットとキャパシティを持つ人間のオペレーター(またはキュー)にリアルタイムでルーティングするエンジンがオムニチャネルフローです。

  • 名前: EscalateToHuman
  • 説明: Agentforceエージェントから人間オペレーターに引き継ぐ。
  • 入力変数: recordId (テキスト / 入力で使用可能)
  • キュー: Step0で作成した有人対応キューを指定

③権限を付与

エージェントに「フローを実行」の権限があるか念のため確認してください。
デフォルトで割り当たっている「Einstein_Agent_User」プロファイルにその権限が付与されているはずです。

また、権限セット「(エージェント名称)xxxxxx権限」というデフォルトで用意されている権限セットで以下の権限が存在することを確認しておきます。

  • Knowledge: 参照
  • ケース: 参照/作成/編集
  • メッセージングセッション: 参照/編集
  • メッセージングユーザー: 参照
  • 取引先責任者: 参照

④プレゼンス設定

[設定] > [プレゼンス設定] から、人間が応答するためのプレゼンス設定を行います。
先ほど作成したキューとオムニチャネルフローを含めるようにしてください。

Step 3: エージェントの構築

新規バージョンを作成

まずはエージェントの新規バージョンを作成します。これにより動作中のバージョンに影響を出さず安全に改善できます。

  1. [Agentforce スタジオ] からエージェントを選択してAgentforce Builderを開く。
  2. 右上の [新しいバージョン] を選択して新規バージョンを作成する。

スクリプトを編集

Agentforce Builderのスクリプト機能を使ってエスカレーション機能を実装していきます。
ポイントは以下のとおりです。

センチメント分析による強制ルーティングのフック

ユーザーが不満を抱くタイミングは予測できないため、顧客の入力を処理して返答を生成するメインのトピック(今回は Product_SupportOrder_Management)の reasoning.instructions先頭にセンチメント分析のアクションを挿入します。

トピックの本来のアクションを実行する前に顧客の入力を感情分析して、所定のしきい値を下回る場合はすぐさまエスカレーションに進むように設計しています。

サンプルスクリプト

reasoning:
    actions:
        Generate_Knowledge_Answer: @actions.Generate_Knowledge_Answer
            with "Input:Customer_Question" = ...
            with citationMode = ...

        analyze_sentiment: @actions.analyze_sentiment
            with input_Text_Utterance = ...

        go_to_CustomEscalation: @utils.transition to @topic.Custom_Escalation

    instructions: |
        | 回答の生成の前に: ユーザーからの質問に答える前に、必ず {!@actions.analyze_sentiment} を実行して顧客の感情スコア(0.0〜1.0)を取得してください。
        | 感情スコアに基づく処理: もし分析された感情スコアが 0.3 未満だった場合は、回答を生成せずに直ちに {!@actions.go_to_CustomEscalation} を実行してエスカレーション処理を行ってください。
        | 回答の生成: もしスコアが 0.3 以上であれば、{!@actions.Generate_Knowledge_Answer} を実行し、その結果に基づいて回答を作成してください。検索結果にない情報は回答に含めないでください。
        | トーン: 専門的かつ分かりやすい言葉遣いで回答してください。
            不明な場合: 関連する情報が見つからない場合は、正直に「情報が見つかりませんでした」と答えてください。

エスカレーショントピックにおけるケース作成+オペレーター転送

遷移先の Custom_Escalation では、必ずケースレコード作成をしてからオペレーターに転送するように二段階の構成にしています。
まず Custom_Escalation でケースを作成し、その直後に Escalation でオペレーター転送を実行しています。
Escalation が直接使用されないように、topic_selection のアクションとして Escalation トピックを含めないようにしておくこともポイントです。

なお、ケース作成のためにはチャット時点でメッセージングユーザーと取引先責任者を紐付けておく必要があります。具体的な方法は以下の記事をご覧ください。

topic Custom_Escalation:
    label: "Custom_Escalation"

    description: "人間のチャットオペレーターとの直接の会話を要求するすべてのユーザー問い合わせ、およびセンチメント悪化によるエスカレーション要求を処理します。引き継ぎのためにケースを作成してから人間のオペレーターへ引き渡します。"

    reasoning:
        actions:
            create_case: @actions.create_case

        instructions: |
            | エスカレーション準備の必須アクション: 引き継ぎを開始するために、何よりも先に {!@actions.create_case} アクションを実行してケースレコードを作成してください。必ずパラメーターにダミー文字列ではなく変数の値を指定してください。
            | ケース情報の引数パラメーター:
            | - verifiedCustomerID: {!@variables.ContactId}
            | - messagingSessionID: {!@variables.RoutableId}
            | - caseSubject: "エスカレーション要求"
            | - caseDescription: {!@system_variables.user_input}
            | ケース作成後の案内: アクション実行後、「お待たせいたしました。担当者にお繋ぎしますので、そのまま少々お待ちください。」と丁寧にお伝えしてください。

    after_reasoning:
        set @variables.caseEscalationTransitioned = True
        transition to @topic.Escalation
(中略)

topic Escalation:
    label: "Escalation"

    description: "Handles requests from users who want to transfer or escalate their conversation to a live human agent."

    reasoning:
        actions:
            go_to_escalation: @utils.escalate
                description: "Escalate the conversation to a live human agent."

        instructions: |
            | Execute {!@actions.go_to_escalation}.

この二段階トピックを構築するに至った試行錯誤を以下の記事に記載しています。よろしければご覧ください。

DXforce Point

この実装例では、コールセンターの業務効率化のために、転送前に必ずSalesforceシステム上に「ケース(Case)」レコードを作成させ、それまでの文脈をオペレーターに引き継ぐことを必須としています。
これにより以下のようなメリットが考えられます。

  1. コンテキストの構造化と要約
    AIエージェントが顧客と会話した内容を単なるチャット履歴として渡すのではなく、AIに「構造化された要約(件名や詳細な説明)」を作成させてケースに保存することで、人間のオペレーターは状況を瞬時に把握できるようになります。これにより、顧客に同じ質問を繰り返す手間やフラストレーションを省くことができます。
  2. チャット切断時の確実なフォローアップ
    メッセージングセッションは、顧客がブラウザを閉じたりネットワークが切断されたりすると終了してしまいます。しかし、事前にケースが作成されていれば、チャットが不意に切断されても「未解決の課題」としてシステム上に残り続けるため、オペレーターは後からメールや電話で確実にフォローアップを行うことができます。
  3. 高度なSLA管理とルーティングの適用
    ケースを使用することで、Salesforce標準の強力なケース割り当てルール、エスカレーション(時間経過による自動警告)ルール、およびマイルストーンを適用し、より高度な条件で適切な担当者へ案件をルーティングすることが可能になります。
  4. 複数チャネルの履歴の統合(オムニチャネル対応)
    顧客が今日はチャットで問い合わせ、明日はメールで追加情報を送り、明後日に電話をかけてきた場合でも、それらすべての異なる通信履歴を「1つのケース」に紐付けて一元管理することができます。

エスカレーションフローを指定する

Escalation が正常に起動したときに呼び出すオムニチャネルフローを指定します。

  1. 左側メニュー接続の横にある [+] > [接続を追加] を押す。
  2. 拡張チャット v2 を [選択済み] にして [エージェントに追加]。
  • 接続を追加
  • 拡張チャット v2
  • エスカレーションフローを指定

最後にエージェントのバージョンを確定してActivateします。
プレビューではメッセージングセッションIDが取得できない関係でうまくいかないため、有効化してから実際のExperience Cloud画面で動作を確認してみましょう。

最終的なスクリプトは以下のようになります。ご参考になさってください。

system:
  instructions: |
    私たち DXforce.site 社は、Salesforce Experience Cloud の技術コンサルティングに加え、公式トレーニング教材、専門書籍、およびオリジナルグッズのオンライン販売を行う企業です。 私たちはオンラインストアを通じて顧客からの注文を受け付け、受注から配送までのフルフィルメント業務を行っています。顧客はポータルサイトを通じて、商品の購入や配送状況の確認を行うことができます。あなたは DXforce.site 社の親切で知識豊富なカスタマーサポートエージェントです。 
    あなたの目的は、顧客の「注文状況」を確認して配送予定などを伝えること、および「製品や技術」に関する質問にナレッジベースを使って回答することです。 【行動指針】 常に丁寧な「です・ます」調で、共感を持って接してください。 ナレッジベースやCRMデータにない情報は、推測で答えず、正直に「情報が見つかりませんでした」と伝えてください。 顧客の課題解決を最優先し、簡潔かつ的確な回答を心がけてください。

  messages:
    welcome: "こんにちは。私は DXforce.site のサポートエージェントです。何かお困りですか?"
    error: "申し訳ございません。問題が発生しているようです。恐れ入りますが時間をおいてもう一度お試しください。"

config:
  agent_label: "Agentforce Service Agent v2"
  developer_name: "Agentforce_Service_Agent_v2"
  description: "自律型AIエージェントとして、顧客からの注文状況の照会に対応し、ナレッジベースを活用して製品やサービスに関する質問に回答します。複雑な問題は人間のエージェントにエスカレーションします。"
  default_agent_user: "agentforce_service_agent@00dgk00000ft5ol1725598226.ext"

language:
  default_locale: "ja"
  additional_locales: ""
  all_additional_locales: False

variables:
  authenticationKey: mutable string
    description: "Stores the authentication key that's used to generate the verification code."
    visibility: "Internal"
  customerId: mutable string
    description: "Stores the Salesforce user ID or contact ID."
    visibility: "Internal"
  customerType: mutable string
    description: "Stores the customer ID type, whether it's a Salesforce user or a contact."
    visibility: "Internal"
  isVerified: mutable boolean = False
    label: "isVerified"
    description: "Stores a boolean value that indicates whether the customer code is verified."
    visibility: "Internal"
  EndUserId: linked string
    source: @MessagingSession.MessagingEndUserId
    description: "This variable may also be referred to as MessagingEndUser Id"
  RoutableId: linked string
    source: @MessagingSession.Id
    description: "This variable may also be referred to as MessagingSession Id"
  ContactId: linked string
    source: @MessagingEndUser.ContactId
    description: "This variable may also be referred to as MessagingEndUser ContactId"
  EndUserLanguage: linked string
    source: @MessagingSession.EndUserLanguage
    description: "This variable may also be referred to as MessagingSession EndUserLanguage"
  VerifiedCustomerId: mutable string
    description: "This variable may also be referred to as VerifiedCustomerId"
    visibility: "Internal"
  PromptResponse: mutable object
    label: "PromptResponse"
  customerSentimentScore: mutable number
    description: "顧客の最新の発話の感情スコア(0.0〜1.0)"
  createdCaseRecord: mutable object
    description: "作成されたケースのレコードオブジェクト情報"
  createdCaseId: mutable string
    description: "The Case Id captured after successful case creation for deterministic transitions."
  caseEscalationTransitioned: mutable boolean = False
    description: "Guard to ensure deterministic escalation transition occurs only once."

knowledge:
    rag_feature_config_id: ""
    citations_enabled: False
    citations_url: ""

start_agent topic_selector:
    label: "Topic Selector"

    description: "Welcome the user and determine the appropriate topic based on user input"

    reasoning:
        instructions: |
            | Select the best tool to call based on conversation history and user's intent.

        actions:
            go_to_Product_Support: @utils.transition to @topic.Product_Support

            go_to_Order_Management: @utils.transition to @topic.Order_Management

            go_to_CustomEscalation: @utils.transition to @topic.Custom_Escalation

topic Product_Support:
    label: "Product Support"

    description: "製品の仕様、機能、使用方法、トラブルシューティング、または返品ポリシーに関する質問に対し、ナレッジベースを活用して正確な情報を提供します。このトピックは、ユーザーが製品に関する具体的な問題や疑問を解決するためのサポートを目的としています。"

    reasoning:
        actions:
            Generate_Knowledge_Answer: @actions.Generate_Knowledge_Answer
            analyze_sentiment: @actions.analyze_sentiment
            go_to_CustomEscalation: @utils.transition to @topic.Custom_Escalation

        instructions: |
            | 回答の生成の前に: ユーザーからの質問に答える前に、必ず {!@actions.analyze_sentiment} を実行して顧客の感情スコア(0.0〜1.0)を取得してください。
            | 感情スコアに基づく処理: もし分析された感情スコアが 0.3 未満だった場合は、回答を生成せずに直ちに {!@actions.go_to_CustomEscalation} を実行してエスカレーション処理を行ってください。
            | 回答の生成: もしスコアが 0.3 以上であれば、{!@actions.Generate_Knowledge_Answer} を実行し、その結果に基づいて回答を作成してください。検索結果にない情報は回答に含めないでください。
            | トーン: 専門的かつ分かりやすい言葉遣いで回答してください。
            | 不明な場合: 関連する情報が見つからない場合は、正直に「情報が見つかりませんでした」と答えてください。

    actions:
        Generate_Knowledge_Answer:
          description: "ナレッジ記事に基づいて、ユーザーの質問に対する回答を生成します。"
          inputs:
            "Input:Customer_Question": string
              description: "お客様が入力した質問をセットします。"
              label: "Customer Question"
              is_required: True
              is_user_input: True
              complex_data_type_name: "lightning__textType"
            citationMode: string
              description: "Select Citation Mode"
              label: "Citation Mode"
              is_required: False
              is_user_input: False
              complex_data_type_name: "lightning__textType"
          outputs:
            promptResponse: string
              description: "The prompt response generated by the action based on the specified prompt and input."
              label: "Prompt Response"
              complex_data_type_name: "lightning__textType"
              filter_from_agent: False
              is_displayable: True
            citations: object
              description: "The prompt citation response generated by the action based on the specified prompt and input."
              label: "Citations"
              complex_data_type_name: "@apexClassType/AiCopilot__GenAiCitationOutput"
              filter_from_agent: False
              is_displayable: False
          target: "generatePromptResponse://Generate_Knowledge_Answer"
          label: "Generate Knowledge Answer"
          require_user_confirmation: False
          include_in_progress_indicator: True
          progress_indicator_message: "ご質問への回答を生成中..."

        analyze_sentiment:
          description: "顧客の発話の感情分析を行います。"
          inputs:
            input_Text_Utterance: string
              description: "顧客による発言"
          outputs:
            output_Number_SentimentScore: number
              description: "顧客の最新の発話の感情スコア(0.0〜1.0)"
          target: "flow://AnalyzeCustomerSentiment"

topic Order_Management:
    label: "Order Management"

    description: "注文の配送状況、ステータス、到着予定日、または注文内容に関する問い合わせに対応し、注文番号を基にシステムから最新の情報を取得して提供します。このトピックは、ユーザーの注文に関する状況確認や詳細情報の提供を専門としています。"

    reasoning:
        actions:
            Retrieve_Order_Data: @actions.Retrieve_Order_Data
            analyze_sentiment: @actions.analyze_sentiment
            go_to_CustomEscalation: @utils.transition to @topic.Custom_Escalation

        instructions: |
            | 回答の生成の前に: 注文データの検索を開始する前に、必ず {!@actions.analyze_sentiment} を実行して顧客の感情スコア(0.0〜1.0)を取得してください。
            | 感情スコアに基づく処理: もし分析された感情スコアが 0.3 未満だった場合は、それ以上の処理を行わず直ちに {!@actions.go_to_CustomEscalation} を実行してください。
            | 必須情報の確認: 感情スコアが 0.3 以上の場合で、かつユーザーの発言に「注文番号」が含まれていない場合は、「注文番号を教えていただけますか?」と尋ねてください。
            | アクションの実行: 感情スコアが 0.3 以上であり、かつ注文番号が得られたら、速やかに {!@actions.Retrieve_Order_Data} アクションを実行し、その結果(ステータスや配送日)をユーザーに丁寧に伝えてください。
            | 結果の報告: アクションの結果(ステータスや配送日)を、ユーザーに丁寧に伝えてください。

    actions:
        Retrieve_Order_Data:
          description: "注文番号(input_Text_OrderNumber)を入力キーとして受け取り、Salesforce の注文(Order)オブジェクトを検索して、現在のステータス、配送予定日、および配送追跡情報を返します。 ユーザーが「私の注文はどうなっていますか?」「荷物はいつ届きますか?」「発送は終わりましたか?」といった、特定の注文の進捗状況や詳細を知りたがっている場合に、このアクションを使用してください。"
          inputs:
            input_Text_OrderNumber: string
              description: "顧客から得た注文番号。"
              label: "input_Text_OrderNumber"
              is_required: True
              is_user_input: True
              complex_data_type_name: "lightning__textType"
          outputs:
            output_Text_StatusMessage: string
              description: "注文の進捗状況や詳細。"
              label: "output_Text_StatusMessage"
              complex_data_type_name: "lightning__textType"
              filter_from_agent: False
              is_displayable: True
          target: "flow://RetrieveOrderData"
          label: "Retrieve Order Data"
          require_user_confirmation: False
          include_in_progress_indicator: True
          progress_indicator_message: "ご注文状況を確認中..."

        analyze_sentiment:
          description: "顧客の発話の感情分析を行います。"
          inputs:
            input_Text_Utterance: string
              description: "顧客による発言"
          outputs:
            output_Number_SentimentScore: number
              description: "顧客の最新の発話の感情スコア(0.0〜1.0)"
          target: "flow://AnalyzeCustomerSentiment"

topic Custom_Escalation:
    label: "Custom_Escalation"

    description: "人間のチャットオペレーターとの直接の会話を要求するすべてのユーザー問い合わせ、およびセンチメント悪化によるエスカレーション要求を処理します。引き継ぎのためにケースを作成してから人間のオペレーターへ引き渡します。"

    reasoning:
        actions:
            create_case: @actions.create_case
        instructions: |
            | エスカレーション準備の必須アクション: 引き継ぎを開始するために、何よりも先に {!@actions.create_case} アクションを実行してケースレコードを作成してください。必ずパラメーターにダミー文字列ではなく変数の値を指定してください。
            | ケース情報の引数パラメーター:
            | - verifiedCustomerID: {!@variables.ContactId}
            | - messagingSessionID: {!@variables.RoutableId}
            | - caseSubject: "エスカレーション要求"
            | - caseDescription: {!@system_variables.user_input}
            | ケース作成後の案内: アクション実行後、「お待たせいたしました。担当者にお繋ぎしますので、そのまま少々お待ちください。」と丁寧にお伝えしてください。

    after_reasoning:
        set @variables.caseEscalationTransitioned = True
        transition to @topic.Escalation

    actions:
        create_case:
            description: "ケースを作成します。"
            inputs:
                verifiedCustomerID: string
                  description: "顧客の取引先責任者ID"
                messagingSessionID: string
                  description: "メッセージングセッションID"
                caseSubject: string
                  description: "ケースの件名"
                caseDescription: string
                  description: "ケースの詳細な説明"
            outputs:
                caseRecord: object
                  description: "作成されたケースレコード"
                  complex_data_type_name: "lightning__recordInfoType"
            target: "flow://SvcCopilotTmpl__CreateCaseEnhancedData"

topic Escalation:
    label: "Escalation"

    description: "Handles requests from users who want to transfer or escalate their conversation to a live human agent."

    reasoning:
        actions:
            go_to_escalation: @utils.escalate
                description: "Escalate the conversation to a live human agent."

        instructions: |
            | Execute {!@actions.go_to_escalation}.

connection customer_web_client:
    escalation_message: "ただいま適切な有人対応をお客様に提供するために会話を転送します。少々お待ちくださいませ。"
    outbound_route_type: "OmniChannelFlow"
    outbound_route_name: "flow://EscalateToHuman"
    adaptive_response_allowed: True

canEscalateをtrueに更新する

Agentforceにおいて、エージェントが実行可能な特定の業務カテゴリや機能スコープを定義する「トピック」は、内部的には GenAiPluginDefinition というメタデータオブジェクトとして保存・管理されています 。

新たに作成されたカスタムトピックは、デフォルトの状態では人間のオペレーターへ会話を転送する権限を有していません。このエスカレーションの適格性は、GenAiPluginDefinitionオブジェクト内のcanEscalateというブール値(boolean)フィールドによって厳密に制御されています。このフィールドがfalseのままである限り、指示内でどれほど詳細に「オペレーターに転送してください」と指示を与えたとしても、Atlas Reasoning Engineはシステムレベルでのルーティングプロセスをトリガーすることができない仕組みになっています。

開発者コンソールを使用して、以下のSOQLで canEscalatetrue に更新しましょう。

SELECT Id, Planner.DeveloperName, canEscalate FROM GenAiPluginDefinition WHERE DeveloperName LIKE 'Escalation%' ORDER BY Planner.DeveloperName

まとめ:エージェントの動作確認をする

それでは最後にExperience Cloudサイトにログインしてオペレータに転送されるか確認してみましょう。
はじめは普通に会話して、途中からわざと怒って人間にエスカレーションしてくれるか反応を見ます。

製品サポートの問いかけをしてみる

ナレッジに登録しておいたデータに基づいて、うまく回答を返してくれました。
さらに、オペレーターへの転送もうまくいっています。

製品の仕様についてのQAに答えてくれるAgentforce Service Agent
怒る顧客に対応できる人間にエスカレーションしている

注文状況の確認をしてみる

ちゃんと注文番号を聞き出してからステータスを調べて返答していますね。
こちらもオペレーター転送が成功しています。

注文状況を調べて回答してくれるAgentforce Service Agent
取り乱す顧客を見て人間に転送している

オペレーターが見ている画面

Agentforce Service Agentからメッセージング転送を受けたオペレーターは、エージェントが事前に作成したケースの要約やこれまでの会話内容を見ながらチャット対応を行うことができます。

無事にAgent Scriptを活用しながらAgentforceエージェントからオペレーターへの転送が成功しました。
感情分析とケース登録とエスカレーションを組み合わせる、実態に合わせた難易度の高い実装でしたがうまくいきましたね。皆さんはここからさらに発展させて完璧なエスカレーション構築をしてみてください。

参考URL

Transfer Conversations from an Agent with an Omni-Channel Flow

utils.escalate

Get Started with Agent Script

Code Your Agent Using Its Agent Script File

Agentforce Builder に関する考慮事項

DXforceの管理人

福島 瑛二

2013年にJavaエンジニアとしてのキャリアをスタート。2019年にSalesforceと出会い、Salesforceエンジニアの道へ。

デザインや UI/UX の観点からもシステムを捉え、ユーザーにとって心地よい体験を実装することにやりがいを感じています。

CRM(顧客データ)や Data Cloud と連携した高度なサイトを目に見える形で表現できる Experience Cloud に大きな可能性を見出しており、バックエンドのデータ構造とフロントエンドの表現力を極めることがこれからの Salesforce エンジニアに求められるスキルだと確信しています。

Trailblazer: efukushima

福島 瑛二をフォローする

読者の声

タイトルとURLをコピーしました