Build parsers
Author, validate, test, and deploy log-source parsers (Vector VRL) over MCP with the build_parser prompt — no web UI
Build parsers
Beyond reading the SIEM, nano-investigator can build the data layer underneath it. A set of parser tools lets the agent author a log-source parser — the Vector VRL that normalizes a raw log into nano's Unified Data Model — and take it all the way to live, without leaving the chat. The agent writes the VRL, the server validates and tests it against a real sample, then saves and deploys it.
This is one of two ways to author a parser in the OSS build, and it's the interactive one: you work against a live tenant over MCP, and the server validates, tests, and deploys for you. The other is the version-controlled path in Authoring parsers — draft a parser.yaml against the nano-rs/parsers repo, validate it with the vector vrl CLI, and ship it by PR or UI import. Use that one when a parser should be reviewed and version-controlled; use this one to stand a parser up quickly on a running deployment. (nano's Enterprise build adds an AI parser wizard on top; these tools give any coding agent the same authoring discipline via the VRL reference and the validate-first loop, with no AI-credit or Enterprise dependency.)
A parser is independent of a transport. The parser turns a raw line into UDM; a source configuration and its routing rules decide which incoming events reach that parser by source_type. You can author and test a parser in isolation, then wire routing separately.
The build_parser prompt
build_parser takes source_type (required) and sample_log (optional but strongly recommended). It scripts a validate-first loop so the agent never deploys VRL it hasn't compiled and tested:
- Read the
nanosiem://reference/vrl-parsersresource and the UDM schema list_log_sources— don't duplicate an existingsource_type- Draft a generic parser for the whole source, not just the sample
validate_vrl— compile-check; fix every diagnostic and re-run until validtest_parse_sample— run the VRL against the sample, inspect theudm.*outputcreate_log_source— save as a draft (validated, not deployed)deploy_log_source— push the config to Vectorget_log_source_health— confirm events are actually flowing
The agent presents the VRL and the test output before saving, and confirms before deploying, so you stay in control.
The VRL reference
The nanosiem://reference/vrl-parsers resource is what makes hand-authored VRL reliable. It encodes the same guardrails nano's validator enforces:
- The input/output contract — read
.message, normalize.udm.timestampto%Y-%m-%d %H:%M:%S, set.udm.event_typefrom the data, preserve the raw log - The rules the validator hard-rejects — named-capture regex (
(?P<name>...)),??only on fallible calls (E651),elseon the same line (E203), define-before-use - The forbidden functions —
get_env_var,get_hostname,http_request,dns_lookup,reverse_dnsare blocked at validation and stripped from the runtime registry; VRL is capped at 1 MB - Copy-paste skeletons for JSON and regex/line-oriented sources
Point the agent at it before it writes anything: "read the vrl-parsers reference, then write a parser for these logs."
Validate and test before saving
Two tools run a parser without touching saved state, and the loop between them is where most of the work happens:
validate_vrl(vrl_code) compiles the VRL and returns{ valid, errors, diagnostics }. Diagnostics carry line/column and a code (likeE651orE203) so the agent can fix the exact spot.test_parse_sample(vrl_code,sample_log) runs the VRL against one raw line and returns the parsed output plus anextracted_field_count. An empty or near-emptyudmmeans the parser isn't actually extracting — keep iterating.
For a source_type that's already ingesting, test_parse_live pulls real recent events from ClickHouse and parses them with both the new and the currently deployed VRL, side by side — useful when you're refining a parser rather than writing a new one.
> build a parser for source_type "acme_fw". sample:
ts=2026-06-01T10:15:00Z src=10.1.1.5 dst=8.8.8.8 act=deny proto=udp dpt=53
Running build_parser (source_type=acme_fw)...
Reading nanosiem://reference/vrl-parsers and the UDM schema.
list_log_sources: no existing parser for acme_fw. Drafting.
validate_vrl: valid=false — E651 at 7:34 (`??` on to_string).
Fixed. validate_vrl: valid=true.
test_parse_sample: success=true, extracted_field_count=6
udm.timestamp = "2026-06-01 10:15:00"
udm.src_ip = "10.1.1.5"
udm.dest_ip = "8.8.8.8"
udm.dest_port = 53
udm.protocol = "udp"
udm.event_type = "deny"
Output looks right. Save this as a draft for acme_fw? (won't deploy yet)Save, then deploy
Saving and deploying are deliberately separate, the same as the web UI.
create_log_source (name, source_type, parser_vrl) saves a draft: the server validates it and stores it, but it is not live. update_log_source edits an existing parser the same way — editing VRL never auto-deploys.
deploy_log_source (id) writes the Vector config and triggers a reload. undeploy_log_source takes it back offline.
Deploy is best-effort on the server side: it can return success even if Vector failed to reload. Don't trust the deploy response alone. After deploying, wait about a minute and call get_log_source_health — it reports the 24-hour and last-hour event counts, freshness, and a health_status (healthy / stale / no_data / disabled / error). no_data after a few minutes usually means events aren't being routed to this parser's source_type yet. get_log_source_deployments shows the deploy history and any error.
Wire the routing
A deployed parser only sees events that a routing rule sends it. The source-configuration tools cover that ingress layer:
list_source_config_typeslists the transport drivers (HTTP, Kafka, AWS S3, GCP Pub/Sub, Splunk HEC, Vector) with theirmatch_fieldpresets.list_source_configslists the configured transports.create_routing_rule(source_config_id,match_field,match_type,target_source_type) maps incoming events to a parser'ssource_type.check_rule_reachabilityverifies, before you create a rule, that the source config is enabled and deployed, that a parser exists for the targetsource_type, and (for Kafka) that a broker is reachable.
For the common HTTP/routed case the sender sets the X-Source-Type header, so a parser whose source_type matches the header is reachable as soon as it's deployed — no extra rule needed.
Start from a prebuilt parser
You don't always start from scratch. nano can pull parsers from an upstream library (such as nano-rs/parsers):
list_parser_repositorieslists connected repositories and their sync status.sync_parser_repository(repository_id) refreshes the local cache from the upstream repo.list_repository_parsers(repository_id) browses the available parsers.import_parser(repository_id,path) imports one as a draft log source —linked(tracks upstream updates) by default, orforkedfor a detached copy. Then deploy it like any other.