2
0

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のインシデントからAIエージェントでElasticのオブザーバビリティ調査を行う設定

2
Posted at

はじめに

ServiceNowのインシデントからElasticのAIエージェントを呼び出しの一例です。
インシデントに記録した内容を元に、必要に応じてAIエージェントにオブザーバービリティ分析してもらうことが実現できます。
ServiceNowは使い慣れてないのですがGeminiに教えてもらいながら試したので、最適な実装ではないかもしれませんがご了承ください。

SerivceNowのバージョンはZurichで実施しています。

コンポーネント間の流れ

インシデントの内容について、ElasticのAI Agentに調査をしてもらい、返ってきた結果を記録するというものです。

[ServiceNow Incident]
        │
        ▼
[UI Action (Manual Trigger)]
        │
        ▼
[ServiceNow Flow Designer (Subflow)]
        │
        ▼
[ServiceNow Action (Integration Step)]
        │
        ▼
[Elastic Workflow (Orchestration)]
        │
        ▼
[Elastic AI Agent (Agent Builder)]
        │
        ▼
[Elasticsearch Observability Data]

Elastic側の構成手順

Elastic Workflow

以下の定義のWorkflowを保存します。これのURLに含まれるWorkflow IDは後ほどServiceNowから呼び出すためにコピーしておいてください。

name: test_servicenow
enabled: true
triggers:
  - type: manual
inputs:
  - name: incident_number
    type: string
    required: true
  - name: incident_sys_id
    type: string
    required: true
  - name: short_description
    type: string
    required: true
  - name: priority
    type: string
    required: true

steps:
  - name: console
    type: console
    with:
      message: "{{inputs.incident_number}} {{inputs.incident_sys_id}} {{inputs.priority}} {{inputs.short_description}}"
  - name: check_with_ai_agent
    type: ai.agent
    with:
      message: "Output in plain text format and **NO** markdown. Check index: kibana_sample_data_flights and get information of: {{ inputs.short_description }}"

  - name: post_to_snow
    type: http
    with:
      url: "https://<Your ServiceNow ID domain>/api/now/table/incident/{{ inputs.incident_sys_id }}"
      method: PATCH
      headers:
        Authorization: "Basic <Your user:password base64>"
        Content-Type: "application/json"
      body: '{"work_notes": "{{ steps.check_with_ai_agent.output.message | replace: "\n", "\\n"}}"}'

上のBasicのキーはusername:passwordをbase64エンコードしたものをセットします。
今回はServiceNowのadminとそのパスワードでとりあえず実施。(Macならecho -n "admin:xxx" | base64の出力を利用)

ServiceNow側の構成手順

System Definition > Script Includes

CleanShot 2026-04-16 at 09.55.20.png

// Script Include: ElasticKibanaHelper
// Scope: Global
// Client callable: false

var ElasticKibanaHelper = Class.create();

ElasticKibanaHelper.prototype = {

    initialize: function() {
        this.baseUrl    = 'https://<xxx>.elastic.cloud';
        this.apiKey     = gs.getProperty('elastic.kibana.api_key', '');
        this.timeout    = 30000; // 30 seconds
    },

    /**
     * Trigger a Kibana Workflow by ID.
     *
     * @param  {String} workflowId  - The Kibana workflow ID to run
     * @param  {Object} bodyParams  - Optional JSON payload to send with the request
     * @returns {Object}            - { success: Boolean, status: Number, body: Object, error: String }
     */
    runWorkflow: function(workflowId, bodyParams) {

        if (!workflowId) {
            return this._error('workflowId is required');
        }

        if (!this.apiKey) {
            gs.error('ElasticKibanaHelper: elastic.kibana.api_key system property is not set');
            return this._error('API key not configured. Set the elastic.kibana.api_key system property.');
        }

        var endpoint = this.baseUrl + '/api/workflows/workflow/' + workflowId + '/run';
        var payload = JSON.stringify({
			inputs: bodyParams || {}
		});

        try {
            var request = new sn_ws.RESTMessageV2();
            request.setEndpoint(endpoint);
            request.setHttpMethod('POST');

            // ── Authentication ──────────────────────────────────────────────
            request.setRequestHeader('Authorization', 'ApiKey ' + this.apiKey);

            // ── Standard headers ────────────────────────────────────────────
            request.setRequestHeader('Content-Type',  'application/json');
            request.setRequestHeader('kbn-xsrf',      'true');   // Required by Kibana REST API

            // ── Body ────────────────────────────────────────────────────────
            request.setRequestBody(payload);

            // Timeout
            request.setEccParameter('connect_timeout', this.timeout);
            request.setEccParameter('read_timeout',    this.timeout);

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

            gs.info(
                'ElasticKibanaHelper.runWorkflow | workflowId=' + workflowId +
                ' | status=' + statusCode
            );

            var parsedBody = {};
            try { parsedBody = JSON.parse(bodyText); } catch(e) { parsedBody = { raw: bodyText }; }

            if (statusCode >= 200 && statusCode < 300) {
                return {
                    success:    true,
                    status:     statusCode,
                    body:       parsedBody,
                    error:      null
                };
            }

            gs.error(
                'ElasticKibanaHelper.runWorkflow: HTTP ' + statusCode +
                ' for workflowId=' + workflowId + ' | body=' + bodyText
            );

            return {
                success: false,
                status:  statusCode,
                body:    parsedBody,
                error:   'HTTP ' + statusCode + ': ' + (parsedBody.message || bodyText)
            };

        } catch(ex) {
            gs.error('ElasticKibanaHelper.runWorkflow exception: ' + ex.message);
            return this._error(ex.message);
        }
    },

    // ── Private helpers ───────────────────────────────────────────────────────

    _error: function(msg) {
        return { success: false, status: null, body: null, error: msg };
    },

    type: 'ElasticKibanaHelper'
};

ServiceNow メニュー sys_properties.listからElasticの認証APIキー設定

elastic.kibana.api_key
CleanShot 2026-04-21 at 19.20.27@2x.png

Flow Designer (Workflow Studio) > Actions

Inputs

CleanShot 2026-04-21 at 17.59.28@2x.png

Scirpt - Input Variables

CleanShot 2026-04-21 at 18.01.44@2x.png

Script- Script

CleanShot 2026-04-21 at 18.02.22@2x.png

// Flow Designer Action Script Step
// Action name: Run Elastic Kibana Workflow
// Step name:   Invoke Kibana Workflow API
//
// Inputs (mapped from Action Inputs above):
//   inputs.workflow_id        → String
//   inputs.incident_number    → String
//   inputs.incident_sys_id    → String
//   inputs.short_description  → String
//   inputs.priority           → String
//
// Outputs to set:
//   outputs.success           → Boolean
//   outputs.response_status   → Integer
//   outputs.response_body     → String
//   outputs.error_message     → String

(function execute(inputs, outputs) {

    var helper = new ElasticKibanaHelper();

    // Build the payload sent to Kibana
    var payload = {
        source:            'ServiceNow',
        incident_number:   inputs.incident_number  || '',
        incident_sys_id:   inputs.incident_sys_id  || '',
        short_description: inputs.short_description || '',
        priority:          inputs.priority          || '',
        triggered_at:      new GlideDateTime().getDisplayValue()
    };

    var result = helper.runWorkflow(inputs.workflow_id, payload);

    // ── Map results to Action outputs ────────────────────────────────────────
    outputs.success         = result.success;
    outputs.response_status = result.status   ? String(result.status) : '';
    outputs.response_body   = result.body     ? JSON.stringify(result.body) : '';
    outputs.error_message   = result.error    ? result.error : '';

    if (!result.success) {
        // Surface the error in the flow execution log
        gs.error(
            'Run Elastic Kibana Workflow action failed | ' +
            'incident=' + inputs.incident_number +
            ' | workflowId=' + inputs.workflow_id +
            ' | error=' + result.error
        );
    }

})(inputs, outputs);

Script- Output Variables

CleanShot 2026-04-21 at 18.02.36@2x.png

Flow Designer (Workflow Studio) > Subflows

CleanShot 2026-04-21 at 18.33.56@2x.png

実行するElastic WorkflowsのIDを固定で入れています。
CleanShot 2026-04-21 at 18.05.15@2x.png

All > System Definitions > UI Actions

Form buttonにチェックして、Scriptを設定。
CleanShot 2026-04-21 at 18.11.59@2x.png

(function() {
    try {
        var inputs = {};
        // Set "current" to the "Name" defined in the Subflow Input (e.g., incident_record)
        inputs['incident_record'] = current; 

        // Test with "synchronous execution" that is guaranteed to work
        // * Be sure to use the Internal Name copied from the Subflow Properties for 'global.xxx'
        var result = sn_fd.FlowAPI.executeSubflow('global.from_button_trigger_elastic_investigation', inputs);
        
        // For synchronous execution, you can directly retrieve information from the returned object
        gs.addInfoMessage('Executed Subflow');

    } catch (ex) {
        // Force display of the error type and details
        var errorDetail = (ex.message) ? ex.message : ex.toString();
        gs.addErrorMessage('[Debug] Error details: ' + errorDetail);
        
        // Also output detailed information to the system log (sys_log)
        gs.error('Subflow Debug: ' + errorDetail);
    }

    // Keep the current screen
    action.setRedirectURL(current);
})();

動作テスト!

ServiceNow - Incident作成してください。

  • Execute data investigation in Elastic AIのボタンが右上にあること。
  • Short descriptionがElasticのAI Agentへの調査依頼内容になる。

一度Incident保存してから、また開いてボタンを実行します。

CleanShot 2026-04-21 at 18.40.50@2x.png

Executed Subflowと出ること確認
CleanShot 2026-04-21 at 18.41.22@2x.png

Elastic Workflowが正常実行されることを確認
CleanShot 2026-04-21 at 19.38.57@2x.png

IncidentにElasticのAIエージェントから結果が返ってくることを確認
CleanShot 2026-04-21 at 19.39.19@2x.png

おわり

AIエージェントがない時代ではこのような連携を行っても返せるデータは限定的でした。しかし今はAIエージェントで色々な分析を行ってもらって人が読みやすい形で返してくれるので、インシデント管理にも使いやすくなったと思います。

2
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?