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
statsaggregations make the result useful - Where to use
prevalence,dedup, orevalto 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 -spawnsReview for:
- Field accuracy — does
parent_process_nameexist in your parsed Sysmon events? (It does — seeparsers/parsers/sysmon/parser.yaml— but always verify.) - Time syntax —
earliest=-24his the nPL convention; the agent sometimes producestime > now() - 24hSQL-isms by mistake - Aggregation choice —
stats count()vsstats dc()(distinct count) vstimechartmake 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
whereclauses or useprevalence enrich=true window=24h | where host_count < Nto focus on rare events - Too narrow? Loosen the field filter; double-check field name casing
- Wrong shape? Switch
stats by X↔timechart span=1h↔top Xdepending 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 10while 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 byover 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
- Search Commands reference — full nPL command list
- Quick Reference — all 38 commands at a glance
- Authoring detections — promote a hunt to a scheduled detection