mcpField
M
multi-turn-ordering

multi-turn-ordering

github.com/happy-technologies-llc開発4141 回インストール2 日前に更新
リポジトリ

multi-turn-ordering について

ServiceNow のカタログ注文を複数ターンの会話で構築するスキルです。チャットでカタログを検索・選択・注文させたいチーム向けに、候補の判別、変数の段階的な収集、カート送信を扱います。

主な機能

  1. 01Virtual Agent の注文トピック設定
  2. 02カタログ項目の検索と候補判別
  3. 03必須変数の段階的な収集
  4. 04カート管理と注文送信
  5. 05会話ターン間のコンテキスト維持

活用シーン

  1. 01チャットでハードウェアやソフトウェアを注文
  2. 02複雑なカタログフォームへの段階的な案内
  3. 03複数候補から項目を選ぶフローの作成

MCP 対応

ServiceNow MCP ツールでカタログを照会し、Virtual Agent のトピックやノードを作成・更新して、スクリプトで会話フローをテストする方法を説明します。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/happy-technologies-llc/happy-platform-skills --skill multi-turn-ordering

インストール後、Claude Code で/multi-turn-orderingを入力して読み込まれたか確認します。

詳細

複数ターンのカタログ注文

概要

このスキルでは、ユーザーがガイド付きの対話を通じてカタログ項目を閲覧、選択、注文できる、会話形式の複数ターン注文フローを設定します。次の内容を扱います。

  • sys_cb_topic を使用した、カタログ注文の会話に対応する Virtual Agent トピックの設定
  • sc_cat_item と sc_category から項目を会話形式で検索し、選択するための設定
  • item_option_new の値を段階的に収集する、複数ターンの変数収集フローの設計
  • Service Catalog API を使用したカート管理と注文の実行
  • ユーザーのリクエストに複数の項目が一致する場合の曖昧さの解消
  • 複雑な注文シナリオにおける、ターンをまたいだ会話コンテキストの管理

使用する場面: 従業員が従来のカタログポータルを操作するのではなく、チャットインターフェース(Virtual Agent、Slack、Teams)からカタログ項目を注文できるようにしたい組織や、項目の注文時にガイド付きの段階的な変数収集が必要な場合に使用します。

価値提案: 複数ターンの注文により、カタログの利用中断を減らし、複雑なフォームへの入力をガイドすることで申請者のエクスペリエンスを向上させ、ポータルにアクセスせずにメッセージングプラットフォームから注文できるようになります。

前提条件

  • プラグイン: com.glide.cs.chatbot(Virtual Agent)、com.glideapp.servicecatalog(Service Catalog)
  • ロール: admin、virtual_agent_admin、または catalog_admin
  • アクセス権: sc_cat_item、sc_category、item_option_new、sys_cb_topic、sys_cb_topic_detail への読み取り/書き込みアクセス権
  • 知識: Virtual Agent トピックの設計、NLU モデル、Service Catalog API に関する理解

手順

手順 1:会話形式の注文に適したカタログ項目を特定する

複数ターンの注文に適した項目を特定します。変数が 3~8 個あり、選択経路が明確な項目が最適です。

MCP を使用する場合(Claude Code/Desktop):

Tool: SN-Query-Table
Parameters:
  table_name: sc_cat_item
  query: active=true^type=item^sc_catalogs.titleLIKEService Catalog
  fields: sys_id,name,short_description,category,sc_catalogs,price,order,availability
  limit: 50
  order_by: category,name

REST API を使用する場合:

GET /api/now/table/sc_cat_item?sysparm_query=active=true^type=item&sysparm_fields=sys_id,name,short_description,category,sc_catalogs,price,order&sysparm_limit=50&sysparm_display_value=true

項目ごとの変数数を確認して複雑さを評価します:

Tool: SN-Execute-Background-Script
Parameters:
  description: Count variables per catalog item for ordering suitability
  script: |
    var items = new GlideRecord('sc_cat_item');
    items.addQuery('active', true);
    items.addQuery('type', 'item');
    items.orderBy('category');
    items.query();

    var results = [];
    while (items.next()) {
      var vars = new GlideAggregate('item_option_new');
      vars.addQuery('cat_item', items.sys_id);
      vars.addQuery('active', true);
      vars.addAggregate('COUNT');
      vars.query();

      var varCount = 0;
      if (vars.next()) varCount = parseInt(vars.getAggregate('COUNT'));

      var mandatoryVars = new GlideAggregate('item_option_new');
      mandatoryVars.addQuery('cat_item', items.sys_id);
      mandatoryVars.addQuery('active', true);
      mandatoryVars.addQuery('mandatory', true);
      mandatoryVars.addAggregate('COUNT');
      mandatoryVars.query();

      var mandCount = 0;
      if (mandatoryVars.next()) mandCount = parseInt(mandatoryVars.getAggregate('COUNT'));

      if (varCount > 0) {
        results.push({
          name: items.name.toString(),
          category: items.category.getDisplayValue(),
          total_variables: varCount,
          mandatory_variables: mandCount,
          suitability: varCount <= 8 ? 'Good' : 'Complex'
        });
      }
    }

    gs.info(JSON.stringify(results, null, 2));
手順 2:会話フローを設計する

注文プロセスを会話ターンに割り当てます。

ターンボットのアクションユーザーの応答取得するデータ
1「何を注文しますか?」「新しいノートパソコンが必要です」インテント:catalog_order、キーワード:laptop
2「次の選択肢が見つかりました:[リスト]」「パフォーマンスモデル」項目の選択
3「必要な RAM 容量はどれくらいですか?」「16GB」変数:ram_size
4「ストレージ容量はどれくらいですか?」「512GB SSD」変数:storage_size
5「業務上の必要性を入力してください」「現在のノートパソコンが故障しかけています」変数:justification
6「注文内容を確認してください:[概要]」「はい、送信してください」カートの送信
手順 3:Virtual Agent トピックを作成する

カタログ注文用の Virtual Agent トピックを設定します。

MCP を使用する場合:

Tool: SN-Create-Record
Parameters:
  table_name: sys_cb_topic
  fields:
    name: "Order Catalog Item"
    description: "Conversational flow for browsing and ordering service catalog items with guided variable collection"
    category: service_catalog
    active: true
    enabled: true
    nlu_intent: catalog_order
    greeting_message: "I can help you order from the service catalog. What are you looking for?"
    fallback_message: "I couldn't find a matching item. Could you describe what you need differently?"
    end_message: "Your order has been submitted! You'll receive a confirmation email shortly."
    topic_type: standard

REST API を使用する場合:

POST /api/now/table/sys_cb_topic
Content-Type: application/json

{
  "name": "Order Catalog Item",
  "description": "Conversational flow for browsing and ordering service catalog items",
  "category": "service_catalog",
  "active": "true",
  "enabled": "true",
  "nlu_intent": "catalog_order",
  "greeting_message": "I can help you order from the service catalog. What are you looking for?",
  "topic_type": "standard"
}
手順 4:項目検索用のトピック詳細を設定する

項目の検索と選択を処理するトピック詳細ノードを追加します。

検索ノードを作成します:

Tool: SN-Create-Record
Parameters:
  table_name: sys_cb_topic_detail
  fields:
    topic: [topic_sys_id]
    name: "Search Catalog Items"
    node_type: script
    order: 100
    script: |
      (function() {
        var keyword = vaSystem.getLastUserMessage();
        var items = [];

        var gr = new GlideRecord('sc_cat_item');
        gr.addQuery('active', true);
        gr.addQuery('type', 'item');
        gr.addQuery('nameLIKE' + keyword)
          .addOrCondition('short_descriptionLIKE' + keyword);
        gr.setLimit(5);
        gr.query();

        while (gr.next()) {
          items.push({
            sys_id: gr.sys_id.toString(),
            name: gr.name.toString(),
            description: gr.short_description.toString(),
            price: gr.price.toString()
          });
        }

        vaVars.items = JSON.stringify(items);
        return items.length > 0 ? 'found' : 'not_found';
      })();

複数の一致候補がある場合に、曖昧さを解消するノードを作成します:

Tool: SN-Create-Record
Parameters:
  table_name: sys_cb_topic_detail
  fields:
    topic: [topic_sys_id]
    name: "Disambiguate Items"
    node_type: user_input
    order: 200
    prompt_message: "I found multiple items matching your request. Which one did you mean?"
    input_type: picker
    picker_source_variable: items
手順 5:変数収集ノードを設定する

必須の変数をそれぞれ収集する会話ノードを作成します。

MCP を使用する場合:

Tool: SN-Execute-Background-Script
Parameters:
  description: Create variable collection nodes for catalog item ordering
  script: |
    var topicId = '[topic_sys_id]';
    var itemId = '[cat_item_sys_id]';

    // Get mandatory variables for the item
    var vars = new GlideRecord('item_option_new');
    vars.addQuery('cat_item', itemId);
    vars.addQuery('active', true);
    vars.addQuery('mandatory', true);
    vars.orderBy('order');
    vars.query();

    var nodeOrder = 300;
    while (vars.next()) {
      var detail = new GlideRecord('sys_cb_topic_detail');
      detail.initialize();
      detail.topic = topicId;
      detail.name = 'Collect: ' + vars.question_text.toString();
      detail.node_type = 'user_input';
      detail.order = nodeOrder;
      detail.prompt_message = vars.question_text.toString();

      // Map variable type to input type
      var varType = parseInt(vars.type);
      if (varType === 3) {
        detail.input_type = 'picker';
      } else if (varType === 9) {
        detail.input_type = 'date';
      } else if (varType === 2) {
        detail.input_type = 'text_area';
      } else {
        detail.input_type = 'text';
      }

      detail.mapped_variable = vars.name.toString();
      detail.insert();
      nodeOrder += 100;
    }

    gs.info('Created ' + ((nodeOrder - 300) / 100) + ' variable collection nodes');
手順 6:注文確認と送信を追加する

注文確認とカート送信のノードを作成します。

確認ノードを作成します:

Tool: SN-Create-Record
Parameters:
  table_name: sys_cb_topic_detail
  fields:
    topic: [topic_sys_id]
    name: "Confirm Order"
    node_type: user_input
    order: 900
    prompt_message: "Here's your order summary:\n\nItem: {{selected_item_name}}\n{{variable_summary}}\n\nWould you like to submit this order?"
    input_type: yes_no

Service Catalog API を使用して送信ノードを作成します:

Tool: SN-Create-Record
Parameters:
  table_name: sys_cb_topic_detail
  fields:
    topic: [topic_sys_id]
    name: "Submit Order"
    node_type: script
    order: 1000
    script: |
      (function() {
        var itemId = vaVars.selected_item_id;
        var variables = JSON.parse(vaVars.collected_variables || '{}');

        // Create cart item
        var cart = new sn_sc.CatalogOrderHelper();
        cart.setRequestedFor(vaSystem.getUserSysId());

        var cartItem = cart.addToCart(itemId);
        for (var key in variables) {
          cartItem.setVariable(key, variables[key]);
        }

        var request = cart.submitOrder();
        vaVars.request_number = request.number;

        return 'submitted';
      })();
手順 7:会話フローをテストして公開する

複数ターンのフローを最初から最後まで検証します。

MCP を使用する場合:

Tool: SN-Query-Table
Parameters:
  table_name: sys_cb_topic_detail
  query: topic=[topic_sys_id]
  fields: sys_id,name,node_type,order,prompt_message,input_type,mapped_variable
  limit: 20
  order_by: order

REST API を使用する場合:

GET /api/now/table/sys_cb_topic_detail?sysparm_query=topic=[topic_sys_id]^ORDERBYorder&sysparm_fields=sys_id,name,node_type,order,prompt_message,input_type,mapped_variable&sysparm_limit=20&sysparm_display_value=true

トピックを有効化します:

Tool: SN-Update-Record
Parameters:
  table_name: sys_cb_topic
  sys_id: [topic_sys_id]
  fields:
    active: true
    enabled: true
    published: true

ツールの使用方法

MCP ツールリファレンス
ツール使用する場面
SN-Query-Tableカタログ項目、変数、カテゴリ、トピックを検索する
SN-Create-Recordトピック、トピック詳細、カタログ設定を作成する
SN-Update-Recordトピックを有効化して公開し、項目設定を更新する
SN-Natural-Language-Search自然言語のクエリに一致するカタログ項目を検索する
SN-Execute-Background-Script会話ノードを一括作成し、フローをテストする
SN-Discover-Table-SchemaVirtual Agent とカタログのテーブルスキーマを調べる
REST API リファレンス
エンドポイントメソッド目的
/api/now/table/sc_cat_itemGET注文可能なカタログ項目を検索する
/api/now/table/item_option_newGET収集する項目変数を取得する
/api/now/table/sc_categoryGETカタログカテゴリを閲覧する
/api/now/table/sys_cb_topicGET/POST/PATCHVirtual Agent のトピックを管理する
/api/now/table/sys_cb_topic_detailGET/POST会話フローノードを設定する
/api/sn_sc/servicecatalog/itemsGET項目の詳細を取得する Service Catalog API
/api/sn_sc/servicecatalog/cartPOSTカートの管理と注文の送信を行う

ベストプラクティス

  • 会話は短く保ちます: 最大 5~7 ターンに制限し、可能であれば関連する変数を 1 つのプロンプトにまとめます
  • クイック選択肢を提示します: カタログ全体を検索する前に、人気の高い 3~5 項目を提示します
  • 各ターンでコンテキストを示します: 何を注文しているのか、どの情報がまだ必要なのかをユーザーに伝えます
  • 前の手順に戻れるようにします: ユーザーが「戻る」や「選択を変更」と伝えて、前の回答を修正できるようにします
  • リッチメッセージを使用します: カード形式の応答で、項目の画像、価格、説明を表示します
  • 必須変数を先に収集します: 中断を最小限に抑えるため、任意項目より先に必須フィールドを確認します
  • 送信前に確認します: 注文の概要をすべて表示し、明示的な確認を求めます
  • 適切にエラーを処理します: 項目検索で一致する結果がない場合は、カテゴリから閲覧するか、クエリを言い換えるよう提案します

トラブルシューティング

Virtual Agent がカタログのインテントを認識しない

原因: NLU モデルに、カタログ注文インテントの発話例が十分にトレーニングされていません
解決策: catalog_order インテントに、「注文したい」「新しいものをリクエストしたい」「入手できますか」「購入したい」などの発話例を追加します。発話例を追加した後、NLU モデルを再トレーニングします。

ターン間で変数が保存されない

原因: 会話変数(vaVars)がカタログ変数に正しくマッピングされていません
解決策: 各トピック詳細ノードの mapped_variable が、item_option_new の name フィールドと一致することを確認します。送信スクリプト内の変数名が正確に一致することも確認します。

カートの送信に失敗する

原因: 必須変数の不足、無効な変数値、またはユーザーセッションの問題
解決策: 送信ノードの前に、すべての必須変数が収集されていることを検証します。不足値を確認し、必要に応じて前の手順に戻る事前送信スクリプトノードを追加します。インスタンスで CatalogOrderHelper を利用できることを確認します。

項目検索で誤った結果が返される

原因: 検索クエリの範囲が広すぎる、またはカタログ項目の名前やキーワードの説明が不十分
解決策: 検索可能なキーワードを使って、項目の short_description フィールドと description フィールドを改善します。カタログキーワードフィールドの追加、または NLU エンティティ抽出による検索の絞り込みを検討します。

例

例 1:シンプルなハードウェア注文の会話
Bot: "What would you like to order?"
User: "I need a new monitor"
Bot: "I found 2 monitors available:
      1. Standard Monitor (24" Dell) - $350
      2. Ultra-Wide Monitor (34" LG) - $750
      Which one would you like?"
User: "The ultra-wide"
Bot: "What is your desk location?"
User: "Building A, Floor 3, Desk 312"
Bot: "Do you need any mounting accessories? (desk mount, wall mount, or none)"
User: "Desk mount please"
Bot: "Order Summary:
      Ultra-Wide Monitor (34" LG) - $750
      Location: Building A, Floor 3, Desk 312
      Mounting: Desk mount
      Shall I submit this order?"
User: "Yes"
Bot: "Order submitted! Request REQ0045123 created. Expected delivery: 5-7 business days."
例 2:曖昧さを解消するソフトウェアリクエスト
Bot: "What would you like to order?"
User: "I need Adobe"
Bot: "I found several Adobe products:
      1. Adobe Creative Cloud (Full Suite) - $55/mo
      2. Adobe Acrobat Pro - $15/mo
      3. Adobe Photoshop (Single App) - $22/mo
      Which one do you need?"
User: "Just Acrobat"
Bot: "How many licenses do you need?"
User: "3"
Bot: "Business justification for the licenses?"
User: "Legal team needs PDF editing for contract reviews"
Bot: "I'll submit this for approval since it's 3+ licenses. Confirm?
      Adobe Acrobat Pro x3 - $45/mo
      Justification: Legal team PDF editing for contract reviews"
User: "Confirm"
Bot: "Submitted! REQ0045124 is pending manager approval."

関連スキル

  • catalog/catalog-item-generation - 説明からカタログ項目を生成する
  • catalog/variable-management - 高度な変数設定
  • catalog/item-creation - 標準的なカタログ項目の設定
  • catalog/request-fulfillment - 注文後の履行ワークフロー
  • catalog/approval-workflows - 注文の承認ルーティング
  • genai/playbook-generation - Virtual Agent のプレイブックを生成する

コメント