2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ServiceNowのUI BuilderでLLMチャット機能を実装する完全ガイド

2
Last updated at Posted at 2026-01-26

ServiceNowのUI BuilderでLLMチャット機能を実装する完全ガイド

対象読者とゴール

対象読者:

  • ServiceNow開発の基礎知識がある方
  • AWS基本サービスを理解している方
  • LLMを業務システムに組み込みたい方

ゴール:
ServiceNow内で動作するAIチャットボットを構築し、Claude 3 Sonnetと自然な対話ができるようになること。

※このガイドは学習・プロトタイプ開発用です。本番環境での使用は推奨しません。

本ガイドでは「動作する最小構成」を目標としています。セキュリティ対策(API認証など)、コスト管理、エラーハンドリングなどは含まれていません。本番環境で使用する場合は、必ず追加の対策を実施してください。

Part 1: 概要とServiceNow基本設定編

1. はじめに

1.1 本記事の目的

ServiceNowのUI Builderを使用して、外部LLM(Large Language Model)と連携したチャットボット機能を実装する方法を、ステップバイステップで解説します。本記事では、AWS BedrockのClaude 3 Sonnetを活用し、ServiceNow内で動作する対話型AIアシスタントを構築します。

1.2 実装する機能の概要

本チュートリアルで実装する機能:

  • ServiceNow UI Builderでのカスタムチャット画面作成
  • AWS Lambda経由でのBedrock Claude 3 Sonnetとの連携
  • リアルタイムでの対話履歴管理
  • 非同期処理による応答の表示

1.3 必要な前提知識・環境

ServiceNow側の要件:

  • ServiceNowインスタンス(開発インスタンス推奨)
  • Admin権限またはui_builder_adminロール
    • ※Admin権限がない場合:Custom Application作成、UI Builder操作が制限されます
  • Custom Application作成権限

AWS側の要件:

  • AWSアカウント
  • Lambda、API Gateway、Bedrockへのアクセス権限
  • Bedrock Claude 3 Sonnetの利用申請済み(ap-southeast-2リージョン)

技術的な前提知識:

  • JavaScript基礎知識
  • REST APIの基本概念
  • ServiceNow開発の基礎(推奨)

2. システムアーキテクチャ

2.1 全体構成図

image.png

2.2 コンポーネント間の連携

Backend構成

Backend:
├── Script Include
│   └── SimpleLLMConnector      // AWS API Gatewayとの通信処理
│
├── Data Broker Scripts(UI Builderが自動的に「_1」を付与)
│   ├── llm_chat (SimpleLLMConnectorを使用) → llm_chat_1として参照
│   └── llm_chat_messages (単純な配列処理) → llm_chat_messages_1として参照

Frontend構成(UI Builder)- 実装手順準拠

Frontend (UI Builder):
├── Client State Parameters
│   ├── userInput (JSON型, 初期値"{"botContent":"","userContent":""}")
│   ├── conversationHistory (JSON型, 初期値"[]")
│   └── processingPrompt (String型, 初期値"")
│
├── Client Scripts
│   ├── handleSend
│   └── handleLLMResponse
│
└── UI Components
    ├── Textarea 1 → @state.userInput
    ├── Button 1 → handleSend
    └── Repeater 1 → @state.conversationHistory
        ├── Stylized Text 1 → @item.value.userContent
        └── Stylized Text 2 → @item.value.botContent

重要な注記:userInputがJSON型で{"botContent":"","userContent":""}という初期値を持つのは、理論的には奇妙ですが、ServiceNowの内部処理により必要な設定です。この通りに設定すれば動作できます。

2.3 データフロー

  1. ユーザー入力処理
    • ユーザーがTextareaに質問を入力
    • Enterキーまたは送信ボタンをクリック
    • handleSendスクリプトが実行される
  2. LLM呼び出し
    • Client Scriptがllm_chat_1 Data Brokerを実行
    • Data BrokerがSimpleLLMConnectorを呼び出し
    • Script IncludeがAWS API GatewayにPOSTリクエストを送信
  3. AWS処理
    • API GatewayがLambda関数をトリガー
    • Lambda関数がBedrockのClaude 3 Sonnetを呼び出し
    • AI応答を生成してServiceNowに返却
  4. 応答表示
    • handleLLMResponseが応答を受け取る
    • 会話履歴(conversationHistory)を更新
    • Repeaterコンポーネントが自動的に再レンダリング
    • ユーザーとAIの対話が画面に表示される

3. ServiceNow側の実装

実装前の重要な注意事項

ServiceNowでは、カスタムアプリケーションは独自のスコープ内で動作します。本チュートリアルでは新規スコープを作成しますが、以下の点に注意してください:

  • Script IncludeとUI Builderのスコープは必ず一致させる
  • Data BrokerのACL設定時はElevate権限が必要
  • 作業完了後は必ずElevate権限を解除する

3.1 Scope作成

3.1.1 Custom Applicationの作成

  1. ServiceNowメイン画面の左側のFilter navigatorに Studio と入力
  2. System Applications → Studio を選択

image 1.png

  1. Create Application ボタン(緑色)をクリック

image 2.png

  1. Let's get started ボタンをクリック

image 3.png

  1. 以下の情報を入力:
Name: AI Chat Demo
Description: AI chatbot integrated with ServiceNow data
Advanced settings:
  ☑ Scoped を選択(既に選択済み)
Scope: 自動生成されるので、そのままでOK
      (例:x_1664513_ai_chat)

入力が完了したら Create ボタンをクリックしてください。

image 4.png

  1. ロール設定画面で Continue ボタンをクリック(デフォルトロールで十分)

image 5.png

  1. 今回はWebページ作成のため、Classicを選択します

image 6.png

  1. データテーブル選択画面です。今回はテーブルを作成せずに進めます。
    • 今回はテーブルを作成せずに進める
    • Done with tables ボタンをクリック

image 7.png

  1. Start ボタンをクリック

image 8.png

これでアプリケーションと新しいscopeが作成されます。

image 9.png

3.1.2 Tables と Roles の設定

最低限の選択が必要:

Tables:
  - Incident [incident] を選択(データ取得のデモ用)

Roles:
  - admin を選択(開発とテスト用)

image 10.png

選択後、Create ボタンをクリック

次に、Done with apps ボタンをクリック、これで作成できました。

image 11.png

3.2 UI Builder Experience作成

3.2.1 UI Builderへのアクセス

  1. Studioを閉じるか、右上の X をクリックしてStudioを閉じる
  2. ServiceNowメイン画面に戻る
  3. Filter navigatorに UI Builder と入力
  4. Now Experience Framework → UI Builder を選択

image 12.png

これで作成画面に入ります。

image 13.png

3.2.2 Experience情報の入力

UI Builderを開いて、新しいExperienceを作成。画面はこんな感じです:

image 14.png

以下情報を入力:

Name: AI Chat Demo
App shell UI: Portal App Shell を選択
URL path: ai-chat-demo
Landing path: home (既に入力済み)
Roles: 自動的に新しいscope(x_1664513_ai_chat.canvas_user)が入る

image 15.png

CreateOpen experience の順にクリック

image 16.png

これでExperience詳細画面が開き、ページの作成を開始できます。

3.3 ページ作成

3.3.1 新規ページ作成

  1. Create new page ボタンをクリック

image 17.png

  1. Create From scratch insteadを選択します

image 18.png

  1. ページ情報の入力します
Name: Chat
URL path: chat

image 19.png

  1. パラメータは不要なので、そのまま Continue ボタンをクリック

image 20.png

  1. Variant設定:
Name: Default(そのまま)
Audiences: 追加不要
Conditions: 追加不要

image 21.png

そのまま Continue ボタンをクリック

  1. Build responsive が選択されているので、そのまま進める

image 22.png

注意事項:
初回編集時に「Private application scope variant is in the safety application」というメッセージが表示される場合は、Developer menuからClear UI Builder cacheを実行してブラウザをリフレッシュしてください。

参考:https://www.servicenow.com/community/developer-forum/private-application-scope-variant-is-in-the-safety-application/m-p/3079385#M1154433

image 23.png

3.4 UI Builderでチャット画面構築

3.4.1 Repeaterの追加

  1. Body エリアをクリックして選択
  2. 画面下部の Add content ボタンをクリック
  3. 表示されるメニューから Repeater を検索

image 24.png

  1. Cancelを選択すれば空のコンポーネントが作成される

image 25.png

3.4.2 Stylized Textの追加

Repeater 1の中に Stylized text を2つ追加:

  • 同じくCancelを選択

image 26.png

3.4.3 TextareaとButtonの追加

次はTextareaButtonを追加

image 27.png

image 28.png

これで基本な画面コンポーネントを作成しました。

image 29.png

3.5 Frontend初期設定

3.5.1 Client state parametersの追加

左側パネルの Data and scriptsClient states で以下を追加:

1. userInput (JSON型, 初期値"{"botContent":"","userContent":""}") - ユーザー入力
2. conversationHistory (JSON型, 初期値"[]") - 会話履歴
3. processingPrompt (String型, 初期値"") - 処理中のユーザー入力保存用

image 30.png

⚠️ 重要:
実装手順ではuserInputはJSON型で初期値{"botContent":"","userContent":""}となっています。理論的には奇妙ですが、ServiceNowの内部処理で必要な設定のため、この通りに設定してください。

processingPromptの初期値を削除:

image 31.png

一旦これでOK。後ほどまだ編集します。
Save


Part 1の「概要とServiceNow基本設定編」はここまでです。基本的なScope作成とUI Builder画面構築が完了しました。
次のPart 2では、Backend設定(Script Include、Data Broker、ACL設定)を詳細に説明します。

Part 2: Backend設定編

4. Backend設定

4.1.1 Script Include作成

Backend処理の中核となるScript Includeを作成します。

  1. Filter navigatorで「Script Includes」を検索
  2. System Definition > Script Includes を選択

image 32.png

  1. 右上の「New」ボタンをクリック、新規作成

以下の情報を入力:

Name: SimpleLLMConnector

Script:

var SimpleLLMConnector = Class.create();
SimpleLLMConnector.prototype = {
    initialize: function() {
        // AWS API Gatewayのエンドポイントを設定
        this.apiEndpoint = 'YOUR_API_GATEWAY_URL'; // ここにAPI Gateway URLを入力
    },

    callLLM: function(userInput) {
        try {
            var request = new sn_ws.RESTMessageV2();
            request.setEndpoint(this.apiEndpoint);
            request.setHttpMethod('POST');
            request.setRequestHeader('Content-Type', 'application/json');

            var body = {
                prompt: userInput
            };
            request.setRequestBody(JSON.stringify(body));

            var response = request.execute();
            var statusCode = response.getStatusCode();

            if (statusCode == 200) {
                var responseBody = response.getBody();
                var jsonResponse = JSON.parse(responseBody);
                return jsonResponse.response || 'レスポンスが空です';
            } else {
                return 'エラー: ステータスコード ' + statusCode;
            }

        } catch (e) {
            gs.error('SimpleLLMConnector Error: ' + e.message);
            return 'システムエラーが発生しました: ' + e.message;
        }
    },

    type: 'SimpleLLMConnector'
};

重要な設定:

※initializeメソッド中の「YOUR_API_ENDPOINT_HERE」はAWSでのAPI Gateway設定後に引き換えが必要。

※Application scopeの設定、ここは必ずExperienceが作成されたScopeと一致する必要があります。

4.1.2 Script Includeの構成説明

  1. initialize() - 初期化
    • 現在は空の関数
    • 将来の拡張用に予約済み
    • インスタンス作成時に呼び出される
  2. callLLM() - メインメソッド
    • 入力: userInput(ユーザーからのテキスト)
    • 処理フロー:
      • AWS API Gatewayエンドポイントを定義(ハードコード)
      • RESTMessageV2オブジェクトを作成
      • HTTPメソッドをPOSTに設定
      • Content-Typeヘッダーを設定
      • リクエストボディを作成(prompt: userInput)
      • APIを実行
      • ステータスコードを確認
      • 成功時(200): JSONレスポンスを解析して返す
      • エラー時: エラーメッセージを返す
    • 出力: AI応答テキストまたはエラーメッセージ
  3. エラーハンドリング
    • try-catchブロックで例外をキャッチ
    • ステータスコードチェック
    • エラーログ記録(gs.error)
    • ユーザーフレンドリーなエラーメッセージ返却

技術仕様

エンドポイント: これからAWS側の設定で取得します

  • メソッド: POST
  • Content-Type: application/json

リクエスト形式:

{
  "prompt": "ユーザー入力テキスト"
}

レスポンス形式:

{
  "response": "AI応答テキスト"
}

依存関係

  • sn_ws.RESTMessageV2: ServiceNowのREST API呼び出しクラス
  • 認証: API Gatewayで処理

使用箇所

  • Data Broker Script: llm_chat のtransform関数内で使用

呼び出し方法:

var llm = new SimpleLLMConnector();
var response = llm.callLLM(userInput);

4.2 Data Brokerの作成

4.2.1 llm_chat Data Broker作成

  1. UI Builderに戻る
  2. 左側パネルの Data and scriptsData resources セクションで「+」をクリック

image 33.png

  1. +Create」を選択、「Transform」を選択

image 34.png

  1. 以下の情報を入力:

    Name: llm_chat

    Description: Simple LLM Chat Broker

    Properties:

    [
        {
            "name": "userInput",
            "type": "string"
        }
    ]
    

    Script:

    function transform(input) {
        var userInput = input.userInput || '';
    
        if (!userInput) {
            return { bot: 'エラー:入力がありません' };
        }
    
        // SimpleLLMConnectorを呼び出し
        var llm = new SimpleLLMConnector();
        var response = llm.callLLM(userInput);
    
        // 応答を返す
        return {
            bot: response
        };
    }
    

    Output schema:

    [
        {
            "name": "bot",
            "type": "string"
        }
    ]
    

    ACL Failure Result: Failure

    ⚠️ ここがポイント!

    • Mutates server data: ✅ チェックを入れる(必須)
    • Private: チェックなし

    image 35.png

    Submit をクリックして保存

    作成されたことを一覧から確認できます:

    image 36.png

4.2.2 llm_chat_messages Data Broker作成

同じ手順で、二つ目のData brokerを作成:

Name: llm_chat_messages

Description: Chat messages display broker for repeater

Properties:

[
    {
        "name": "conversationHistory",
        "type": "string"
    }
]

Script:

function transform(input) {
    gs.info('[CHAT_MESSAGES] ==================== START ====================');
    gs.info('[CHAT_MESSAGES] Input: ' + JSON.stringify(input));

    try {
        // 会話履歴を取得
        var conversationHistory = input.conversationHistory || [];

        gs.info('[CHAT_MESSAGES] conversationHistory length: ' + conversationHistory.length);

        // 会話履歴をそのまま返す
        if (conversationHistory && conversationHistory.length > 0) {
            gs.info('[CHAT_MESSAGES] Returning ' + conversationHistory.length + ' messages');
            return conversationHistory;
        }

        // 履歴がない場合は空配列を返す
        gs.info('[CHAT_MESSAGES] No messages, returning empty array');
        return [];

    } catch (e) {
        gs.error('[CHAT_MESSAGES] Error: ' + e.message);
        return [];
    }
}

Output schema:

[
    {
        "name": "userContent",
        "type": "string"
    },
    {
        "name": "botContent",
        "type": "string"
    }
]

ACL Failure Result: Failure

⚠️ ここがポイント!

  • Mutates server data: ☐ チェックを外す(重要)
  • Private: チェックなし

image 37.png

Submit をクリックして保存

一覧に戻ると、新規作成されたDataBrokerが確認できます:

image 38.png

4.3.1 ACL権限付与

追加されたData brokerはそのままでは直接使えないので、ACLから権限付与が必要です。

  1. Filter navigatorで「ACL」を検索
  2. System Security > Access Control (ACL) を選択

image 39.png

admin権限が足りないため、ロールをElevateします:

  1. 右上のプロファイルアイコンをクリック
  2. Elevate role を選択

image 40.png

  1. security_admin にチェック
  2. Update をクリック

image 41.png

Elevate後、新規追加のボタンが見えるようになります

image 42.png

4.3.2 llm_chat用ACL作成

  1. New ボタンをクリック

image 43.png

  1. 作成されたData brokerのsys_idが必要なため、まずData brokerを開いてsys_idを取得

image 44.png

  1. ACLの新規作成画面に戻って、以下を設定:
Type: ux_databroker
Name: 取得されたsys_idを入れる
Requires role: itil

image 45.png

提出

4.3.3 llm_chat_messages用ACL作成

もう一つのscriptも同じようにACLに追加します。

追加されたことを確認し、roleをadminに戻ります。

image 46.png

5. UI BuilderでFrontend設定完了

5.1 Data Brokerの追加と設定

UI Builderに戻ります。

  1. Data and scriptsData resources から先ほど作成した2つのData brokerが表示されることを確認

image 47.png

二つのData brokreを追加します。

image 48.png

  1. llm_chat_messagesの出力変数を設定:

    llm_chat_messages_1をクリック、パラメータフィールドが表示される

    image 49.png

    フィールドからBind dataを選択して、Data binding画面を開く

    image 50.png

    Client statesからconversationHistoryを選択、Apply

    image 51.png

    image 52.png

    一度Save、画面Refreshします。

5.2 Client Scripts作成

5.2.1 handleSend スクリプト

  1. Data and scripts パネルを開く
  2. Client scripts セクションで「+」をクリック
  3. handleSendという名前で以下のスクリプトを作成:
async function handler({api, event, helpers, imports}) {
    console.log('=== ボタンクリック ===');

    var input = api.state.userInput;
    console.log('入力値:', input);

    if (!input || input.trim() === '') {
        console.log('入力がありません');
        return;
    }

    // 処理中のユーザー入力を保存
    api.setState('processingPrompt', input);

    // 入力フィールドをクリア
    api.setState('userInput', '');

    // LLMを実行
    console.log('LLMを実行中...');
    await api.data.llm_chat_1.execute({
        userInput: input
    });
}

5.2.2 handleLLMResponse スクリプト

もう一つのScriptを追加:

Script name: handleLLMResponse

async function handler({api, event, helpers, imports}) {
    console.log('[RESPONSE] LLM応答トリガー');
    console.log('[RESPONSE] Event payload:', JSON.stringify(event.payload));

    try {
        // レスポンスデータを取得
        const response = event.payload.data?.output;
        const botMessage = response?.bot;
        const userMessage = api.state.processingPrompt; // processingPromptから取得

        console.log('[RESPONSE] Bot message:', botMessage);
        console.log('[RESPONSE] User message:', userMessage);

        if (!botMessage || !userMessage) {
            console.error('[RESPONSE] 必要なデータが不足しています');
            return;
        }

        // 現在の会話履歴を取得
        const history = api.state.conversationHistory || [];

        // 新しい会話を追加
        const newConversation = {
            userContent: userMessage,
            botContent: botMessage
        };

        history.push(newConversation);
        console.log('[RESPONSE] 新しい履歴数:', history.length);

        // 状態を更新
        api.setState('conversationHistory', history);
        api.setState('processingPrompt', ''); // 処理完了後にクリア

        console.log('[RESPONSE] 状態更新完了');

    } catch (error) {
        console.error('[RESPONSE] エラー:', error);
    }
}

これでClient scriptが作成されました。

image 53.png

5.3 コンポーネントのData Binding

5.3.1 Textarea (Input Field)

  1. Textareaを選択
  2. 右側の編集画面で「Value」に注目
  3. Bind data or use script」を開く

image 54.png

  1. userInput」を選択して、Apply

image 55.png

Eventsタブ設定:

  1. 一回保存、Refreshした後、もう一度Textareaを選択
  2. Eventsタブに移動
  3. Text entered」の「Add handler」をクリック

image 56.png

  1. Update client state parameter」を選択

image 57.png

  1. Client state名はuserInputに設定

image 58.png

  1. Value to use after triggeringはfieldValueに設定

image 59.png

Saveして、画面部分の設定は基本完了しました。

5.3.2 Button

  1. Buttonを選択
  2. 右側のPropertiesパネルで Events タブを開く
  3. Button clickedAdd handler

image 60.png

  1. Execute - Client scripthandleSendを選択

image 61.png

Addして設定完了

image 62.png

一旦Save。

image 63.png

5.3.3 Repeater

  1. Repeater 1を選択
  2. Data arrayのBind dataを開く

image 64.png

  1. Client statesからconversationHistoryを選択して、Apply

image 65.png

5.3.4 Stylized Text(Repeater内)

Stylized text 1:

  1. Textのエリアで「Bind data or use script」を選択

image 66.png

  1. Repeaterを選択して、valueをダブルクリック

image 67.png

※ここがポイントです!選択されたPillにさらにダブルクリック、そしたら手入力編集ができます。

  1. Pill viewで手動入力: @item.value.userContent

image 67.png

image 68.png

Stylized text 2:
同じように編集、Pill viewで手動入力: @item.value.botContent

image 69.png

忘れずに、Apply。

5.4 Data resourceとClient scriptの連携

  1. Data and scripts パネルを開く
  2. Data resources セクションで llm_chat_1 をクリック
  3. Eventsタブに移動

image 70.png

  1. Operation SucceededAdd handler

image 71.png

  1. handleLLMResponseを選択

image 72.png

Add。

これでllm_chat_1の動きをhandleLLMResponseと連携しました。

image 73.png

Configure設定:

  1. 一回保存して、もう一度llm_chat_1を開いて、Configureタグに移動
  2. When to evaluate this data resource」を「Only when invoked (explicit)」に設定

image 74.png

Saveします。


Part 2はここまでです。ServiceNow側のBackend設定とUI Builderの設定が完了しました。
Part 3では、AWS側の設定(Lambda、API Gateway、Bedrock)とテスト手順を説明します。

Part 3: AWS設定とテスト編

6. AWS側の設定

この後はAWS側の設定を行い、実際のEndpointを取得します。

6.1 Lambda関数作成

  1. AWSコンソールにログイン
  2. Lambdaコンソールを開く
  3. 関数の作成 ボタンをクリック

image 75.png

以下を設定:

「一から作成」 を選択
関数名: ServiceNowLLMChat
ランタイム: Python 3.11 または Python 3.12
アーキテクチャ: x86_64

関数の作成 をクリック

image 76.png

Getting startedのポップアップが表示されたら Dismiss をクリックして閉じる

image 77.png

デフォルトの lambda_function.py の内容を以下のコードに置き換え:

import json
import boto3
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
    """
    ServiceNowからのリクエストを処理し、Bedrockを呼び出す
    """
    try:
        # リクエストボディを解析
        if isinstance(event.get('body'), str):
            body = json.loads(event['body'])
        else:
            body = event.get('body', {})

        user_message = body.get('prompt', '')

        logger.info(f"Received message: {user_message}")

        if not user_message:
            return {
                'statusCode': 400,
                'headers': {
                    'Content-Type': 'application/json',
                    'Access-Control-Allow-Origin': '*'
                },
                'body': json.dumps({
                    'error': 'No message provided'
                })
            }

        # Bedrock clientを初期化
        bedrock = boto3.client(
            'bedrock-runtime',
            region_name='ap-southeast-2'  # 今回はシドニーリージョンを使います
        )

        # Claude 3を呼び出し
        response = bedrock.invoke_model(
            modelId='anthropic.claude-3-sonnet-20240229-v1:0',
            body=json.dumps({
                "anthropic_version": "bedrock-2023-05-31",
                "max_tokens": 1000,
                "messages": [
                    {
                        "role": "user",
                        "content": user_message
                    }
                ],
                "temperature": 0.7
            })
        )

        # レスポンスを解析
        response_body = json.loads(response['body'].read())
        ai_response = response_body['content'][0]['text']

        logger.info(f"AI response: {ai_response[:100]}...")

        return {
            'statusCode': 200,
            'headers': {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin': '*'
            },
            'body': json.dumps({
                'response': ai_response
            })
        }

    except Exception as e:
        logger.error(f"Error: {str(e)}")
        return {
            'statusCode': 500,
            'headers': {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin': '*'
            },
            'body': json.dumps({
                'error': str(e)
            })
        }

image 78.png

Deploy ボタンをクリックして保存

※ここは重要です!タイムアウト設定

LLMの反応は時間がかかるため、Lambda関数の設定を調整:

  1. コード編集区域下のタブで「設定」を開く

image 79.png

  1. 一般設定」→「編集
  2. タイムアウトをデフォルト3秒から30秒に変更

image 80.png

  1. 保存

6.2 権限設定

IAMロールの設定

  1. Lambda関数の「設定」タブを開く
  2. アクセス権限」を確認

image 81.png

  1. ロール名をクリックしてIAMコンソールを開く
  2. 許可」タブを開く
  3. 許可を追加」→「ポリシーをアタッチ」をクリック

image 82.png

  1. 検索ボックスに AmazonBedrockFullAccess を検索
  2. ポリシーを選択

image 83.png

  1. 許可を追加」をクリック

※注意: 本番環境では、より制限的なカスタムポリシーを作成することが推奨されます。

カスタムポリシーの参考例(今回は使わない):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "bedrock:InvokeModel"
            ],
            "Resource": "arn:aws:bedrock:ap-southeast-2::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0"
        }
    ]
}

これで一つのポリシーが追加しました。

image 84.png

もう一つのポリシーを追加します。今回は**「許可を追加」** ボタンをクリック、ドロップダウンから 「インラインポリシーを作成」 を選択、以下JSONを貼り付けます:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "bedrock:InvokeModel"
            ],
            "Resource": "arn:aws:bedrock:us-east-1:*:foundation-model/anthropic.claude-3-sonnet-20240229-v1:0"
        }
    ]
}

image 85.png

ポリシー名に「BedrockInvokePolicy」を入力、「ポリシーの作成」をクリック。

image 86.png

これでLambda関数がBedrockのClaude 3 Sonnetモデルを呼び出す権限が付与されます。

image 87.png

6.3 Bedrock設定

今回のLambda関数のコードでは claude-3-sonnet-20240229-v1:0 を指定しているので、Claude 3 Sonnet を有効化する必要があります。

※AWSのお知らせにより、2025年9月29日以降では、LLM機能使うためのモデル申請は不要になりました!直接使えるので、ここは参考までに。

  1. AWSコンソールでBedrockを検索
  2. Bedrockサービス画面を開く
  3. 左側メニューの最後のブロックから「モデルアクセス」を開く

image 88.png

  1. Claude 3 Sonnet の行の右側にある「リクエスト可能」をクリック

image 89.png

  1. 必要な情報を入力して使用申請

申請後、数分で承認されます(通常は即座に承認)

image 90.png

6.4 API Gateway設定(Endpoint取得)

6.4.1 API作成

  1. API Gatewayコンソールを開く
  2. APIを作成」をクリック

image 91.png

  1. REST API」を選択、「構築」をクリック

image 92.png

API設定:

API名: ServiceNowLLMChatAPI
説明 - オプション: ServiceNow UI BuilderからBedrock Claude3を呼び出すためのAPI
API エンドポイントタイプ: リージョン(そのまま)
IP アドレスのタイプ: IPv4(選択済みでOK)

image 93.png

API を作成」をクリック

6.4.2 リソース作成

  1. リソースを作成」ボタンをクリック

image 94.png

リソースパス: /
リソース名: chat
CORS: ✅ チェック入れ

image 95.png

作成」をクリック

image 96.png

6.4.3 メソッド作成

  1. 右側の「メソッドを作成」ボタンをクリック
メソッドタイプ: POST
統合タイプ: Lambda
関数名: ServiceNowLLMChat
リージョン: ap-southeast-2 ※今回のLambdaはシドニーリージョン

重要:

  • Lambdaプロキシ統合: ✅ チェック入れる(Trueにする)

image 97.png

画面の一番下にある「メソッドを作成」ボタンをクリック

image 98.png

POST methodが作成されました。

6.4.4 APIのデプロイ

  1. 画面右上のオレンジ色のボタン「APIをデプロイ」をクリック

image 99.png

デプロイ設定画面で以下を入力:

ステージ: *新しいステージ* を選択
ステージ名: prod と入力
説明(オプション): Production environment for ServiceNow LLM Chat

デプロイ」ボタンをクリック

Invoke URLの取得:

デプロイ後、ステージ詳細画面でInvoke URLが表示されます。

※API GatewayのエンドポイントURLの命名規則は以下です:

https://[API_ID].execute-api.[REGION].amazonaws.com/[STAGE]/[RESOURCE-PATH]

このURLをコピーして保存します。

7. ServiceNowでの最終設定

7.1 Endpoint追加

先ほど作成されたScript Includeに、AWS EndpointのパスをScript Includeに設定:

  1. ServiceNowに戻る
  2. System Definition > Script Includes で SimpleLLMConnector を開く
  3. initializeメソッドを以下のように修正:
initialize: function() {
    // AWS API Gatewayのエンドポイントを設定(ご自分のパスに変更してください)
    this.apiEndpoint = 'https://[API_ID].execute-api.[REGION].amazonaws.com/[STAGE]/[RESOURCE-PATH]';
},

デフォルト値として直接エンドポイントURLを設定しています。

Update で保存

8. テスト

8.1 Script Includeの単体テスト

  1. ServiceNowで System Definition > Scripts - Background に移動

image 100.png

  1. 以下のコードを入力:
var llm = new SimpleLLMConnector();
var response = llm.callLLM('Hello from ServiceNow');
gs.info('=== LLM Response ===');
gs.info(response);
gs.info('=== Test Complete ===');
  1. Run script をクリック

image 101.png

単体テストが成功すると、Claude 3からの応答がログに表示されます。

8.2 UI Builderでの統合テスト

  1. UI Builderに戻る
  2. 作成したページを開く
  3. Preview ボタンをクリックして実際の画面を確認
  4. Textareaに「This is a test」と入力

image 102.png

  1. Buttonをクリック
  2. しばらく待つと、Claude 3からの応答が表示される

image 103.png

見た目は雑な画面ですが、外部LLMとの連携機能はこれでできました。

9. トラブルシューティング

よくある問題と解決方法

1. CORS エラーが発生する場合

  • API GatewayでCORSが有効になっているか確認
  • Lambda関数のレスポンスヘッダーに 'Access-Control-Allow-Origin': '*' が含まれているか確認

2. タイムアウトエラーが発生する場合

  • Lambda関数のタイムアウト設定を30秒以上に設定
  • API Gatewayの統合タイムアウトも確認

3. Bedrock呼び出しエラー

  • モデルアクセスが承認されているか確認
  • リージョンが正しいか確認(ap-southeast-2)
  • IAMロールに適切な権限が付与されているか確認

4. Data Brokerが実行されない

  • ACL設定が正しく行われているか確認
  • Mutates server dataの設定が正しいか確認
  • スコープが一致しているか確認

10. 統合動作確認チェックリスト

  • Script IncludeにAPI GatewayのURLが設定されている
  • Lambda関数がデプロイされている
  • Bedrockモデルアクセスが承認されている
  • API Gatewayがデプロイされている
  • ACL権限が正しく設定されている
  • UI Builderの各コンポーネントが正しくバインドされている
  • Client Scriptsが正しく設定されている
  • CORSが両端(ServiceNowとAPI Gateway)で有効になっている

これで全3部の実装ガイドが完了しました。

ServiceNow UI BuilderとAWS Bedrock(Claude 3 Sonnet)を連携させたAIチャットボットが正常に動作するはずです。

お疲れ様でした!

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?