Skip to content

Commit 817a07c

Browse files
committed
[Sig Events] Add significant events management skill and tools
1 parent 13643da commit 817a07c

32 files changed

Lines changed: 1342 additions & 16 deletions

File tree

x-pack/platform/packages/shared/agent-builder/agent-builder-common/tools/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ export const platformStreamsSigEventsTools = {
5252
searchKnowledgeIndicators: `${internalNamespaces.platformStreams}.sig_events.ki_search`,
5353
createFeatureKnowledgeIndicator: `${internalNamespaces.platformStreams}.sig_events.ki_feature_create`,
5454
createQueryKnowledgeIndicator: `${internalNamespaces.platformStreams}.sig_events.ki_query_create`,
55+
searchEvent: `${internalNamespaces.platformStreams}.sig_events.event_search`,
56+
createEvent: `${internalNamespaces.platformStreams}.sig_events.event_create`,
57+
updateEventVerdict: `${internalNamespaces.platformStreams}.sig_events.event_verdict_update`,
5558
} as const;
5659

5760
export const attachmentTools = {

x-pack/platform/packages/shared/agent-builder/agent-builder-server/allow_lists.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ export const AGENT_BUILDER_BUILTIN_SKILLS = [
125125
// Platform – Streams
126126
'streams-management',
127127
'significant-events-memory',
128+
'significant-events-management',
128129
'knowledge-indicators-management',
129130
'ki-identification-management',
130131

x-pack/platform/packages/shared/kbn-streams-schema/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,14 @@ export {
302302
type Discovery,
303303
verdictSchema,
304304
type Verdict,
305+
SIG_EVENT_VERDICT_OPTIONS,
306+
SIG_EVENT_IMPACT_OPTIONS,
305307
sigEventSchema,
308+
sigEventVerdictSchema,
309+
sigEventImpactSchema,
306310
type SigEvent,
311+
type SigEventVerdict,
312+
type SigEventImpact,
307313
} from './src/sig_events';
308314
export type { OnboardingResult } from './src/onboarding';
309315
export { OnboardingStep } from './src/onboarding';

x-pack/platform/packages/shared/kbn-streams-schema/src/sig_events/events/index.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,33 @@ import {
1313
evidenceSchema,
1414
} from '../common_schemas';
1515

16+
export const SIG_EVENT_VERDICT_OPTIONS = ['promoted', 'acknowledged', 'demoted'] as const;
17+
export const sigEventVerdictSchema = z.enum(SIG_EVENT_VERDICT_OPTIONS);
18+
export type SigEventVerdict = z.infer<typeof sigEventVerdictSchema>;
19+
20+
export const SIG_EVENT_IMPACT_OPTIONS = ['critical', 'high', 'medium', 'low'] as const;
21+
export const sigEventImpactSchema = z.enum(SIG_EVENT_IMPACT_OPTIONS);
22+
export type SigEventImpact = z.infer<typeof sigEventImpactSchema>;
23+
1624
export const sigEventSchema = z.object({
1725
'@timestamp': z.iso.datetime(),
1826
created_at: z.iso.datetime(),
1927
event_id: z.string(),
20-
discovery_id: z.string(),
28+
discovery_id: z.string().optional(),
2129
discovery_slug: z.string(),
2230
previous_event_id: z.string().optional(),
23-
verdict: z.string(),
24-
verdict_id: z.string(),
25-
workflow_execution_id: z.string(),
26-
rule_names: z.array(z.string()),
31+
verdict: sigEventVerdictSchema,
32+
verdict_id: z.string().optional(),
33+
workflow_execution_id: z.string().optional(),
34+
rule_names: z.array(z.string()).optional(),
2735
stream_names: z.array(z.string()),
2836
title: z.string(),
2937
summary: z.string(),
3038
root_cause: z.string(),
3139
criticality: z.number(),
3240
confidence: z.number(),
3341
recommended_action: z.string(),
34-
impact: z.string(),
42+
impact: sigEventImpactSchema,
3543
recommendations: z.array(z.string()),
3644
dependency_edges: z.array(dependencyEdgeSchema).optional(),
3745
infra_components: z.array(infraComponentSchema).optional(),

x-pack/platform/packages/shared/kbn-streams-schema/src/sig_events/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,13 @@
88
export { detectionSchema, type Detection } from './detections';
99
export { discoverySchema, type Discovery } from './discoveries';
1010
export { verdictSchema, type Verdict } from './verdicts';
11-
export { sigEventSchema, type SigEvent } from './events';
11+
export {
12+
SIG_EVENT_VERDICT_OPTIONS,
13+
SIG_EVENT_IMPACT_OPTIONS,
14+
sigEventSchema,
15+
sigEventVerdictSchema,
16+
sigEventImpactSchema,
17+
type SigEvent,
18+
type SigEventVerdict,
19+
type SigEventImpact,
20+
} from './events';

x-pack/platform/plugins/shared/streams/server/agent_builder/skills/register_skills.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type { GetScopedClients } from '../../routes/types';
1111
import { streamsManagementSkill } from './streams_management_skill';
1212
import { knowledgeIndicatorsManagementSkill } from './knowledge_indicators_management';
1313
import { createKiIdentificationManagementSkill } from './ki_identification_management';
14+
import { sigEventsManagementSkill } from './sig_events_management';
1415

1516
export const registerAgentBuilderSkills = ({
1617
agentBuilder,
@@ -28,6 +29,7 @@ export const registerAgentBuilderSkills = ({
2829
const streamsSkills = [
2930
streamsManagementSkill,
3031
knowledgeIndicatorsManagementSkill,
32+
sigEventsManagementSkill,
3133
createKiIdentificationManagementSkill({ getScopedClients, telemetry }),
3234
];
3335

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Search, create, and update significant events for Streams, with guidance to avoid duplicates and keep event lifecycle state accurate.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { defineSkillType } from '@kbn/agent-builder-server/skills/type_definition';
9+
import {
10+
STREAMS_CREATE_EVENT_TOOL_ID,
11+
STREAMS_EVENT_VERDICT_UPDATE_TOOL_ID,
12+
STREAMS_SEARCH_EVENTS_TOOL_ID,
13+
} from '../../tools/register_tools';
14+
import description from './description.text';
15+
import content from './skill.md.text';
16+
17+
export const sigEventsManagementSkill = defineSkillType({
18+
id: 'significant-events-management',
19+
name: 'significant-events-management',
20+
basePath: 'skills/platform/streams',
21+
description,
22+
content,
23+
getRegistryTools: () => [
24+
STREAMS_SEARCH_EVENTS_TOOL_ID,
25+
STREAMS_CREATE_EVENT_TOOL_ID,
26+
STREAMS_EVENT_VERDICT_UPDATE_TOOL_ID,
27+
],
28+
});
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
You manage Significant Events (SigEvents) for Streams.
2+
3+
<significant_events_concept>
4+
What a Significant Event is:
5+
- A SigEvent is a durable incident-level summary of an important operational issue.
6+
- It captures what happened, why it happened, impact, confidence/criticality, and supporting context.
7+
- SigEvents should be actionable and non-duplicative.
8+
9+
Examples of conversation signals that may indicate a SigEvent:
10+
- Recurring service degradation with clear customer/user impact.
11+
- Security or compliance risk with confirmed evidence.
12+
- Cross-stream failures that share a common root cause.
13+
- Repeated alerting patterns that represent a known incident class.
14+
</significant_events_concept>
15+
16+
<available_tools>
17+
You have 3 SigEvents tools in this skill:
18+
19+
- `event_search`
20+
Use this first to find existing similar significant events.
21+
`query` is optional; if omitted (or empty), search uses optional stream and verdict filters only.
22+
`stream_name` is optional; omit it for cross-stream searches.
23+
24+
- `event_create`
25+
Use this only after confirming there is no similar existing event.
26+
The system generates internal identifiers and timestamps automatically.
27+
28+
- `event_verdict_update`
29+
Use this to update an existing event verdict to one of: `promoted`, `acknowledged`, `demoted`.
30+
If an event already has the requested verdict or is missing, update is ignored.
31+
32+
Additional globally-available helper guidance:
33+
- `ki_search` can be used to gather existing Knowledge Indicators (KIs) for context.
34+
- `execute_esql` can be used to confirm the event and collect evidence rows.
35+
</available_tools>
36+
37+
<required_workflow>
38+
Always follow this workflow:
39+
1. Detect potential significant-event signals from the conversation.
40+
2. Search existing events with `event_search` using optional stream scope and optional query.
41+
3. Compare returned events for semantic similarity (same issue class/root cause/impact).
42+
4. If a similar event exists, do not create a duplicate; reference the existing event.
43+
5. If no similar event exists, investigate and validate:
44+
- Use `ki_search` to collect related Feature and Query KIs.
45+
- Use `execute_esql` to confirm the issue and gather supporting facts.
46+
6. Create a new event with `event_create` using complete, high-quality event properties.
47+
48+
Verdict update workflow:
49+
1. Gather evidence supporting the target event state.
50+
2. Choose verdict based on intent:
51+
- `promoted`: incident-worthy and active.
52+
- `acknowledged`: known and actively tracked.
53+
- `demoted`: no longer incident-worthy.
54+
3. Call `event_verdict_update` with the event id and target verdict.
55+
4. Treat `{ updated: 0, ignored: 1 }` as expected when event is missing or already in the requested verdict.
56+
</required_workflow>
57+
58+
<proactive_behavior>
59+
Be proactive.
60+
61+
When conversation context and evidence strongly suggest a new significant event, suggest creating one.
62+
63+
Proactive pattern:
64+
1. State why current signals indicate a likely new significant event.
65+
2. Run `event_search` to check for similar existing events.
66+
3. If no similar event exists, recommend creating a new event and proceed with investigation/evidence collection.
67+
4. Use `event_create` with a complete payload.
68+
</proactive_behavior>
69+
70+
<ki_and_evidence_guidance>
71+
Using KIs for context:
72+
- Prefer KI context before writing root cause and impact.
73+
- Reuse KI terminology in `summary`, `root_cause`, and `impact` when relevant.
74+
75+
Using ES|QL for confirmation:
76+
- Run focused ES|QL queries that directly test the suspected issue.
77+
- Capture concise evidence in narrative form inside `summary`, `root_cause`, and `impact`.
78+
- If detailed evidence structures are needed, ensure tool support exists before attempting to submit them.
79+
</ki_and_evidence_guidance>
80+
81+
<sig_event_property_guidance>
82+
Populate event properties with care:
83+
84+
- `verdict`:
85+
- For new events, default to `promoted` unless user intent says otherwise.
86+
87+
- `title`:
88+
- Short, specific, human-readable incident title.
89+
90+
- `summary`:
91+
- Brief narrative: what happened, where, and key signal.
92+
93+
- `root_cause`:
94+
- Best-known causal explanation; avoid vague language.
95+
96+
- `stream_names`:
97+
- Include all affected streams.
98+
99+
- `criticality`:
100+
- Number in range 0..100 indicating system criticality.
101+
- Suggested scale:
102+
- 0-30 low
103+
- 31-60 medium
104+
- 61-80 high
105+
- 81-100 critical
106+
107+
- `confidence`:
108+
- Required. Float in range 0..1 indicating confidence in the event assessment.
109+
110+
- `impact`:
111+
- Always set to exactly one of: `critical`, `high`, `medium`, `low`.
112+
113+
- `recommended_action`:
114+
- Required. Short next operator action, ideally a single word (for example: `escalate`).
115+
116+
- `recommendations`:
117+
- Required. List of descriptive, detailed mitigation steps.
118+
</sig_event_property_guidance>
119+
120+
<tool_examples>
121+
Example: search existing events first
122+
Tool: `event_search`
123+
{
124+
"query": "checkout latency spike with timeout burst",
125+
"stream_name": "logs.checkout",
126+
"verdict": ["promoted", "acknowledged"]
127+
}
128+
129+
Example: filter-only search (no query text)
130+
Tool: `event_search`
131+
{
132+
"stream_name": "logs.checkout",
133+
"verdict": ["promoted", "acknowledged"]
134+
}
135+
136+
Example: cross-stream search (no stream_name)
137+
Tool: `event_search`
138+
{
139+
"query": "timeout burst",
140+
"verdict": ["promoted", "acknowledged"]
141+
}
142+
143+
Example: create a new significant event
144+
Tool: `event_create`
145+
{
146+
"verdict": "promoted",
147+
"title": "Checkout timeout spike under upstream latency",
148+
"summary": "Checkout experienced a sustained timeout spike correlated with upstream latency increase.",
149+
"root_cause": "Upstream dependency latency exceeded service timeout budget during peak load.",
150+
"stream_names": ["logs.checkout", "logs.payment"],
151+
"criticality": 86,
152+
"confidence": 0.84,
153+
"impact": "high",
154+
"recommended_action": "Scale checkout pods and increase upstream timeout budget temporarily.",
155+
"recommendations": [
156+
"Add alert on upstream latency threshold breach",
157+
"Review timeout configuration for checkout service"
158+
]
159+
}
160+
161+
Example: update an existing significant event verdict
162+
Tool: `event_verdict_update`
163+
{
164+
"event_id": "9c4d04a1-86fe-45c2-b1dd-00891a8ba9f1",
165+
"verdict": "acknowledged"
166+
}
167+
</tool_examples>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { createEventToolHandler } from './handler';
9+
10+
describe('createEventToolHandler', () => {
11+
it('creates a single event', async () => {
12+
const eventClient = {
13+
bulkCreate: jest.fn().mockResolvedValue({}),
14+
};
15+
16+
const result = await createEventToolHandler({
17+
eventClient: eventClient as never,
18+
eventInput: {
19+
title: 'T',
20+
summary: 'S',
21+
root_cause: 'R',
22+
stream_names: ['logs.a'],
23+
criticality: 60,
24+
impact: 'high',
25+
confidence: 0.7,
26+
recommended_action: 'escalate',
27+
recommendations: ['create incident'],
28+
},
29+
});
30+
31+
expect(eventClient.bulkCreate).toHaveBeenCalledTimes(1);
32+
expect(eventClient.bulkCreate).toHaveBeenCalledWith([
33+
expect.objectContaining({
34+
discovery_slug: expect.stringMatching(/^agent-event-[a-f0-9]{8}$/),
35+
}),
36+
]);
37+
expect(result.acknowledged).toBe(true);
38+
expect(result.event_id).toBeTruthy();
39+
});
40+
});

0 commit comments

Comments
 (0)