nano SIEM
Coding Agents

Crafting Searches

Use a coding agent to translate natural-language hunting questions into nPL search queries

Crafting Searches with a Coding Agent

The hosted nano product uses pivt AI to translate "show me rare PowerShell commands run by service accounts" into a working nPL query. In the OSS build, your coding agent does the same job — it reads the Search Commands reference and the rules repo for syntax patterns, and produces nPL you can paste into the search bar (or run via the nanodac MCP server).

This page assumes you've completed Setup.

Why an agent helps here

nPL is small and consistent — 38 commands, piped syntax, predictable behaviour. But writing a good hunting query still requires knowing:

  • Which fields to filter on (and which are indexed for performance — see Field Types)
  • Which stats aggregations make the result useful
  • Where to use prevalence, dedup, or eval to cut noise
  • How to chain risk score= for layered scoring

An agent that's read the search-commands docs once knows all of that, and can apply it to a question phrased in English.

Workflow

Step 1: Point the agent at the references

If you followed Setup, your CLAUDE.md (or AGENTS.md) already tells the agent to consult the search-commands docs and the rules/ repo. If not, mention them in the prompt:

When writing nPL, use the Search Commands reference and ~/nano-workspace/rules/ for syntax patterns.

Step 2: Ask the question in English

Be specific about:

  • The data source (source_type= value, e.g. windows_sysmon, aws_cloudtrail)
  • The time window (last 24h, last 7d)
  • The fields you want in the output

Example:

Hunt for PowerShell processes spawned by Office applications in the last 24h. Source is windows_sysmon. Show me the parent process, command line, host, and user. Group by parent process so I can see the worst offenders first.

Step 3: The agent drafts nPL

The output should look something like:

source_type=windows_sysmon earliest=-24h
| where event_type="process_create"
| where process_name IN ("powershell.exe", "pwsh.exe")
| where parent_process_name IN ("winword.exe", "excel.exe", "outlook.exe", "powerpnt.exe")
| stats count() as spawns,
        values(command_line) as commands,
        values(src_host) as hosts,
        values(user) as users
    by parent_process_name
| sort -spawns

Review for:

  • Field accuracy — does parent_process_name exist in your parsed Sysmon events? (It does — see parsers/parsers/sysmon/parser.yaml — but always verify.)
  • Time syntaxearliest=-24h is the nPL convention; the agent sometimes produces time > now() - 24h SQL-isms by mistake
  • Aggregation choicestats count() vs stats dc() (distinct count) vs timechart make different result shapes; make sure the agent picked what you actually want

Step 4: Run it

Paste into the nano search bar in the UI, or — if the nanodac MCP server is wired up — ask the agent to run it directly:

Run that query and show me the top 5 results.

The MCP server hits the nano search API, returns JSON, and the agent summarizes. This loop ("ask → query → review → refine") is what replaces pivt's natural-language search bar in the OSS build.

Step 5: Iterate

Almost no first-shot query is the right one. Common refinements:

  • Too noisy? Add where clauses or use prevalence enrich=true window=24h | where host_count < N to focus on rare events
  • Too narrow? Loosen the field filter; double-check field name casing
  • Wrong shape? Switch stats by Xtimechart span=1htop X depending on what you're trying to see

Hand the result back to the agent and ask for the next iteration. Don't rewrite by hand if the agent can do it.

Promoting a hunt to a detection

When a hunting query consistently surfaces real attacker behaviour, it's a candidate for a scheduled detection. Ask the agent:

Take that query and convert it into a nanodac detection file. Severity high, MITRE T1059.001, scheduled every 5 minutes with a 15-minute lookback. Save it to detections/execution/.

This is the bridge from ad-hoc search to detection-as-code. See Authoring detections for the full workflow once the YAML exists.

Tips

  • Tell the agent the field schema. If your parser produces non-standard field names, mention them in the prompt or document them in CLAUDE.md. Otherwise the agent guesses based on common conventions and gets it wrong.
  • Use | limit 10 while iterating. Cheap to run, fast to review. Drop the limit once the shape looks right.
  • Save reusable searches as macros. If you find yourself asking the agent the same hunt repeatedly, save the resulting query as a search macro and call it directly.
  • Check field types. A stats count by over a high-cardinality field can be slow — see Field Types & Search Performance for the cost model. The agent doesn't always know what's expensive in your deployment.

What's next

On this page

On this page