ServiceNow 인시던트를 Elastic AI Agents와 통합하여 Observability 분석
I’m happy to help translate the article, but I’ll need the full text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source line unchanged and translate the rest into Korean while preserving all formatting, markdown, and code blocks.
소개
이는 ServiceNow 인시던트에서 Elastic AI Agent를 호출하는 예시입니다.
사용된 ServiceNow 버전은 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 워크플로 정의
다음 정의를 사용하여 워크플로를 저장하십시오. 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:///api/now/table/incident/{{ inputs.incident_sys_id }}"
method: PATCH
headers:
Authorization: "Basic "
Content-Type: "application/json"
body: '{"work_notes": "{{ steps.check_with_ai_agent.output.message | replace: "\n", "\\n"}}"}'
Basic authentication – username:password 문자열을 Base64로 인코딩한 값을 설정합니다.
테스트용으로는 관리자 계정을 사용할 수 있습니다. 예:
echo -n "admin:yourPassword" | base64
Script Include: ElasticKibanaHelper
// Script Include: ElasticKibanaHelper
// Scope: Global
// Client callable: false
var ElasticKibanaHelper = Class.create();
ElasticKibanaHelper.prototype = {
initialize: function() {
this.baseUrl = 'https://.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 };
} else {
return this._error('Request failed', statusCode, parsedBody);
}
} catch (ex) {
return this._error('Exception: ' + ex.message);
}
},
_error: function(message, status, body) {
return { success: false, status: status || 0, body: body || null, error: message };
}
};
Note: 실행될 Elastic 워크플로우의 ID는 위 스크립트에 하드코딩되어 있습니다.
폼 버튼 스크립트
(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에서 Create an Incident를 수행합니다.
- 인시던트 양식 오른쪽 상단에 “Execute data investigation in Elastic AI” 버튼이 표시되는지 확인합니다.
- Short description 필드는 Elastic AI Agent에 전송되는 조사 요청으로 사용됩니다.
- 인시던트를 Save한 뒤 다시 열고 버튼을 클릭합니다.
기대 결과
- 토스트/메시지 “Executed Subflow” 가 표시됩니다.
- Elastic Workflow가 성공적으로 실행됩니다.
- Elastic AI Agent의 결과가 반환되어 인시던트 레코드에 채워집니다.
맥락
AI 에이전트가 등장하기 전에는 통합이 제한된 데이터만 반환했습니다.
이제 AI 에이전트는 정교한 분석을 수행하고 인간이 읽을 수 있는 형식으로 결과를 반환하여 사고 관리 효율성을 크게 향상시킵니다.