← Files CrowdStrike Falcon FusionARCHIVED FILE
skills/authoring/references/event-query-action.md
8.75 KB · Oct 9, 2026 · 00:07 UTC
# Event Query Action (`Inline.QueryEvent`)
> **⚠️ FIRST, CHECK: are you querying a _population_ of Falcon alerts, detections,
> or incidents the workflow does NOT already hold?** ("summarize all high-severity
> alerts", "list open detections", "fetch alerts from the last 24h".) If so, **do
> NOT use this action.** An Event Query runs against NG-SIEM/LogScale repos, whose
> alert/detection contents depend on the customer's ingestion connectors — a tenant
> with no connectors returns audit-log events, not alerts, so the query silently
> returns nothing. **Default to a CrowdStrike HTTP Request** to
> `/alerts/queries/alerts/v2` (tenant-authenticated, no app; FQL
> `severity_name:'High'+created_timestamp:>'now-24h'`). Only reach for a Foundry-app
> FalconPy `Alerts`/`Detects` function (route to `foundry-skills`) when the workflow
> must be distributed/certified. See `event-query-vs-api.md`. Event Query is correct
> ONLY for data that genuinely lives in NG-SIEM (ingested logs, custom parsers) or
> for **enriching a detection the workflow already holds** (it was triggered on the
> detection and has its ID, e.g. `Ngsiem.alert.id = ?detectID` — the trigger's
> composite `DetectionID` is stored as `Ngsiem.alert.id`, NOT `Ngsiem.detection.id`;
> see `event-query-vs-api.md`).
Fusion's native event-query action runs a CQL/FQL query against the event store
directly inside a workflow step (vendor: CrowdStrike, namespace `faas`, like the
other inline actions). Use it for simple, inline lookups against data that
genuinely lives in NG-SIEM/LogScale — ingested third-party logs, custom parsers,
LogScale search results, or enriching a detection the workflow already holds (e.g.
`Ngsiem.alert.id = ?detectID` — match the composite `DetectionID` against
`Ngsiem.alert.id`, not `Ngsiem.detection.id`) — including schemaless queries where no
predefined schema exists. (For an alert/detection _population_, see the warning
above — use a CrowdStrike HTTP Request, not this action.)
> triggered on a detection and has its ID, an Event Query is the right tool. See
> [event-query-vs-api.md](event-query-vs-api.md).
```yaml
query_ngsiem_logs:
id: <inline-queryevent-action-id> # discover via action_search.py
class: Inline.QueryEvent
version_constraint: ~1
properties:
# Top-level properties (required at release): the query args bound to
# trigger data, plus the search window and export flags.
detection_id: ${data['Trigger.Detection.DetectionID']}
logscale_search_start_time: 1 day
output_files_only: false
workflow_csv_header_fields: []
workflow_export_event_query_results_to_csv: false
inline_configuration:
config:
description: ''
end: now # NOT "time_range"
repo_or_view: search-all # NOT "repo"
search_name: Hydrate detection
search_query: "#repo=xdr_indicatorsrepo Ngsiem.alert.id=?detection_id"
search_query_args:
detection_id: '*' # placeholder default; real value bound above
start: 24h # NOT "time_range"
tags: []
input_schema:
$schema: https://json-schema.org/draft-07/schema
type: object
description: Generated request schema
required:
- detection_id
properties:
detection_id:
type: string
title: Detection ID
default: '*'
next:
- handle_results
```
- **Config field names matter at release.** Use `search_query` (not `query`),
`repo_or_view` (not `repo`), and `start`/`end` (not `time_range`), plus the
top-level `logscale_search_start_time`. The minimal `query`/`time_range`/`repo`
shape passes structural + API validation but release rejects it with "Missing
repo or view; Missing search start time; Missing search end time". Match the
full shape from the shipped `ngsiem/close-duplicate-detections.yaml` export.
**`start` and `end` both live INSIDE `inline_configuration.config` and are both
required** — the top-level `logscale_search_start_time` does NOT substitute for
them. Omitting `start:` (even with `logscale_search_start_time` set) fails
release with "Missing search start time". `validate.py` now flags a config that
has `search_query`/`repo_or_view` but is missing `start` or `end`.
- **Outputs:** results are an **array** at `${data['<ActionLabel>.results']}` —
NOT `.events.0.`, which release validation rejects. Access an element with
`${data['<ActionLabel>.results'][0].FieldName}`, count with
`${data['<ActionLabel>.results'].size()}`, or filter with CEL list ops (the
shipped `close-duplicate-detections.yaml` uses
`data['...results'].filter(e, e.alerted_before == true)[0].previous_alert_id`).
- **Results cap at 200 rows by default.** The Event Query action returns at most
200 rows unless the query asks for more. The general fix is to end the query
with `| tail(x)` or `| head(x)` where 200 < x <= 10000; this works for filter-only
and `select()` queries, which have no `limit` parameter. A query that ends in
`table(...)` has its own 200-row default, so raise it there with
`table(fields=[...], limit=max)` or a specific number (the console query builder
warns _"Output capped at 200 elements by default."_). Either way, 10,000 rows is
the ceiling a workflow can retrieve per search, so a query that matches more
still stops at 10,000. See the Event query
[Limitations](https://docs.crowdstrike.com/access?ft:originId=k84dad72) in the
Falcon Fusion SOAR docs. If a workflow that accumulates query results into a
`WorkflowCustomVariable` (e.g. before a lookup-file write) looks stuck at 200
rows, check the query cap first. Downstream payload limits (such as the 10 MB
response payload) are real too, and large results can fail the workflow; the
action's **Only return results as files** option helps there, at the cost of
the per-row result fields.
- **Read results directly — do NOT route them through an inline Python
extractor.** It is tempting to add an `Inline.Python` step that JSON-parses the
query results and re-emits indicators, then read them back with
`${cs.json.decode(data['<Python>.output_stdout']).field}`. **That form does not
resolve at release** ("invalid or missing variable definitions") and the Python
hop is unnecessary. Reference the query fields straight from
`${data['<ActionLabel>.results'][0].FieldName}` — this is the pattern that
releases cleanly (confirmed live: a workflow reading `results[0]` directly
released; the same workflow rebuilt with a Python extractor failed release
four times).
- **`version_constraint: ~1`.**
## Binding a trigger value into a query argument (two parts, both required)
When the query filters on a runtime value — the detection's IP, the detection ID,
a user — the value flows through a **named query argument** (`?arg` in the query),
and wiring it takes **two** coordinated pieces. Real console exports always have
both; a workflow that has only the first silently scans everything.
1. Declare the arg in `search_query_args` with a **placeholder default of `'*'`**
(this is the console default, not the runtime value).
2. Bind the real trigger value in a **top-level `properties.<arg>`** field with a
`${data['...']}` reference. This is what actually substitutes at runtime.
```yaml
IPBlocklistQuery:
id: <inline-queryevent-action-id> # discover via action_search.py
class: Inline.QueryEvent
version_constraint: ~1
properties:
remote_ip: ${data['Trigger.Detection.NGSIEM.RemoteIP']} # (2) BINDS the value
inline_configuration:
config:
search_query: "#event_simpleName=* RemoteIP=?remote_ip | match(file=\"ip-blocklist.csv\", column=ip, field=RemoteIP, strict=true)"
search_query_args:
remote_ip: '*' # (1) default only
```
**Omitting part (2) is a real bug that passes validation.** `?remote_ip` falls
back to its `'*'` default, so the query matches every event (`RemoteIP=*`) instead
of the detection's IP — a full scan, and the report can disagree with what was
actually queried. The YAML is syntactically valid, so `validate.py` and the import
API both accept it; only runtime behavior is wrong. Every `?arg` referenced in the
query needs a matching `properties.<arg>: ${data['Trigger...']}` binding.
**Event Query vs. a Foundry function with FQL:** use an Event Query action for
simple inline queries inside a workflow step (no app, no code). Reach for a
Foundry function when you need complex processing, pagination, or transformation
logic — that path belongs to the `foundry-skills` plugin.
See [use-cases/event-queries.md](../../../use-cases/event-queries.md) for the full
pattern.
SHA-256: 4b083d429c65fe5482c83827d17021ac86e692baa62a8bde7afbc23bdcea0a58