You do not need a proprietary scripting dialect or a certification to write security content here. A detection is a saved query over your events with a window, a threshold, a severity, and an attack-technique tag — and the moment it matches, it opens an incident the analyst investigates. This guide covers the prebuilt packs, how to author your own rules (including multi-step sequence and cardinality detections), and how to tune them to your environment.
The fastest detection is the one you do not have to write. Before authoring anything, turn on the prebuilt packs — they cover the behaviours nearly every environment needs watched, and they are starting points you can trust and then shape, not a black box.
The library is organised into fourteen packs grouped by real attacker behaviour or operational failure: authentication abuse, data exfiltration, secret exposure, web attacks, threat-intel matches, AI-agent and tool-protocol threats, cloud control-plane tampering, Linux host security, infrastructure and network health, and reliability. Most of the eighty-seven rules carry a recognised attack-technique mapping, so they slot straight into how your team already reasons and reports. You enable a pack with a single action, and because the rules are telemetry-gated, they stay quiet until the events they watch for actually arrive — so turning on broad coverage does not mean turning on noise.
Crucially, nothing in a pack is immutable. Each rule's threshold, window, severity, and filters are yours to adjust, so a prebuilt detection is a sensible default you tighten or relax to fit your environment rather than a fixed appliance. The right workflow for most teams is: enable the packs, let them run, and tune the handful that do not quite fit — which is far less work than authoring coverage from nothing, and gives you a known-good baseline to learn the system on.
There is a second, less obvious reason to start from the packs: they are a teaching tool. Each prebuilt rule is a worked example of how a real detection is expressed — what it filters on, what threshold and window it uses, what severity and attack-technique tag it carries — so reading the packs is the fastest way to learn the patterns you will reuse when you author your own. When you hit a gap specific to your environment, you are rarely starting from a blank page; you are adapting a shape you have already seen work. That is why the recommended path is always enable-then-author rather than author-from-scratch: the packs give you both coverage and a curriculum, and the custom rules you eventually write are better for having studied them.
A detection is a query, a window, a threshold, a severity, and a tag. If you can search your logs, you can author one — here are the three shapes you will use most.
The most common detection counts something and fires when the count crosses a line within a window. This one opens an incident when a single user accumulates more than ten failed logins in five minutes — a classic brute-force signal:
// A simple threshold detection over your events service:auth event:login_failed | stats count() by user | where count > 10 within 5m
Save that with a severity and an attack-technique tag, and it is live. From the moment you save it, any match opens an incident through the same pipeline and routing as every other detection, and the analyst investigates it. The query is the same syntax you would type into Explore to hunt for the same thing by hand — you have just made it continuous.
Some attacks are invisible in any single event and obvious as a sequence. A wall of failed logins is suspicious; a wall of failed logins followed by a success for the same user is an account takeover in progress. Sequence rules express exactly that ordered pattern:
// Sequence: many failures THEN a success, same user service:auth | sequence (event:login_failed* , event:login_success) by user within 10m
This fires only when the failures are followed by a success for the same user within the window — catching the story that a simple count would miss, and not firing on failures alone.
Other attacks reveal themselves through breadth rather than volume. One source IP failing to log in against ten distinct accounts is the fingerprint of a password spray or an enumeration sweep, even if no single account sees many attempts. Cardinality rules count distinct values:
// Cardinality: one source touching many distinct accounts service:auth event:login_failed | stats distinct(user) as accounts by source_ip | where accounts >= 10 within 5m
Between thresholds, sequences, and cardinality, you can express the large majority of detection logic teams actually need — and all three open investigated incidents in exactly the same way.
Detections become much sharper when they can reference context, not just raw event fields. Source addresses are resolved to geography and network owner inline, your own directory of identities and assets stamps risk and criticality onto matching events, and threat intelligence flags known-bad indicators as they arrive. That means a rule can express something genuinely meaningful in one readable line — "a failure on a critical asset, from a high-risk source, outside business hours" — instead of a join across three separate tools. The enrichment is applied as events land, so it is available to every detection without you wiring it up.
A practical consequence is that the most valuable detections are often not the most complex. A rule that combines a modest threshold with a sharp piece of context — a single failed privileged action from a source the threat intel has already flagged — is both quiet and high-signal, precisely because the context does the discriminating work that a higher count would otherwise have to. When you author, reach for enrichment before you reach for cleverness; a well-scoped simple rule usually beats an elaborate one.
It is worth being concrete about the pipeline a detection feeds, because it is what separates authoring here from authoring in a tool that only produces alerts. The instant a rule matches, it opens a first-class incident carrying the rule's severity and attack-technique tag. That incident is wired to the identities, hosts, and assets it implicates, so the blast radius is attached from the first second. The analyst begins investigating immediately — corroborating the signal, checking the context, and returning a verdict with citations. If the match shares a root cause with other open incidents, it is grouped into a single case rather than paging separately. And the whole thing routes through your on-call and alert channels by severity.
So when you write a detection, you are not just defining a condition that produces a notification — you are adding a new way for the platform to open, enrich, investigate, group, and route a real incident, end to end. That is why authoring is worth doing well, and why a one-line query can carry so much weight: the line is small, but the machinery it triggers is the entire incident lifecycle.
A practical implication is that you should think about severity as carefully as you think about the query. The severity you assign decides how the resulting incident is routed — whether it rings a phone or posts quietly to a channel — so a perfectly-tuned detection with a careless severity either wakes people for nothing or buries a real signal in a low-priority queue. Match the severity to the genuine stakes of what the rule detects, and revisit it if the analyst keeps dispositioning the rule's incidents as more or less serious than you assumed. The query decides what fires; the severity decides who hears about it and how loudly, and both deserve thought.
In a traditional SIEM, a noisy rule is a tax — every false positive costs an analyst twenty minutes, so teams tune detections down toward silence and quietly lose coverage. Here that incentive is far weaker, because the analyst investigates and can disposition benign matches automatically, so a slightly noisy rule costs seconds, not twenty minutes. That means you can tune for accuracy rather than for quiet — keeping a sensitive rule on and letting the investigation absorb the occasional benign hit, instead of blinding yourself to stay sane.
When you do want a cleaner signal, four adjustments cover almost everything: raise or lower the threshold to match your normal volume; widen or narrow the window to fit the timescale of the behaviour; add a filter to scope the rule to the services or sources you care about; and exclude a known-benign source that legitimately trips the pattern. Each is a one-line change to the saved query, takes effect immediately, and is fully reversible.
The best tuning signal is the analyst's own dispositions. If a detection keeps firing and the analyst keeps closing the incidents as benign with a consistent reason, that is a precise hint about what to filter or where to raise the threshold — the system is telling you which part of the rule is too broad. Reviewing a rule's recent incidents and their verdicts turns tuning from guesswork into a data-driven adjustment.
When you correct an analyst verdict — confirm it, downgrade it, annotate it — that correction feeds future investigations, so the system gets better at reading your environment over time. Tuning the detections and correcting the verdicts are two halves of the same loop: one shapes what fires, the other shapes how what fires is judged, and together they make your coverage measurably more accurate the longer you run it.
Turn on the packs, author the gaps in a readable query language, tune from the analyst's verdicts — and let every match open an investigated incident.