Generated banner for Kql
Generated logo for Kql

Kql

MicrosoftOfficialPublished by Microsoft

  • Skill
  • Tool integration
  • Data and AI
  • MIT
  • No issues found

From the author

KQL language expertise for writing correct, efficient Kusto Query Language queries. Covers syntax gotchas, join patterns, dynamic types, datetime pitfalls, regex patterns, serialization, memory management, result-size discipline, and advanced functions (geo, vector, graph). USE THIS SKILL whenever writing, debugging, or reviewing KQL queries — even simple ones — because the gotchas section prevents the most common errors that waste tool calls and cause expensive retry cascades. Trigger on: KQL, Kusto, ADX, Azure Data Explorer, Fabric Real-Time Intelligence, EventHouse, Log Analytics, log analysis, data exploration, time series, anomaly detection, summarize, where clause, join, extend, project, let statement, parse operator, extract function, any mention of pipe-forward query syntax.
— the description by Microsoft

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides comprehensive expertise in Kusto Query Language (KQL), the native language for Azure Data Explorer, Microsoft Fabric Real-Time Intelligence, and Log Analytics. It focuses on writing efficient, memory-safe queries by addressing common pitfalls such as dynamic type handling, join cardinality, serialization requirements, and datetime formatting. The skill includes a robust self-correction framework to help users resolve errors like E_LOW_MEMORY_CONDITION or E_RUNAWAY_QUERY without abandoning their query strategy.

What it does

  • Provides syntax guidance for pipe-forward query structures and management commands.
  • Offers solutions for common KQL errors, including dynamic type casting and serialization issues.
  • Explains memory-safe patterns for large-scale data exploration and aggregation.
  • Details advanced capabilities like graph queries, vector similarity, and geospatial operations.
  • Includes a lookup table for rapid error recovery and troubleshooting.
  • Provides best practices for result-size management and efficient string comparisons.

When to use it

  • When writing or debugging KQL queries for Azure Data Explorer, Sentinel, or Fabric.
  • When encountering performance issues like memory errors or runaway queries.
  • When performing complex data analysis involving joins, time series, or graph structures.
  • When you need to explore database schemas or policies using management commands.
  • When you need to ensure query efficiency before running against large datasets.

Advantages

  • Prevents expensive retry cascades by addressing common syntax and logic gotchas early.
  • Promotes memory-safe coding habits to avoid cluster-level performance degradation.
  • Reduces reliance on external tools by leveraging native KQL functions for regex, vector, and graph tasks.
  • Provides a structured, repeatable approach to error recovery and query optimization.

Usage examples

“How do I fix a 'Summarize group key is of a dynamic type' error in KQL?”
The agent will advise wrapping the dynamic column in an explicit cast function like tostring(), tolong(), or todouble() before using it in the summarize by-clause.
“My KQL query is failing with E_LOW_MEMORY_CONDITION. How can I optimize it?”
The agent will suggest adding pre-filters (where clauses) before aggregation, reducing the number of group-by columns, or breaking the query into smaller time windows.
“How do I perform a join in KQL when I need to use a range condition?”
The agent will explain that KQL joins only support equality, and will guide you to pre-bucket data using bin() or spatial cells before joining on the resulting keys.
“What is the correct way to filter by year in KQL?”
The agent will provide the correct syntax using datetime_part('year', Column) or the between operator with a full datetime range, rather than comparing against a bare integer.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/microsoft/kql/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip kql.zip -d .agents/skills

Documentation by Microsoft

KQL Mastery

Try it yourself: All ✅ examples in this skill can be run against the public help cluster: https://help.kusto.windows.net, database Samples (contains StormEvents, SimpleGraph_Nodes/Edges, nyc_taxi, and more).

1. KQL Basics

Kusto Query Language (KQL) is a pipe-forward query language for exploring data. It is the native query language for Azure Data Explorer (ADX), Microsoft Fabric Real-Time Intelligence (EventHouse), Azure Monitor Log Analytics, Microsoft Sentinel, and other Microsoft data services.

Pipe-forward syntax

KQL queries are a chain of operators separated by |. Data flows left to right:

StormEvents                          // start with a table
| where State == "TEXAS"             // filter rows
| summarize count() by EventType     // aggregate
| top 5 by count_ desc              // limit results
Query vs management commands

KQL has two execution planes:

PlaneStarts withExamples
QueryTable name, let, print, datatableStormEvents | where State == "TEXAS"
Management.show, .create, .set, .drop, .alter.show tables, .show table T schema

Management commands can be followed by query operators (the output is tabular), but the entire request runs on the management plane. You cannot start with a query and pipe into a management command.

// ✅ WORKS — management command piped to query operators
.show tables | project TableName | where TableName has "Events"

// ❌ WRONG — query piped into management command
StormEvents | take 5 | .show tables

When in doubt: if the first token starts with ., it's a management command. For a full catalog of schema exploration commands, see references/discovery-queries.md.

2. Dynamic Type Discipline

KQL's dynamic type is flexible but strict in certain contexts. A common mistake is using a dynamic column in summarize by, order by, or join on without casting.

The rule: Any time you use a dynamic-typed column in by, on, or order by, wrap it in an explicit cast.

// ❌ ERROR: "Summarize group key ... is of a 'dynamic' type"
StormEvents | summarize count() by StormSummary.Details.Location

// ✅ FIX
StormEvents | summarize count() by tostring(StormSummary.Details.Location)
// ❌ ERROR: "order operator: key can't be of dynamic type"
StormEvents | order by StormSummary.TotalDamages desc

// ✅ FIX
StormEvents | order by tolong(StormSummary.TotalDamages) desc
// ❌ ERROR in join: dynamic join key
StormEvents | join kind=inner (PopulationData) on $left.StormSummary == $right.State

// ✅ FIX — cast both sides
StormEvents
| extend State_str = tostring(StormSummary.Details.Location)
| join kind=inner (PopulationData) on $left.State_str == $right.State

Self-correction: When you see "is of a 'dynamic' type" in an error, add tostring(), tolong(), or todouble().

3. Join Patterns & Pitfalls

KQL joins have constraints that differ from SQL.

Equality only

KQL join conditions support only ==. No <, >, !=, or function calls in join predicates.

// ❌ ERROR: "Only equality is allowed in this context"
StormEvents | join (nyc_taxi) on geo_distance_2points(BeginLon, BeginLat, pickup_longitude, pickup_latitude) < 1000

// ✅ WORKAROUND — pre-bucket into spatial cells, then join on cell ID
StormEvents
| extend cell = geo_point_to_s2cell(BeginLon, BeginLat, 8)
| join kind=inner (nyc_taxi | extend cell = geo_point_to_s2cell(pickup_longitude, pickup_latitude, 8)) on cell

For range joins, pre-bin values: | extend bin_val = bin(Value, 100), then join on bin_val. Note: values near bin boundaries may land in adjacent bins — consider checking neighboring bins or overlapping the range for precision.

Left/right attribute matching

Both sides of a join on clause must reference column entities only — not expressions, not aggregates.

// ❌ ERROR: "for each left attribute, right attribute should be selected"
StormEvents | join kind=inner (PopulationData) on $left.State

// ✅ FIX — specify both sides explicitly
StormEvents | join kind=inner (PopulationData) on $left.State == $right.State
Cardinality check before large joins

Always check cardinality before joining tables with >10K rows. A cross-join explosion was the source of the single E_RUNAWAY_QUERY error (25K × 195 = potential 4.8M rows).

// Before joining, check how many rows each side contributes
StormEvents | summarize dcount(State)        // → 67 distinct states
PopulationData | summarize dcount(State)     // → 52 — safe to join

4. Regex in KQL

KQL handles regex natively — no need for Python.

The extract_all gotcha

Unlike Python's re.findall(), KQL's extract_all requires capturing groups in the regex:

// ❌ ERROR: "extractall(): argument 2 must be a valid regex with [1..16] matching groups"
StormEvents | extend words = extract_all(@"[a-zA-Z]{3,}", EventNarrative)

// ✅ FIX — add parentheses around the pattern
StormEvents | extend words = extract_all(@"([a-zA-Z]{3,})", EventNarrative)
Regex toolkit — don't fall back to Python
FunctionUse caseExample
extract(regex, group, source)Single matchextract(@"User '([^']+)'", 1, Msg)
extract_all(regex, source)All matches (needs ())extract_all(@"(\w+)", Text)
parseStructured extractionparse Msg with * "User '" Sender "' sent" *
matches regexBoolean filterwhere Url matches regex @"^https?://"
replace_regexFind and replacereplace_regex(Text, @"\s+", " ")

5. Serialization Requirements

Window functions need serialized (ordered) input.

// ❌ ERROR: "Function 'row_cumsum' cannot be invoked. The row set must be serialized."
StormEvents
| where State == "TEXAS"
| summarize DailyCount = count() by bin(StartTime, 1d)
| extend CumulativeCount = row_cumsum(DailyCount)

// ✅ FIX — add | serialize (or | order by, which implicitly serializes)
StormEvents
| where State == "TEXAS"
| summarize DailyCount = count() by bin(StartTime, 1d)
| order by StartTime asc
| extend CumulativeCount = row_cumsum(DailyCount)

Functions requiring serialization: row_number(), row_cumsum(), prev(), next(), row_window_session().

6. Memory-Safe Query Patterns

The most common memory error. Caused by scanning too much data without pre-filtering.

The progression of safety
Safest ──────────────────────────────────────────────── Most dangerous
| count    | take 10    | where + summarize    | summarize (no filter)    | full scan
Rules for large tables (>1M rows)
  1. Always start with | count to understand table size

  2. Always | where before | summarize — filter time range, partition key, or category first

  3. Never dcount() on high-cardinality columns without pre-filtering

  4. Check join cardinality before executing (see Section 3)

  5. Use materialize() for subqueries referenced multiple times

// ❌ OUT OF MEMORY — large table, no filter, many group-by columns
StormEvents
| summarize dcount(EventType), count() by StartTime, State, Source
| where dcount_EventType > 1

// ✅ SAFE — filter first, then aggregate
StormEvents
| where StartTime between (datetime(2007-04-15) .. datetime(2007-04-16))
| summarize dcount(EventType) by State, Source
| where dcount_EventType > 1
When you see E_LOW_MEMORY_CONDITION

The query touched too much data. Your options:

  • Add | where filters (time range, partition key)

  • Reduce the number of by columns in summarize

  • Break into smaller time windows and union results

  • Use | sample 10000 for exploratory work instead of full scans

When you see E_RUNAWAY_QUERY

A join or aggregation produced too many output rows. Check join cardinality — one or both sides is too large.

7. Result Size Discipline

Large results slow down analysis. Prevention:

Query typeSafeguard
ExploratoryAlways end with | take 10 or | take 20
AggregationUse | top 20 by ... not unbounded summarize
Wide rows (vectors, JSON)| project only needed columns
make_list() / make_set()Avoid on high-cardinality groups (produces huge cells)
Unknown sizeRun | count first

The vector trap: Tables with embedding columns (1536-dim float arrays) produce ~30KB per row. Even | take 20 yields 600KB. Always | project away vector columns unless you specifically need them.

8. String Comparison Strictness

KQL sometimes requires explicit casts when comparing computed string values — even when both sides are already strings.

// ❌ ERROR: "Cannot compare values of types string and string. Try adding explicit casts"
StormEvents | where geo_point_to_s2cell(BeginLon, BeginLat, 16) == other_cell

// ✅ FIX — wrap both sides in tostring()
StormEvents | where tostring(geo_point_to_s2cell(BeginLon, BeginLat, 16)) == tostring(other_cell)

This is most common with computed values from geo_point_to_s2cell() and strcat() comparisons. When in doubt, cast with tostring().

9. Advanced Functions

KQL handles these natively — no need for Python:

Vector similarity
// try it! — cosine similarity on Iris feature vectors
let target = pack_array(5.1, 3.5, 1.4, 0.2);
Iris
| extend Vec = pack_array(SepalLength, SepalWidth, PetalLength, PetalWidth)
| extend sim = series_cosine_similarity(Vec, target)
| top 5 by sim desc
Geo operations
// Distance between two points (meters)
StormEvents | extend dist = geo_distance_2points(BeginLon, BeginLat, EndLon, EndLat)

// Spatial bucketing for joins
StormEvents | extend cell = geo_point_to_s2cell(BeginLon, BeginLat, 8)
Graph queries
// Persistent graph model — try it on the help cluster!
graph("Simple")
| graph-match (src)-[e*1..3]->(dst)
  where src.name == "Alice"
  project src.name, dst.name, path_length = array_length(e)

// Transient graph — build inline with make-graph
SimpleGraph_Edges
| make-graph source --> target with SimpleGraph_Nodes on id
| graph-match (src)-[e*1..5]->(dst)
  where src.name == "Alice"
  project src.name, dst.name, path_length = array_length(e)
Time series
// try it! — create a time series and detect anomalies
StormEvents
| make-series count() default=0 on StartTime step 1d
| extend anomalies = series_decompose_anomalies(count_)

For detailed examples and patterns, consult references/advanced-patterns.md.

10. Self-Correction Lookup Table

When you encounter an error, look it up here before retrying:

Error message containsLikely causeFix
is of a 'dynamic' typeDynamic column in by/on/order byWrap in tostring()/tolong()
Only equality is allowedRange predicate in join conditionPre-bucket with S2/H3 cells or bin()
extractall(): matching groupsMissing () in regexAdd (): @"(\w+)" not @"\w+"
row set must be serializedWindow function on unsorted dataAdd | serialize or | order by before it
Cannot compare values of types string and stringComputed string comparisonAdd tostring() on both sides
Failed to resolve column named 'X'Wrong column name or wrong tableRun .show table T schema to check column names
E_LOW_MEMORY_CONDITIONQuery touched too much dataAdd | where filters, reduce time range, break into steps
E_RUNAWAY_QUERYJoin/aggregation produced too many rowsCheck cardinality before joining; add pre-filters
for each left attribute, right attributeJoin on clause incompleteUse explicit form: on $left.X == $right.Y
needs to be bracketedReserved word used as identifierUse ['keyword'] syntax
plugin doesn't existUnavailable plugin on this clusterFall back to equivalent function or Python
Expected string literal in datetime()Bare integer in datetime literalUse datetime(2024-01-01) not datetime(2024)
Unexpected token after byComplex expression in summarize by-clauseextend the expression first, then summarize by the column
not recognized / unknown operatorOperator not available on this engineCheck operator support; try equivalent (order by = sort by)

11. Datetime Pitfalls

Datetime literals are a common source of errors. A wrong literal format can cascade into completely different approaches instead of fixing the small issue.

Literal format
// ❌ WRONG — bare year is not a valid datetime
StormEvents | where StartTime > datetime(2007)

// ✅ RIGHT — always use full date format
StormEvents | where StartTime > datetime(2007-01-01)
Filtering by year, month, or hour
// ❌ WRONG — comparing datetime column to integer
StormEvents | where StartTime == 2007

// ✅ RIGHT — use datetime_part() to extract components
StormEvents | where datetime_part("year", StartTime) == 2007

// ✅ ALSO RIGHT — use between with datetime range
StormEvents | where StartTime between (datetime(2007-01-01) .. datetime(2007-12-31T23:59:59))
Time bucketing in summarize
// This works, but can be harder to read and reuse in complex queries
StormEvents | summarize count() by startofmonth(StartTime)

// Clearer — extend first, then summarize by the computed column
StormEvents
| extend Month = startofmonth(StartTime)
| summarize count() by Month
| order by Month asc
Useful datetime functions
FunctionPurposeExample
bin(ts, 1h)Round down to bucket boundarybin(Timestamp, 1d)
startofmonth(ts)First day of monthstartofmonth(Timestamp)
datetime_part("hour", ts)Extract componentdatetime_part("year", Timestamp)
format_datetime(ts, fmt)Format as stringformat_datetime(Timestamp, "yyyy-MM")
ago(1d)Relative timewhere Timestamp > ago(1d)
between(a .. b)Range filter (inclusive)where Timestamp between (datetime(2024-01-01) .. datetime(2024-01-31T23:59:59))
todatetime(str)Parse string → datetimetodatetime("2024-01-15T10:30:00Z")
totimespan(str)Parse string → timespantotimespan("01:30:00")

12. Operator Naming & Equality

KQL has subtle differences from SQL syntax.

Naming conventions
EntityConventionExample
TablesUpperCamelCaseStormEvents, NetworkLogs
ColumnsUpperCamelCaseStartTime, EventType
Variables (let)snake_caselet filtered_events = ...
Built-in functionssnake_caseformat_bytes(), geo_distance_2points()
Stored functionsUpperCamelCase.create function GetTopUsers
Equality operators
// In where clauses, == is case-sensitive, =~ is case-insensitive
StormEvents | where State == "TEXAS" | count        // exact match
StormEvents | where State =~ "texas" | count        // case-insensitive

// In joins, use == only
StormEvents | join kind=inner (PopulationData) on State
sort vs order

Both sort by and order by work identically in KQL — they are aliases. Use whichever you prefer, but be consistent.

contains vs has
// contains: substring match (slower)
StormEvents | where EventNarrative contains "tree"   // finds "trees", "treetop" too

// has: term/word match (faster, uses index)
StormEvents | where EventNarrative has "tree"        // matches word boundaries only

// For exact prefix/suffix
StormEvents | where EventType startswith "Thunder"
StormEvents | where Source endswith "Spotter"

13. Error Recovery Strategy

When a first KQL query fails, the temptation is to abandon the entire approach and try something completely different. The correct response is almost always to fix the specific error, not change strategy.

The pattern to avoid
Query 1: extract(@"pattern", 1, col)  → Parse error
Query 2: todynamic(col)               → Different error  
Query 3: parse_json(col)              → Another error
Query 4: Python script                → Works but 10x tokens
The correct pattern
Query 1: extract(@"pattern", 1, col)  → Parse error (bad escaping)
Query 2: extract(@"pattern", 1, col)  → Fix the specific escaping issue → Success

Rules for error recovery:

  1. Read the error message carefully — it almost always tells you exactly what's wrong

  2. Fix the specific syntax/escaping issue, don't switch approaches

  3. Use the self-correction table (Section 10) to map errors to fixes

  4. Only switch approaches after 2 failed fixes of the same query

  5. The parse operator is often simpler than extract() for structured text:

// Instead of complex regex on TraceLogs:
// extract(@"file path: \"\"([^\"]+)\"\"", 1, Message)

// Use parse for structured extraction (try it on help cluster, SampleLogs db):
cluster("help").database("SampleLogs").TraceLogs
| where Message has "file path"
| parse Message with * "file path: \"\"" FilePath "\"\"" *
| project Timestamp, FilePath
| take 5

14. Query Writing Checklist

Before running any KQL query, mentally check:

  1. Pre-filtered? Large tables have a | where before any | summarize

  2. Result bounded? Exploratory queries end with | take N or | top N

  3. Dynamic columns cast? Any dynamic column in by/on/order by is wrapped

  4. Regex has groups? extract_all patterns have () around what you want to capture

  5. Join cardinality safe? Both sides checked with dcount() before joining

  6. Needed columns only? Wide tables get | project to drop unneeded columns

  7. Datetime literals valid? Using datetime(2024-01-01) not datetime(2024) or bare integers

  8. Complex by-expressions? Use | extend first, then | summarize by the computed column

  9. Error recovery plan? If a query fails, fix the specific error — don't change strategy

Files

references/discovery-queries.md

KQL Schema Discovery Queries

Reference for schema exploration commands. Use these to understand a database's structure before writing queries.


Table and Column Discovery

Table Discovery
// List all tables with row counts and sizes
.show tables details
| project TableName, TotalRowCount, TotalOriginalSize, TotalExtentSize, HotOriginalSize

// List tables (names only)
.show tables
| project TableName

// Table schema (column names, types, folder)
.show table StormEvents schema as json

// Table schema as CSL (for scripting)
.show table StormEvents cslschema

// Compact column listing (CSL format)
.show table StormEvents cslschema
| project TableName, Schema
Column Statistics
// Column cardinality and statistics (sample-based)
.show table StormEvents column statistics

// Quick column profiling via query
StormEvents
| take 10000
| summarize
    Rows = count(),
    Nulls = countif(isnull(BeginLat)),
    Distinct = dcount(State),
    MinVal = min(StartTime),
    MaxVal = max(StartTime)

Function and View Discovery

Function Discovery
// List all stored functions
.show functions
| project Name, Parameters, Body = substring(Body, 0, 100), DocString, Folder

// Full function definition
.show function MyFunction2

// Functions in a folder
.show functions
| where Folder == "Demo"
Materialized View Discovery
// List all materialized views
.show materialized-views
| project Name, SourceTable, Query = substring(Query, 0, 100), IsEnabled, IsHealthy

// View statistics (lag, processed records)
.show materialized-view DailyCovid19 statistics

// View extents
.show materialized-view DailyCovid19 extents
| summarize ExtentCount = count(), TotalRows = sum(RowCount)

Policy Discovery

// Retention policies
.show table StormEvents policy retention

// Caching policies
.show table StormEvents policy caching

// Streaming ingestion policy
.show table StormEvents policy streamingingestion

// Update policies
.show table StormEvents policy update

// All major policies for a table (run individually):
// retention, caching, streamingingestion, update, merge, sharding

External Tables and Ingestion Mappings

External Table Discovery
// List external tables
.show external tables
| project TableName, TableType, Folder, ConnectionStrings

// External table schema
.show external table TaxiRides schema as json
Ingestion Mapping Discovery
// CSV mappings for a table
.show table StormEvents ingestion csv mappings

// JSON mappings for a table
.show table StormEvents ingestion json mappings

// All mappings for a table
.show table StormEvents ingestion mappings

Graph Model Discovery

// List all graph models
.show graph_models

// Show a specific graph model definition
.show graph_model Simple

// List graph snapshots
.show graph_snapshots

Security Discovery

// Database-level principals
.show database Samples principals

// Table-level principals
.show table StormEvents principals

// Current identity
print CurrentUser = current_principal(), Cluster = current_cluster_endpoint()

Database Overview Script

Run this sequence to get a complete picture of a KQL Database:

// 1. Database stats (uses current database context)
.show database datastats

// 2. All tables with details
.show tables details
| project TableName, TotalRowCount, TotalOriginalSize, CachingPolicy
| order by TotalRowCount desc

// 3. All functions
.show functions
| project Name, Folder, DocString, Parameters

// 4. All materialized views
.show materialized-views
| project Name, SourceTable, IsEnabled, IsHealthy

// 5. All external tables
.show external tables

// 6. All graph models
.show graph_models

Advanced Troubleshooting

Commands for diagnosing ingestion failures, throttling, capacity issues, and cluster health.

Ingestion Failures

When data isn't showing up after ingestion, check for failures (retained for 14 days):

// Show all recent ingestion failures
.show ingestion failures

// Filter to a specific table
.show ingestion failures
| where Table == "StormEvents"
| where FailedOn > ago(1d)
| project FailedOn, Table, FailureKind, ErrorCode, Details
| order by FailedOn desc

// Check a specific operation
.show ingestion failures with (OperationId = 'GUID-HERE')

Key columns: FailureKind (Permanent vs Transient), ErrorCode, Details, OriginatesFromUpdatePolicy.

Cluster Capacity

Check whether the cluster is running out of capacity for ingestion, merges, exports, or other operations:

// Show capacity for all resource types
.show capacity

// Show capacity for a specific operation
.show capacity ingestions
.show capacity extents-merge
.show capacity data-export
.show capacity materialized-view
.show capacity extents-partition

Returns Total, Consumed, and Remaining for each resource. If Remaining is 0, operations are being throttled.

Cluster Diagnostics
// Cluster health and node state
.show diagnostics

// Currently running queries (useful for identifying long-running or stuck queries)
.show queries

// Completed commands and their resource usage
.show commands
| where StartedOn > ago(1h)
| project CommandType, StartedOn, Duration, State, ResourceUtilization

// Combined view of commands and queries
.show commands-and-queries
| where StartedOn > ago(1h)
| order by StartedOn desc

// Administrative operations log
.show operations
| where StartedOn > ago(1d)
| where State == "Failed"
Workload Groups

Workload groups control resource governance — per-request limits, rate limits, and concurrency. If queries are being throttled or rejected, check workload group configuration:

// Show all workload groups and their policies
.show workload_group default

// Monitor requests by workload group
.show commands-and-queries
| where StartedOn > ago(1h)
| summarize count(), avg(Duration), sum(TotalCPU) by WorkloadGroup

Built-in workload groups:

  • default — catches all requests not classified elsewhere

  • internal — internal system requests (cannot be modified)

  • $materialized-views — materialized view materialization process

Troubleshooting Decision Tree
SymptomFirst commandWhat to look for
Data not appearing after ingestion.show ingestion failuresFailureKind, ErrorCode, Details
Queries running slowly or timing out.show capacityRemaining = 0 on any resource
Queries being rejected/throttled.show workload_group defaultRate limits, concurrent request caps
Cluster unresponsive.show diagnosticsNode health, memory pressure
Merges falling behind.show capacity extents-mergeRemaining = 0
Materialized views stale.show materialized-view DailyCovid19 statisticsMaterialization lag

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
Microsoft
Publisher
Microsoft (Official)
Source
microsoft/skills · .github/skills/kql · commit 0696600
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Microsoft or Microsoft.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download kql.zip