Structured Output
NAAS can parse raw command output into typed data structures (list[dict])
on the server side, eliminating ad-hoc parsing in client applications. Two
parsers are supported on the /v2/send-command-structured endpoint:
- TextFSM (the default and most commonly used) — regex-based templates with the large ntc-templates community library covering 1000+ vendor commands.
- TTP (Template Text Parser) — Jinja2-style templates, useful when you'd rather write that style than regex or when ntc-templates doesn't cover your command.
Pass either textfsm_template or ttp_template (mutually exclusive). With
neither, NAAS uses TextFSM with ntc-templates.
Quick Start
curl -k -u "username:password" https://localhost:8443/v2/send-command-structured \
-H "Content-Type: application/json" \
-d '{
"host": "192.168.1.1",
"platform": "cisco_ios",
"commands": ["show version", "show ip interface brief"]
}'
By default this picks up matching ntc-templates and parses each command's
output into list[dict].
How it works
- Automatic template lookup (TextFSM only) — Netmiko matches
(platform, command)against ntc-templates and applies the template automatically. - Custom template — supply
textfsm_templateorttp_templateto override the lookup or to parse a command ntc-templates doesn't cover. - Structured output — returns
list[dict]per command when a template matches, rawstrwhen none does (TextFSM falls back gracefully). - Endpoint —
/v2/send-command-structuredfor the structured path;/v2/send-commandis the raw-output equivalent.
Return type
Results are list[dict] when a template matched, str when none did. Client
code must handle both.
{
"job_id": "...",
"status": "finished",
"results": {
"show version": [
{
"hostname": "router1",
"version": "15.0(2)SE",
"uptime": "1 week, 2 days"
}
],
"show ip interface brief": [
{"interface": "Gi0/1", "ip_address": "192.168.1.1", "status": "up"},
{"interface": "Gi0/2", "ip_address": "192.168.1.2", "status": "down"}
]
}
}
result = response["results"]["show version"]
if isinstance(result, list):
# Parsed output
for item in result:
print(item["hostname"])
else:
# Raw string (no template matched)
print(result)
Choosing TextFSM or TTP
| TextFSM | TTP | |
|---|---|---|
| Community templates | ntc-templates — large, active, 1000+ commands | ttp-templates — smaller |
| Template syntax | Regex + state machine | Jinja2-like placeholders |
| Default behavior | Auto-lookup via ntc-templates if no template provided | Must supply ttp_template explicitly |
| Best for | Standard show commands covered by ntc-templates | Custom or complex parsing where regex is painful |
Most NAAS users want TextFSM with ntc-templates — that's the default for a reason. Reach for TTP when ntc-templates doesn't cover a command and you'd rather write a TTP template than a TextFSM one, or when you have an existing TTP-templates investment.
TextFSM
Custom TextFSM templates
Supply your own template for commands not covered by ntc-templates:
{
"host": "192.168.1.1",
"platform": "cisco_ios",
"commands": ["show custom output"],
"textfsm_template": "Value FIELD1 (\\S+)\\nValue FIELD2 (\\S+)\\n\\nStart\\n ^${FIELD1}\\s+${FIELD2} -> Record"
}
Template syntax
TextFSM templates define:
- Value lines: field names and regex capture groups
- States: parsing state machine (
Start,Record, etc.) - Rules: regex patterns that match lines and extract values
Example template for show ip interface brief:
Value INTERFACE (\S+)
Value IP_ADDRESS (\S+)
Value STATUS (up|down|administratively down)
Start
^${INTERFACE}\s+${IP_ADDRESS}.*${STATUS} -> Record
See the TextFSM documentation for full syntax.
TTP
Using TTP templates
Pass ttp_template (mutually exclusive with textfsm_template):
curl -k -u "username:password" https://localhost:8443/v2/send-command-structured \
-H "Content-Type: application/json" \
-d '{
"host": "192.168.1.1",
"platform": "cisco_ios",
"commands": ["show interfaces"],
"ttp_template": "interface {{ interface }}\n ip address {{ ip }} {{ mask }}"
}'
Community templates
Reference templates from the
ttp-templates library with the
ttp:// prefix:
Template syntax
TTP templates use {{ variable }} placeholders:
See the TTP documentation for full syntax.
When to use structured vs raw output
Use /v2/send-command-structured when:
- You need typed data for programmatic processing
- The command is covered by ntc-templates (check the template index) or you have a template ready
- Your code can handle mixed return types (
list[dict]vsstr)
Use /v2/send-command when:
- You need raw output for logging, display, or human review
- The command has no template and you don't want to write one
- You want a consistent return type (always
str)
Limitations
- No connection pooling. Both TextFSM and TTP keep parsing state on the Netmiko connection that makes pooling unreliable. Structured requests always open a fresh SSH session.
- Template availability (TextFSM auto-lookup). Not every command has an ntc-template — check coverage before relying on auto-parsing.
- Mixed return types. A single response can mix
list[dict]andstrresults (one command parsed, another fell back to raw). - Parsing overhead. Adds roughly 10–50ms per command depending on output size.
Examples
Inventory collection
import requests
response = requests.post(
"https://naas.local/v2/send-command-structured",
auth=("user", "pass"),
json={
"host": "192.168.1.1",
"platform": "cisco_ios",
"commands": ["show version", "show inventory"]
},
verify=False
)
job_id = response.json()["job_id"]
# Poll for results
result = requests.get(
f"https://naas.local/v2/send-command-structured/{job_id}",
auth=("user", "pass"),
verify=False
).json()
for device in result["results"]["show version"]:
print(f"{device['hostname']}: {device['version']}")
Custom TextFSM template
template = """
Value VLAN_ID (\\d+)
Value VLAN_NAME (\\S+)
Value STATUS (active|suspended)
Start
^${VLAN_ID}\\s+${VLAN_NAME}\\s+${STATUS} -> Record
"""
response = requests.post(
"https://naas.local/v2/send-command-structured",
auth=("user", "pass"),
json={
"host": "192.168.1.1",
"platform": "cisco_ios",
"commands": ["show vlan brief"],
"textfsm_template": template
},
verify=False
)
See also
- Platform Autodetect — fingerprint unknown devices before running structured commands