nano SIEM
Search Commands

ai

ai

Send pipeline results to an LLM for inline classification, scoring, or enrichment.

Description

The ai command passes your query results to a large language model (LLM) and adds three new columns to every row: ai_verdict, ai_confidence, and ai_reasoning. This lets you apply natural-language classification to structured data without leaving the search pipeline.

Because the LLM call happens in post-processing (after SQL execution), ai works with any upstream commands — raw events, aggregations, stats, or enriched results. You can pipe further commands after ai to filter or sort on the AI-generated fields.

Syntax

... | ai prompt="<instruction>" [max_rows=<number>]

Required Arguments

prompt Syntax: prompt="<instruction>" Description: Natural-language instruction telling the LLM how to classify each row. The prompt should specify the exact verdict labels you want back so that downstream | where filters match.

Optional Arguments

max_rows Syntax: max_rows=<number> Description: Maximum number of rows to send to the LLM. Rows beyond this limit receive ai_verdict=SKIPPED. Default: 100 Hard cap: 500

Output Fields

The command adds three fields to every row:

FieldTypeDescription
ai_verdictstringClassification label returned by the LLM (e.g. MALICIOUS, SUSPICIOUS, NORMAL)
ai_confidencenumberConfidence score between 0.0 and 1.0
ai_reasoningstringBrief explanation for the verdict (1-2 sentences)

Rows that exceed max_rows receive:

  • ai_verdict = SKIPPED
  • ai_confidence = 0.0
  • ai_reasoning = "Row exceeded max_rows limit of N"

If the AI agent is not configured or the LLM call fails, all rows receive:

  • ai_verdict = ERROR
  • ai_confidence = 0.0
  • ai_reasoning = "AI enrichment failed: <error message>"

Examples

Classify raw events

source_type=squid_proxy
| ai prompt="Classify each event as NORMAL, SUSPICIOUS, or MALICIOUS. Look for data exfiltration, C2 beaconing, or access to known-bad domains."

Classify aggregated data and filter

Aggregate first, then let the LLM score the summary rows. The | where after | ai filters on the AI-generated fields.

source_type=squid_proxy
| stats count, values(url), sum(bytes_out) as total_bytes by src_ip, dest_host
| where count > 3
| ai prompt="Classify as NORMAL, SUSPICIOUS, or MALICIOUS based on browsing patterns. Look for data exfiltration or unusual destinations."
| where ai_verdict="MALICIOUS"

Triage failed logins

action=login status=failure
| stats count, values(src_ip) as sources, dc(src_ip) as source_count by user
| where count > 5
| ai prompt="Label each row as BRUTE_FORCE, CREDENTIAL_STUFFING, or BENIGN. Consider the number of distinct source IPs and total attempts."
| sort -ai_confidence

Score DNS queries for DGA detection

source_type=dns query_type=A
| ai prompt="Score each DNS query. Label as DGA, SUSPICIOUS, or LEGITIMATE. DGA domains have high entropy, random-looking character sequences, and unusual TLDs." max_rows=200
| where ai_verdict="DGA"

Enrich process execution events

source_type=sysmon event_id=1
| table timestamp, user, process_name, command_line, parent_command_line
| ai prompt="Classify as MALICIOUS, SUSPICIOUS, or BENIGN. Flag living-off-the-land binaries, encoded PowerShell, unusual parent-child relationships, and known attack tools."
| where ai_verdict!="BENIGN"
| sort -ai_confidence

Custom labels for alert triage

The LLM will use whatever labels you specify in the prompt. Match your | where filter to those exact labels.

source_type=firewall action=block
| stats count, values(dest_port) as ports, dc(dest_ip) as dest_count by src_ip
| ai prompt="Triage each source IP as TRUE_POSITIVE, FALSE_POSITIVE, or NEEDS_REVIEW. True positives are likely attacks (port scans, known exploit ports). False positives are routine blocks (DNS, NTP)."
| where ai_verdict="TRUE_POSITIVE"

Limit rows sent to the LLM

For large result sets, use max_rows to control cost and latency. Rows beyond the limit are tagged as SKIPPED.

*
| stats count by src_ip, dest_ip, dest_port
| ai prompt="Flag port scanning activity as SCAN or NORMAL." max_rows=50

Usage Notes

Labels must match your filters. The LLM returns whatever labels your prompt asks for. If your prompt says "classify as NORMAL, SUSPICIOUS, or MALICIOUS" then | where ai_verdict="TP" will return zero results because the LLM never outputs "TP". Always align your | where values with the labels in your prompt.

Aggregate before classifying. Sending raw events to the LLM is expensive and often unnecessary. Use | stats or | table to summarize data first, then pipe to | ai. This reduces row count, improves LLM accuracy (more context per row), and keeps costs down.

Non-streamable. Queries with | ai always execute synchronously (not streamed). The search service collects all results, sends them to the LLM, then returns the enriched data.

Results are cached. If Dragonfly/Redis is configured, the full enriched result (including AI columns) is cached. Repeat queries with the same parameters return instantly without re-calling the LLM.

max_rows hard cap. The max_rows parameter has a hard cap of 500 regardless of the value you set. Rows beyond the limit are not sent to the LLM and are tagged with ai_verdict=SKIPPED.

Requires AI configuration. The ai command requires a configured AI agent (Cloudflare AI Gateway). If no AI provider is configured, results are returned without AI enrichment. Check Settings > AI Agents to verify the "AI Pipe Agent" is enabled.

Prompt injection defense. The AI agent is instructed to ignore any instructions embedded in the data fields. However, adversarial log data could attempt to influence the LLM. Treat AI verdicts as analyst aids, not authoritative decisions.

  • where - Filter on AI-generated fields after enrichment
  • stats - Aggregate data before sending to the LLM
  • table - Select specific fields to send to the LLM
  • sort - Sort by ai_confidence or ai_verdict
  • eval - Custom calculations on AI output fields
  • prevalence - Statistical enrichment (non-AI alternative)
  • anomaly - Statistical outlier detection (non-AI alternative)
On this page

On this page