将 ServiceNow 事件与 Elastic AI Agents 集成用于可观测性分析
It looks like the text you’d like translated didn’t come through. Could you please paste the content you want translated (excluding the source line you already provided)? Once I have the full text, I’ll translate it into Simplified Chinese while preserving the formatting and markdown.
介绍
这是一个在 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 身份验证 – 设置 username:password 的 Base64 编码字符串。
测试时可以使用管理员凭据,例如:
echo -n "admin:yourPassword" | base64
脚本包含: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 };
}
};
注意: 上述脚本中要执行的 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);
})();
验证步骤
- Create an Incident in ServiceNow。
- 验证在事件表单右上角是否出现 “Execute data investigation in Elastic AI” 按钮。
- Short description 字段将作为发送给 Elastic AI Agent 的调查请求。
- Save 事件后,重新打开并点击该按钮。
预期结果
- 显示一个 toast/消息 “Executed Subflow”。
- Elastic 工作流成功运行。
- Elastic AI Agent 的结果返回并填充到事件记录中。
Context
在 AI 代理出现之前,集成仅返回有限的数据。
现在,AI 代理能够执行复杂的分析,并以人类可读的格式返回结果,显著提升事件管理的有效性。