YAML rule schema reference for Kibana Universal Alerting
Kibana Universal Alerting YAML rule definitions accept the following fields. For authoring guidance, refer to Create an ES|QL rule.
These fields are required on every rule.
query.format determines which additional query fields are required.
| Field | Type | Accepted values | Description |
|---|---|---|---|
kind |
string | alert or signal |
Whether the rule tracks ongoing alerts (alert) or records point-in-time observations (signal). Set when the rule is created and can't be modified when editing the rule. |
metadata.name |
string | Any string | The name of the rule. Max 256 characters. |
schedule.every |
duration | Any duration string | How often the rule runs. For example: 5s, 1m, 5m. Minimum interval applies. |
query.base
|
ES|QL string | Any ES|QL query | The query that selects the data the rule evaluates. |
query.format
|
string | composed or standalone |
The query structure the rule uses. standalone means each condition (breach, recovery, no-data) is a separate, self-contained ES|QL query. composed means you write one base query and each condition is a pipe segment appended to it. The UI always creates standalone rules. |
kind: alert also require the recovery and no_data objects. The rule APIs reject an alert rule that omits either one. If you omit them in the YAML editor of the rule form, Kibana fills in strategy: no_breach for recovery and strategy: ignore for no_data.
Every rule has one base query that selects the data to evaluate. To match only some rows, add a breach segment. Without one, every row that query.base returns is a match.
| Field | Type | Description |
|---|---|---|
query.base |
ES|QL string | The ES|QL query that selects the data to evaluate. Must include a FROM clause. Kibana applies the time filter from schedule.lookback using time_field. Required. |
query.breach.segment |
ES|QL segment string | An optional ES|QL clause that Kibana appends to query.base, for example WHERE avg_cpu > 0.85. Don't include a FROM clause. |
Several settings depend on the breach segment:
- To use the
conditionrecovery strategy, setquery.breach. Refer to Recovery strategy. - To use a no-data strategy other than
ignore, setquery.breachorno_data.query. Refer to No-data strategy.
In 9.5, query.format selects one of two query structures.
Fields for query.format: composed
Use composed when breach, recovery, and no-data conditions all start from the same data shape. Define that shape once in the base query and each condition adds only what differs.
| Field | Type | Description |
|---|---|---|
query.base |
ES|QL string | Base query that runs on every evaluation. Time filters are applied automatically using the lookback window. Required. |
query.breach.segment |
ES|QL segment string | ES|QL segment appended to the base query for breach detection. Written as a pipe command, for example \| WHERE count > 5. Required. |
query.recovery.segment |
ES|QL segment string | ES|QL segment appended to the base query for recovery detection. Required when recovery_strategy is query. |
Fields for query.format: standalone
Use standalone when conditions need full independence. Each query can target different indices, apply different filters, or return a completely different shape.
| Field | Type | Description |
|---|---|---|
query.breach.query |
Full ES|QL string | Full ES|QL query for breach detection. Required. |
query.recovery.query |
Full ES|QL string | Full ES|QL query for recovery detection. Required when recovery_strategy is query. |
query.no_data.query |
Full ES|QL string | Full ES|QL query that detects presence of data. Required when no_data_strategy is not none. Only supported on standalone format. |
These optional fields add descriptive information to a rule for identification and filtering, and link the rule to action policies. None affect rule evaluation behavior.
| Field | Type | Accepted values | Description |
|---|---|---|---|
metadata.description |
string | Any string | Optional description of what the rule monitors. Max 1,024 characters. |
metadata.owner
|
string | Any string | Team or person responsible for the rule. Max 256 characters. |
metadata.tags |
array of strings | Array of strings | Labels for filtering and organization. Max 20 tags, each max 128 characters. |
metadata.routing_tags
|
array of strings | Array of strings | Tags that link the rule's alerts to action policies. An action policy applies when it has at least one of these tags. Only valid when kind: alert. Max 20 tags, each max 128 characters. To learn more, refer to Add routing tags to a rule. |
These fields control how far back each evaluation looks and which timestamp field is used for the time range filter. Both are optional, but omitting schedule.lookback means the query runs without a time bound.
| Field | Type | Accepted values | Description |
|---|---|---|---|
schedule.lookback |
duration | Any duration string | How far back in time the query searches on each run. For example: 5m, 24h. |
time_field |
string | Any field name | The timestamp field used for the lookback window filter. Max 128 characters. Defaults to @timestamp. |
The recovery object controls how Kibana detects that an alert has recovered. It's required when kind: alert, and strategy selects the behavior.
| Field | Type | Accepted values | Description |
|---|---|---|---|
recovery.strategy |
string | no_breach, condition, query, or manual |
How recovery is detected. - no_breach: Recovers an alert when its group no longer appears in the breach results. - condition: Recovers an alert when query.base plus recovery.segment returns the group. Requires query.breach. - query: Recovers an alert when recovery.query returns the group. - manual: Doesn't recover automatically. Close the alert with a user action. |
recovery.segment |
ES|QL segment string | Any ES|QL clause | Required when strategy is condition. An ES|QL clause that Kibana appends to query.base, for example WHERE avg_cpu < 0.60. Don't include a FROM clause. |
recovery.query |
ES|QL string | Any ES|QL query | Required when strategy is query. An independent ES|QL query with its own FROM clause. A group that this query returns recovers its alert. |
The condition strategy requires query.breach. Without a breach segment, every row of query.base already matches, so the recovery condition could only return groups that are still breaching.
Rules with kind: signal can't set recovery. A rule with strategy: manual can't set state_transition.recovering, because the recovery delay has no effect when alerts never recover on their own.
The recovery_strategy field is optional. When omitted, the rule emits no recovery events and active alerts don't close automatically.
| Field | Type | Accepted values | Description |
|---|---|---|---|
recovery_strategy |
string | no_breach, query, or none |
How recovery is detected. - no_breach: Recovers an alert when its active group no longer appears in the breach results. - query: Evaluates a separate recovery query defined in query.recovery.segment (composed) or query.recovery.query (standalone) - none: Turns off recovery. |
Rules with kind: signal must omit recovery_strategy or set it to none. Any other value fails validation.
Only valid when kind: alert. Controls how many consecutive detections are required before an alert becomes active or recovers.
State transition settings are nested objects. state_transition.pending delays when an alert opens, and state_transition.recovering delays when an alert closes. In each object, set count, timeframe, or both.
| Field | Type | Accepted values | Description |
|---|---|---|---|
state_transition.pending.count |
integer | Integer, 0–1000 | Consecutive matches the alert spends in pending before it becomes active on the next match. For example, 2 opens the alert on the third consecutive match. Set to 0 to open it on the first match. |
state_transition.pending.timeframe |
duration | Any duration string | How long the condition must hold before the alert becomes active. For example: 5m. |
state_transition.pending.operator |
string | and or or |
Allowed only when you set both count and timeframe. and requires both and or requires either. Defaults to or. |
state_transition.recovering.count |
integer | Integer, 0–1000 | Consecutive recoveries the alert spends in recovering before it becomes inactive on the next recovery. For example, 2 closes the alert on the third consecutive recovery. Set to 0 to close it on the first recovery. |
state_transition.recovering.timeframe |
duration | Any duration string | How long the condition must hold before the alert recovers. For example: 5m. |
state_transition.recovering.operator |
string | and or or |
Allowed only when you set both count and timeframe. and requires both and or requires either. Defaults to or. |
state_transition:
pending:
count: 2
timeframe: 5m
operator: and
recovering:
count: 1
| Field | Type | Accepted values | Description |
|---|---|---|---|
state_transition.pending_operator |
string | AND or OR |
Whether both the count and timeframe must be met (AND) or either one (OR) before becoming active. |
state_transition.pending_count |
integer | Integer, 0–1000 | Number of consecutive breaches required before the alert becomes active. Set to 0 to skip the pending phase and transition directly to active on the first breach. |
state_transition.pending_timeframe |
duration | Any duration string | How long the condition must remain continuously breached before the alert becomes active. For example: 5m. |
state_transition.recovering_operator |
string | AND or OR |
Whether both the count and timeframe must be met (AND) or either one (OR) before recovering. |
state_transition.recovering_count |
integer | Integer, 0–1000 | Number of consecutive clear evaluations required before the alert recovers. Set to 0 to skip the recovering phase and transition directly to inactive on recovery. |
state_transition.recovering_timeframe |
duration | Any duration string | How long the condition must remain continuously non-breaching before the alert recovers. For example: 5m. |
Use grouping to split a rule's detections into independent series, one per unique combination of field values. This lets a single rule track multiple subjects without creating a separate rule for each, for example, tracking CPU usage per host. Each series maintains its own alert lifecycle.
| Field | Type | Accepted values | Description |
|---|---|---|---|
grouping.fields |
array of strings | Array of field names | Fields to group results by. Each unique combination becomes its own series. Max 16 fields, each max 256 characters. |
When a data source goes silent, a quiet source and a healthy one can look the same to a rule. The no-data setting controls what the rule does with an alert when its group has no data.
The no_data object is required when kind: alert, and strategy selects the behavior.
| Field | Type | Accepted values | Description |
|---|---|---|---|
no_data.strategy |
string | ignore, keep_last, or resolve |
What happens when a group has no data. - ignore: Doesn't check whether a group still has data. Missing groups don't produce no_data events. - keep_last: Holds the alert's current status. - resolve: Closes the alert the first time the rule finds no data for the group. |
no_data.query |
ES|QL string | Any ES|QL query | Optional presence query that checks whether a group has data. Allowed with keep_last and resolve. If you omit it, Kibana uses query.base as the presence query. |
A strategy other than ignore requires query.breach or no_data.query. That way, Kibana can tell a group with no data apart from a group that stopped breaching.
Rules with kind: signal can't set no_data.
Use no_data_strategy to control what the rule does when an evaluation returns no results.
| Field | Type | Accepted values | Description |
|---|---|---|---|
no_data_strategy |
string | emit, last_known_status, recover, or none |
Optional. What happens when the rule evaluates and returns no results. emit records a no-data event. last_known_status holds the last known status. recover forces recovery. none disables no-data detection. |
No-data detection is only supported with query.format: standalone. Setting no_data_strategy to any active value on a composed rule has no effect because query.no_data.query can only be defined on a standalone query. Rules with kind: signal must omit no_data_strategy or set it to none.
Artifacts let you attach reference material directly to a rule, such as a runbook or a linked dashboard. Kibana stores the artifact with the rule and displays it on the rule details page, so responders have context when an alert fires.
The artifacts array is optional and accepts up to 100 entries. Every artifact needs id and type. Use data or value for the content, as shown in the following table.
| Field | Type | Accepted values | Description |
|---|---|---|---|
artifacts[].id |
string | Any string | Artifact identifier. Required. Max 256 characters. |
artifacts[].type |
string | Any string | Use runbook or dashboard. Other strings are allowed. Max 128 characters. |
artifacts[].data
|
object | Type-specific object | Required. The artifact's content. Max 32 fields. |
artifacts[].data.content
|
string | Non-empty string | The Markdown body of a runbook. Kibana displays it on the Runbook tab of the rule details page. Required when type is runbook. Max 50,000 characters. |
artifacts[].data.dashboard_id
|
string | Non-empty string | ID of the dashboard to link. Required when type is dashboard. Max 1,024 characters. |
artifacts[].value
|
string | Any string | Required. Runbook Markdown (max 50,000 characters) or a dashboard ID (max 1,024 characters). |
The following example attaches a runbook and a dashboard to the same rule.
artifacts:
- id: checkout-runbook
type: runbook
data:
content: |
Fires when checkout error rate exceeds 10%.
- id: checkout-errors-dashboard
type: dashboard
data:
dashboard_id: "8ac12f90-3d2b-11ef-9a4e-0242ac120002"
typedetermines whichdatafield the artifact requires.- The runbook Markdown goes in
data.content. - The dashboard ID goes in
data.dashboard_id.
If Kibana loads a rule that still uses value, it converts that field to data. Write new YAML with data.
artifacts:
- id: checkout-runbook
type: runbook
value: |
Fires when checkout error rate exceeds 10%.
- id: checkout-errors-dashboard
type: dashboard
value: "8ac12f90-3d2b-11ef-9a4e-0242ac120002"
- The runbook Markdown goes in
value. - The dashboard ID goes in
value.
All duration fields accept the following units:
| Unit | Example | Meaning |
|---|---|---|
s |
30s |
Seconds |
m |
5m |
Minutes |
h |
1h |
Hours |
d |
7d |
Days |
- Create an ES|QL rule: Author rules using the YAML editor, with a live sandbox for previewing results.
- Configure a rule: Field-by-field guidance for each setting, with examples and when-to-use recommendations.