Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export const AGENT_BUILDER_BUILTIN_SKILLS = [
'significant-events-memory',
'knowledge-indicators-management',
'ki-identification-management',
'sig-events-management',

// Platform – Workflows
'workflow-authoring',
Expand Down
8 changes: 8 additions & 0 deletions x-pack/platform/packages/shared/kbn-streams-schema/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,14 @@ export {
INSIGHT_IMPACT_LEVEL_MAP,
getImpactLevel,
} from './src/insights';
export {
type SigEvent,
type SigEventVerdict,
sigEventSchema,
sigEventEvidenceSchema,
sigEventCauseKiSchema,
sigEventVerdictSchema,
} from './src/events';
export type { OnboardingResult } from './src/onboarding';
export { OnboardingStep } from './src/onboarding';
export { streamsOasDefinitions } from './src/oas_definitions';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { z } from '@kbn/zod/v4';

export const sigEventVerdictSchema = z.enum(['promoted', 'demoted', 'acknowledged']);
export type SigEventVerdict = z.infer<typeof sigEventVerdictSchema>;

export const sigEventEvidenceSchema = z.object({
stream_name: z.string().describe('Stream name where evidence was collected'),
rule_name: z.string().describe('Rule name used to identify this evidence'),
description: z.string().describe('Human-readable description of the evidence'),
esql_query: z
.string()
.describe('Valid ESQL query used to fetch event-related documents for investigation'),
confirmed: z
.boolean()
.describe('Whether the query was executed and confirmed that the issue exists'),
collected_at: z.string().datetime().describe('When the evidence confirmation was collected'),
row_count: z
.number()
.int()
.nonnegative()
.describe('Number of documents signaling the issue for this evidence'),
});

export const sigEventCauseKiSchema = z.object({
id: z.string().describe('Feature KI identifier'),
name: z.string().describe('Feature KI name'),
stream_name: z.string().describe('Stream name associated with the Feature KI'),
});

export const sigEventSchema = z.object({
id: z.string().describe('Unique identifier of the significant event'),
verdict: sigEventVerdictSchema.describe('Current promotion status of the significant event'),
title: z.string().describe('Human readable title of the event'),
summary: z.string().describe('Human readable short summary of the event'),
root_cause: z.string().describe('Human readable text describing the root cause of the event'),
stream_names: z.array(z.string()).describe('List of streams affected by the event'),
rule_names: z
.array(z.string())
.optional()
.describe('Optional list of rule names used to identify the event'),
workflow_execution_id: z
.string()
.optional()
.describe('Optional workflow execution identifier that produced this event'),
criticality: z
.number()
.min(0)
.max(1)
.describe('0 to 1 value of how critical this event is to the system'),
evidences: z
.array(sigEventEvidenceSchema)
.optional()
.describe('List of evidence objects with data about the event investigation'),
impact: z
.string()
.describe("Human readable text specifying the event's impact on the user's system"),
cause_kis: z
.array(sigEventCauseKiSchema)
.optional()
.describe('List of Feature KIs used to derive this event'),
});

export type SigEvent = z.infer<typeof sigEventSchema>;
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const registerStreamsAgentBuilder = async ({
isMemoryEnabled: () => Promise<boolean>;
}) => {
registerAgentBuilderTools({ agentBuilder, getScopedClients, server, logger, telemetry });
registerAgentBuilderSkills({ agentBuilder, getScopedClients, telemetry });
registerAgentBuilderSkills({ agentBuilder, getScopedClients, server, logger, telemetry });

const getMemoryService = () =>
new MemoryServiceImpl({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,27 @@
* 2.0.
*/

import type { Logger } from '@kbn/core/server';
import type { AgentBuilderPluginSetup } from '@kbn/agent-builder-plugin/server';
import type { EbtTelemetryClient } from '../../lib/telemetry/ebt';
import type { GetScopedClients } from '../../routes/types';
import type { StreamsServer } from '../../types';
import { streamsManagementSkill } from './streams_management_skill';
import { knowledgeIndicatorsManagementSkill } from './knowledge_indicators_management';
import { createKiIdentificationManagementSkill } from './ki_identification_management';
import { createSigEventsManagementSkill } from './sig_events_management';

export const registerAgentBuilderSkills = ({
agentBuilder,
getScopedClients,
server,
logger,
telemetry,
}: {
agentBuilder: AgentBuilderPluginSetup;
getScopedClients: GetScopedClients;
server: StreamsServer;
logger: Logger;
telemetry: EbtTelemetryClient;
}): void => {
if (!agentBuilder) {
Expand All @@ -28,6 +35,12 @@ export const registerAgentBuilderSkills = ({
const streamsSkills = [
streamsManagementSkill,
knowledgeIndicatorsManagementSkill,
createSigEventsManagementSkill({
getScopedClients,
server,
logger,
telemetry,
}),
createKiIdentificationManagementSkill({ getScopedClients, telemetry }),
];

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Identify, validate, and manage Streams Significant Events by searching existing events first and creating new events with validated evidence and structured context.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { defineSkillType } from '@kbn/agent-builder-server/skills/type_definition';
import type { Logger } from '@kbn/core/server';
import type { EbtTelemetryClient } from '../../../lib/telemetry/ebt';
import type { GetScopedClients } from '../../../routes/types';
import type { StreamsServer } from '../../../types';
import { createEventTool } from '../../tools/event_create/tool';
import { createDemoteEventTool } from '../../tools/event_demote/tool';
import { createSearchEventsTool } from '../../tools/event_search/tool';
import description from './description.text';
import content from './skill.md.text';

export const createSigEventsManagementSkill = ({
getScopedClients,
server,
logger,
telemetry,
}: {
getScopedClients: GetScopedClients;
server: StreamsServer;
logger: Logger;
telemetry: EbtTelemetryClient;
}) =>
defineSkillType({
id: 'sig-events-management',
name: 'sig-events-management',
basePath: 'skills/platform/streams',
description,
content,
getInlineTools: () => [
createSearchEventsTool({
getScopedClients,
server,
logger: logger.get('event_search_tool'),
}),
createEventTool({
getScopedClients,
server,
logger: logger.get('event_create_tool'),
telemetry,
}),
createDemoteEventTool({
getScopedClients,
server,
logger: logger.get('event_demote_tool'),
telemetry,
}),
],
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
You manage Significant Events (SigEvents) for Streams.

<significant_events_concept>
What a Significant Event is:
- A SigEvent is a durable incident-level summary of an important operational issue.
- It captures what happened, why it happened, impact, confidence/criticality, and evidence used to confirm it.
- SigEvents should be actionable and non-duplicative.

Examples of conversation signals that may indicate a SigEvent:
- Recurring service degradation with clear customer/user impact.
- Security or compliance risk with confirmed event evidence.
- Cross-stream failures that share a common root cause.
- Repeated alerting patterns that represent a known incident class.
</significant_events_concept>

<available_tools>
You have 3 SigEvents tools in this skill:

- `event_search`
Use this first to find existing similar significant events.
`query` is optional; if omitted (or empty), search uses stream and verdict filters only.

- `event_create`
Use this only after confirming there is no similar existing event.
This tool generates event id automatically.

- `event_demote`
Use this to demote an existing event when it is no longer incident-worthy.
If an event is already demoted or missing, demotion is ignored.

Additional globally-available helper guidance:
- `ki_search` can be used to gather existing Knowledge Indicators (KIs) for context.
- `execute_esql` can be used to confirm the event and collect evidence rows.
</available_tools>

<required_workflow>
Always follow this workflow:
1. Detect potential significant-event signals from the conversation.
2. Search existing events with `event_search` using the target stream and optional query.
3. Compare returned events for semantic similarity (same issue class/root cause/impact).
4. If a similar event exists, do not create a duplicate; reference the existing event.
5. If no similar event exists, investigate and validate:
- Use `ki_search` to collect related Feature and Query KIs.
- Use `execute_esql` to confirm the issue and capture supporting evidence.
6. Create a new event with `event_create` including complete, high-quality SigEvent properties.

Demotion workflow:
1. Collect evidence that an existing promoted sig event was resolved and can be deprioritized
1. Ask user for confirmation before demoting the event, unless user asks for it explicitly
2. Call `event_demote` with the event id.
3. Treat `{ demoted: 0, ignored: 1 }` as expected when event is missing or already demoted.
</required_workflow>

<proactive_behavior>
Be proactive.

When conversation context and evidence strongly suggest a new significant event, suggest creating one.

Proactive pattern:
1. State why current signals indicate a likely new significant event.
2. Run `event_search` to check for similar existing events.
3. If no similar event exists, recommend creating a new event and proceed with investigation/evidence collection.
4. Use `event_create` with a complete payload.
</proactive_behavior>

<ki_and_evidence_guidance>
Using KIs for context:
- Prefer KI context before writing root cause and impact.
- Reuse KI terminology in `summary`, `root_cause`, and `impact` when relevant.

Using ES|QL for confirmation:
- Run focused ES|QL queries that directly test the suspected issue.
- For each evidence item in `evidences`, include:
- `stream_name`: stream where evidence was collected
- `rule_name`: related rule/query name when available
- `description`: what the query proved
- `esql_query`: exact ES|QL query used
- `confirmed`: set true when query output confirms the issue
- `row_count`: number of matching/problematic rows
- `collected_at`: ISO timestamp when evidence was collected
</ki_and_evidence_guidance>

<sig_event_property_guidance>
Populate all required SigEvent fields with care:

- `verdict`:
- Always set new events to `promoted` when calling `event_create`.

- `title`:
- Short, specific, human-readable incident title.

- `summary`:
- Brief narrative: what happened, where, and key signal.

- `root_cause`:
- Best-known causal explanation; avoid vague language.

- `stream_names`:
- Include all affected streams.

- `rule_names`:
- Include names of query KIs/rules that were part of the investigation and contributed to event identification.

- `workflow_execution_id` (optional):
- Include when event creation is tied to a known workflow execution.

- `criticality`:
- Float in range 0..1 indicating system criticality.
- Suggested scale:
- 0.0-0.3 low
- 0.31-0.6 medium
- 0.61-0.8 high
- 0.81-1.0 critical

- `impact`:
- Human-readable statement of user/business/system impact.

- `cause_kis`:
- Include Feature KIs involved in investigation and causally related to the event.
- Each item includes `id`, `name`, `stream_name`.

- `evidences`:
- Include one or more validated evidence records.
- Use `confirmed: true` only after query confirmation.
</sig_event_property_guidance>

<tool_examples>
Example: search existing events first
Tool: `event_search`
{
"query": "checkout latency spike with timeout burst",
"stream_name": "logs.checkout",
"verdict": ["promoted", "acknowledged"]
}

Example: filter-only search (no query text)
Tool: `event_search`
{
"stream_name": "logs.checkout",
"verdict": ["promoted", "acknowledged"]
}

Example: create a new significant event (no id; generated by tool)
Tool: `event_create`
{
"verdict": "promoted",
"title": "Checkout timeout spike under upstream latency",
"summary": "Checkout experienced a sustained timeout spike correlated with upstream latency increase.",
"root_cause": "Upstream dependency latency exceeded service timeout budget during peak load.",
"stream_names": ["logs.checkout", "logs.payment"],
"rule_names": ["Checkout timeout burst detector"],
"workflow_execution_id": "wf-1e3135d9-16cb-4017-b5f6-c7df5a22f981",
"criticality": 0.86,
"impact": "Increased checkout failures and degraded conversion during the affected interval.",
"evidences": [
{
"stream_name": "logs.checkout",
"rule_name": "Checkout timeout burst detector",
"description": "ES|QL confirms timeout errors sharply increased in the last 30 minutes.",
"esql_query": "FROM logs.checkout, logs.checkout.* | WHERE event.outcome == \"failure\" AND error.type == \"timeout\" | STATS failures = COUNT(*)",
"confirmed": true,
"collected_at": "2026-05-01T12:34:56.000Z",
"row_count": 124
}
],
"cause_kis": [
{
"id": "checkout_timeout_spike",
"name": "checkout-timeout-pattern",
"stream_name": "logs.checkout"
}
]
}

Example: demote an existing significant event
Tool: `event_demote`
{
"event_id": "9c4d04a1-86fe-45c2-b1dd-00891a8ba9f1"
}
</tool_examples>
Loading
Loading