Structured Output For It
Overview
You ask an AI to generate a network configuration. It returns valid config, but wrapped in explanation text, markdown formatting, and caveats. Now you need to extract the config, strip the commentary, and clean it up before you can use it. Five minutes of work that should have been instant.
Structured output is the practice of asking AI to produce data in a specific format (JSON, YAML, CSV, markdown table, code blocks) that you can parse and use directly. Instead of readable prose that might need manual processing, you get machine-readable output ready to be plugged in.
Structured output is critical in IT because the output often needs to be used by tools or scripts, not just read by humans. A firewall rule in prose format is not useful. A firewall rule in JSON that your automation can parse directly is useful.
Purpose
Structured output has specific purposes:
- Automation compatibility: Output can be piped into scripts, tools, or configurations without manual reformatting
- Consistency: Output follows a predictable schema, making it easier to parse and validate
- Reduced manual work: No need to extract data from prose or reformat it
- Version control: Structured output is easier to diff, review, and track changes
- Validation: Structured data can be validated against a schema
When you ask AI to produce a report, you want prose (readable). When you ask AI to produce a configuration, you want structured data (machine-readable).
Why This Matters
Without structured output, AI-generated technical content requires manual processing:
- Extraction overhead: You ask for a list of servers. AI returns "In your environment, you have servers 1, 2, 3..." You need to extract the list manually.
- Formatting mismatch: You need JSON. AI returns YAML. You convert manually.
- Commentary pollution: AI wraps the configuration in explanation. You need to delete the explanation before using the config.
- Inconsistency: One output has fields in alphabetical order, another has them nested differently. Parsing is fragile.
- Validation failures: The output looks like JSON but has syntax errors. Your script fails, and you have to debug AI output.
With structured output, AI produces data in the exact format you need. Your script or tool can consume it directly.
Key Insight: Structured Output Requires Explicit Direction
AI defaults to producing readable prose. Requesting structured output requires explicit instruction: format, schema, field names, all of it.
The more specific your structural requirements, the better the output.
Core Concepts
1. Output Formats for Different Purposes
Different tasks need different formats:
JSON: Machine-readable, nested data, APIs, configurations
- Use when: Data has hierarchical structure, will be parsed by code
- Example: {"server": {"name": "web1", "ip": "192.168.1.100"}}
YAML: Human and machine-readable, configuration files
- Use when: Configuration files, clear hierarchy, human review
- Example:
server:
name: web1
ip: 192.168.1.100
CSV: Tabular data, spreadsheets, simple lists
- Use when: Data is rows/columns, will be imported to Excel,
needs to be flat
- Example: name,ip,role
web1,192.168.1.100,frontend
Markdown table: Human-readable tabular data
- Use when: Needs to be displayed in documentation, markdown
processing
- Example: | name | ip | role |
| web1 | 192.168.1.100 | frontend |
XML: Structured, nested data, legacy systems
- Use when: System requires XML (rare in modern IT)
Shell script: Executable code
- Use when: Output needs to be executed directly
The format depends on purpose. A report for humans: markdown table. A firewall rule list for automation: JSON. A Kubernetes config file: YAML.
Key insight: Match format to use case.
2. Schema Definition: Telling AI What Structure You Want
Structured output is only useful if you specify the exact structure. Vague requests produce vague output.
Poor schema request:
"Give me a list of servers."
Good schema request:
"Give me a JSON array of servers. Each server object should have:
- name (string)
- ip_address (string, IPv4)
- role (string: frontend, backend, database, utility)
- status (string: active, inactive, maintenance)
- capacity_gb (integer)
Format:
[
{
"name": "web1",
"ip_address": "192.168.1.100",
"role": "frontend",
"status": "active",
"capacity_gb": 500
}
]
"
The good request specifies: format (JSON array), structure (each object), fields (name, ip_address, role, status, capacity_gb), types (string, integer), and constraints (IPv4 format).
Key insight: Specific schema requests produce consistent output.
3. Validation and Error Handling
Structured output can fail in subtle ways. The JSON is syntactically valid but doesn't match your schema. A field is missing. A value is wrong type.
Request: "Give me this data as JSON. Validate that it's valid JSON
before returning. If any field is missing, use null. If the JSON is
invalid, return an error explaining the issue."
This adds a layer of quality control. AI validates its own output before sending it.
Alternatively, you validate after receiving:
Pseudocode to validate output
parsed = JSON.parse(output)
for item in parsed:
assert item.has("name"), "Missing name field"
assert item.has("ip_address"), "Missing ip_address"
assert is_valid_ipv4(item["ip_address"]), "Invalid IP format"
Key insight: Validate structured output before using it, or ask AI to validate before sending.
4. Handling Commentary
AI often wants to explain things. You ask for JSON, it returns:
"Here's the JSON for your servers:
{
"servers": [...]
}
I included the hostname, IP, and role fields as you requested..."
Now you need to extract the JSON from the prose. You can:
Ask AI to output ONLY the structured data, nothing else:
"Output ONLY valid JSON, no explanations or markdown formatting."
Use code to extract the structured part (find the first { and last }, parse what's between)
Request a specific delimiter:
"Output the JSON between json and tags only, no additional text."
Key insight: Tell AI to output ONLY the structured data if that's all you need.
5. Handling Incomplete or Invalid Output
Sometimes AI can't produce perfect structured output. A field is unknown. A value doesn't match the schema. You need fallback behavior.
"If you don't know a value, use null. If you're uncertain about a
value, include a note field explaining the uncertainty. If the data
is incomplete, include it anyway rather than failing."
This gives AI permission to produce partial output rather than refusing. You can handle nulls and uncertainty in your validation step.
Alternatively:
"If you cannot produce valid JSON due to the data being incomplete
or contradictory, return an error message explaining why, rather than
producing invalid JSON."
This tells AI when to refuse vs. when to output partial data.
Key insight: Define fallback behavior for edge cases.
Practical Use Cases
Before: AI output needs manual extraction and reformatting.
After: AI output is ready to use directly or pipe into scripts.
Use Case 1: Configuration Files as Structured Output
You need to generate Kubernetes deployment manifests for three microservices. You'll apply these with kubectl apply -f. They need to be valid YAML, properly formatted, with specific structure.
Structured output request:
Generate Kubernetes deployment manifests for three services:
1. API service (3 replicas, port 8080, memory limit 512Mi)
2. Worker service (2 replicas, port not applicable, memory limit 256Mi)
3. Database service (1 replica, port 5432, memory limit 1Gi)
Output ONLY valid Kubernetes YAML. Each manifest should include:
- apiVersion: apps/v1
- kind: Deployment
- metadata with name
- spec with replicas, selector, template
- container spec with image, ports, resources (limits and requests)
Use this image naming: registry.company.com/[service-name]:latest
Output the YAML between ```yaml and ``` markers. Do not include
explanatory text before or after the YAML. If the YAML is invalid,
return an error message instead.
AI returns:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-service
spec:
replicas: 3
selector:
matchLabels:
app: api-service
template:
metadata:
labels:
app: api-service
spec:
containers:
- name: api
image: registry.company.com/api-service:latest
ports:
- containerPort: 8080
resources:
limits:
memory: "512Mi"
requests:
memory: "256Mi"
---
[Additional manifests...]
This output is ready to save and deploy: kubectl apply -f manifest.yaml.
Anti-pattern (without structured request):
"Generate Kubernetes configs for these services."
AI returns:
"For the API service, you'll need a Deployment with 3 replicas.
Here's what that looks like:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-service
...
You'll also need a Service to expose it. Here's the Service config:
apiVersion: v1
kind: Service
...
And for the Worker service, you'll want a Deployment with 2 replicas..."
Now you need to extract three manifests from prose, and the Service config wasn't requested but is included.
Use Case 2: Network Firewall Rules as Structured Data
You need a list of firewall rules for your architecture. Your firewall uses JSON API. You'll POST this JSON to create rules.
Structured output request:
Generate firewall rules for a web application architecture.
Requirements:
- Allow HTTP (80) and HTTPS (443) from any source to web servers
- Allow SSH (22) from management network (10.0.0.0/8) to all servers
- Allow database traffic (port 5432) from app servers to database
- Deny all other traffic (implicit)
Output valid JSON array. Each rule object must have:
- rule_id (string: unique identifier)
- description (string: human readable)
- direction (string: "inbound" or "outbound")
- protocol (string: "TCP", "UDP", "ICMP")
- source_cidr (string: CIDR notation, e.g., "0.0.0.0/0")
- dest_cidr (string: CIDR notation)
- port_range (string: "80" or "80-443" or null for ICMP)
- action (string: "allow" or "deny")
- priority (integer: 1-65535, lower executes first)
Output ONLY the JSON array, no markdown formatting or explanation.
Validate the JSON is syntactically correct.
AI returns:
[
{
"rule_id": "rule_001",
"description": "Allow HTTP from internet to web servers",
"direction": "inbound",
"protocol": "TCP",
"source_cidr": "0.0.0.0/0",
"dest_cidr": "10.1.0.0/16",
"port_range": "80",
"action": "allow",
"priority": 100
},
{
"rule_id": "rule_002",
"description": "Allow HTTPS from internet to web servers",
"direction": "inbound",
"protocol": "TCP",
"source_cidr": "0.0.0.0/0",
"dest_cidr": "10.1.0.0/16",
"port_range": "443",
"action": "allow",
"priority": 110
},
...
]
Now you can pipe this to your firewall API: POST /api/rules < firewall_rules.json.
Use Case 3: Compliance Audit Checklist as Structured Data
You need a compliance checklist in a format your audit tool can import. The tool expects CSV: section, requirement, status, evidence, notes.
Structured output request:
Generate a SOC 2 Type II compliance checklist for IT infrastructure.
Output as CSV with columns:
- section (string: SOC 2 section, e.g., "Logical Access")
- requirement (string: specific requirement)
- status (string: "implemented", "partially", "missing")
- evidence (string: what evidence shows compliance)
- notes (string: additional notes or gaps)
For status, assume:
- "implemented" for controls that are fully in place
- "partially" for controls that are partially implemented
- "missing" for controls not yet implemented
Include 15-20 requirements across these sections:
- Logical Access (authentication, authorization)
- Change Management (approvals, testing, rollback)
- Physical Security (data center access, device management)
- Incident Management (detection, response, reporting)
- Data Residency (where data is stored, compliance)
Output valid CSV format. Include headers. No markdown formatting.
AI returns:
section,requirement,status,evidence,notes
Logical Access,MFA for all users,implemented,Azure AD MFA logs,Enforced 2022
Logical Access,Password policy (12+ chars),implemented,AD policy settings,Updated 2024
Logical Access,Admin access approval,implemented,Change management tickets,All admin requests logged
Logical Access,Session timeout (30 min),partially,RDP timeout set; VPN timeout not configured,VPN timeout needs config by Q2
Change Management,Change request for all changes,implemented,CAB approval process,100% of major changes captured
...
This CSV is ready to import into your audit tool.
Use Case 4: Infrastructure Inventory as Structured Data
You need a current inventory of servers for capacity planning. Your inventory management tool expects JSON with specific schema.
Structured output request:
Generate a server inventory for our data center.
Assume:
- 15 physical servers total
- Mix of web, app, database, and utility servers
- Various CPU, memory, and storage configurations
Output valid JSON array. Each server object must have:
- server_id (string: unique hostname, e.g., "web-01")
- location (string: data center)
- cpu_cores (integer)
- memory_gb (integer)
- storage_gb (integer)
- role (string: web, app, database, utility)
- os (string: Windows Server 2019, Ubuntu 20.04, etc.)
- status (string: active, standby, decommissioned)
- end_of_life (string: YYYY-MM-DD or null)
- notes (string: optional notes)
Output ONLY the JSON array. Validate syntax before sending.
If any value is uncertain, use null and include a note.
AI returns:
[
{
"server_id": "web-01",
"location": "DC1",
"cpu_cores": 8,
"memory_gb": 32,
"storage_gb": 500,
"role": "web",
"os": "Ubuntu 20.04",
"status": "active",
"end_of_life": "2028-04-30",
"notes": "Nginx reverse proxy, healthy"
},
{
"server_id": "db-01",
"location": "DC1",
"cpu_cores": 16,
"memory_gb": 64,
"storage_gb": 2000,
"role": "database",
"os": "Windows Server 2019",
"status": "active",
"end_of_life": "2027-01-31",
"notes": null
},
...
]
Your inventory tool can parse this and update automatically.
Examples
Example 1: Prompting for Structured Table Output
I need a summary of our cloud resources by region and service type.
Output as a markdown table with columns:
- Region (us-east-1, us-west-2, eu-west-1, etc.)
- Service (EC2, RDS, S3, Lambda)
- Instance Count
- Monthly Cost
- Utilization (%)
Include rows for our major regions and services. Assume:
- US regions have more capacity than EU
- RDS is more expensive per month than EC2
- S3 costs scale with data volume (assume 100TB total)
Output ONLY the markdown table, no explanatory text.
AI outputs a markdown table ready to paste into documentation.
Example 2: Prompting for Shell Script Output
Generate shell commands to audit security settings on Ubuntu servers.
Output valid bash script. Include commands to check:
- SSH configuration (port, root login, password auth)
- Firewall rules (ufw status, open ports)
- User accounts (users with sudo, inactive accounts)
- File permissions (suid/sgid files, world-writable dirs)
- System updates (security patches pending)
Output ONLY the bash script code, between ```bash and ```.
The script should be directly executable (#!/bin/bash at the top,
proper error handling, exit codes).
AI outputs a script that can be saved and executed immediately.
Example 3: Prompting for Terraform Code
Generate Terraform code to create an AWS VPC with:
- 2 public subnets (10.0.1.0/24, 10.0.2.0/24)
- 2 private subnets (10.0.10.0/24, 10.0.11.0/24)
- Internet Gateway
- NAT Gateway in public subnet
- Route tables for public and private subnets
Output valid Terraform code (HCL). Use variables for VPC CIDR,
availability zones, and tags. Include provider configuration for
AWS region us-east-1.
Output ONLY the Terraform code, no markdown formatting or explanations.
The code should be syntactically valid (can be run with terraform apply).
AI outputs Terraform that's ready to use.
Anti-Patterns
Anti-Pattern 1: Asking for Structured Output Without Specifying Format
"Give me a list of servers."
AI responds with prose: "You have servers including web-01, db-01..."
You need to extract it and format it yourself.
Prevention: Specify format explicitly: "Give me a JSON array with server names and IPs" or "Give me a CSV: name, ip, role."
Anti-Pattern 2: Asking for Structure But Not Schema
"Give me JSON of the network configuration."
AI returns JSON, but with fields: {"info": "config", "data": {...}}.
You expected: {"interfaces": [...], "routes": [...], "dns": [...]}.
Prevention: Specify the exact schema: field names, types, structure.
Anti-Pattern 3: Accepting Output With Commentary
AI returns:
"Here's the JSON for your rules:
{
"rules": [...]
}
This includes inbound and outbound rules as requested..."
You copy this directly and now you have markdown formatting in your JSON file.
Prevention: Tell AI to output ONLY the structured data: "Output ONLY valid JSON, no explanatory text, no markdown formatting."
Anti-Pattern 4: Not Validating Structured Output
AI returns JSON that looks good but has a syntax error or missing field. You use it and your tool fails.
Prevention: Always validate output. Parse it (if it's JSON, try JSON.parse()), check required fields, validate values.
Anti-Pattern 5: Requesting Perfect Data When Partial Is Acceptable
"Generate a complete network diagram in JSON with all 500 devices."
AI struggles because it's incomplete, and you get nothing.
Prevention: If data is incomplete, ask AI to include it anyway: "Output all devices you can identify. For missing details, use null. Include a notes field if uncertain."
Human Judgment Checkpoints
Format suitability: "Is this format actually useful for my use case?" JSON is good for APIs, but CSV is better for spreadsheets. Choose format wisely.
Schema completeness: "Does this schema capture all the information I need?" Review the field names and types before using them.
Validation strategy: "How will I validate this output?" Decide in advance if you'll validate in code or ask AI to validate.
Error handling: "What happens if the output is incomplete or invalid?" Plan for partial data or errors.
Key Takeaways
Specify format explicitly. JSON, YAML, CSV, markdown table, tell AI which format you need.
Define schema in detail. Don't say "give me data." Say "give me a JSON array with these fields, these types, these constraints."
Ask AI to output ONLY the structured data. If you need JSON, request no markdown formatting, no explanations, just JSON.
Validate structured output before using it. Even if AI produces syntactically valid JSON, validate that it matches your schema and has the data you need.
Use structured output for automation. When output needs to be used by scripts or tools, structured data is essential.
Use prose output for human consumption. When output is for reading, not processing, prose is better than raw JSON.
Handle incomplete data gracefully. If data is partial, ask AI to include it with null values rather than failing completely.
Include error signals in structured output. If AI can't produce valid output, it should return an error message, not invalid data.
Structured output reduces manual reformatting. The effort to specify schema upfront pays off in time saved processing output.
Test structured output requests with sample data. Generate a small example first to ensure the format works before generating large outputs.
Skill.re