Getting Useful Technical Output
Hook
You ask an AI to help you troubleshoot a certificate issue. It comes back with a command that assumes OpenSSL 3.0, but your servers run 1.1. Or you ask for a Docker config and it generates a Dockerfile that references base images that don't exist in your air-gapped registry. The output looks technically competent, it has the right vocabulary, proper syntax, but it's completely useless in your actual environment. The gap between "plausible technical output" and "output I can actually use" comes down to what details you provide upfront.
Purpose
This lesson teaches you how to extract technical output from AI that actually works in your specific environment. You'll learn how to specify OS versions, software versions, architecture constraints, and required context so AI understands the limits of what's available to you. You'll also learn output formatting techniques that give you code, configs, or documentation you can use directly instead of having to interpret and adapt prose.
Why This Matters for IT Professionals
Technical output is only useful if it works in your environment. A PowerShell script for Windows Server 2022 won't run on Windows Server 2016 without modification. A Kubernetes manifest written for 1.28 might not work on 1.24. A Terraform module that assumes internet connectivity is useless if you're in an air-gapped environment.
The more specific you are about your environment upfront, the less post-delivery work you have to do. You save yourself from deploying something that looked right in the terminal but failed in production because it was written for the wrong version or configuration.
You also save time during the conversation itself. Vague output requires follow-up questions and iterations. Specific output, formatted the way you need it, is ready to go.
Core Concepts
Key Insight: Versions Matter More Than You Think
When you ask AI for technical output without specifying versions, it makes assumptions. Those assumptions are often wrong, and silently so. The output looks right until you try to run it.
Always specify:
- OS version and distribution: Not "Linux", "Ubuntu 22.04 LTS" or "RHEL 9.2." Distributions differ. Versions differ. Commands and packages vary.
- Software versions: "Kubernetes 1.28.0," "PostgreSQL 14.5," "pfSense 2.7.2." APIs change. Flags change. Syntax changes.
- Dependencies and their versions: "Node.js 18.16 LTS," "Python 3.11," "Go 1.20." These matter because a library or module you reference might not exist in older versions.
Example of what goes wrong:
Vague: "Show me how to list all Docker images."
AI might suggest: docker image ls --format "table {{.Repository}}\t{{.Size}}"
But if you're on Docker 18.x, the --format flag works differently. Or if you're using Podman (which mimics Docker but has subtle differences), it might not work at all.
Specific: "Show me how to list all Docker images in Docker 20.10 running on RHEL 8.9."
AI knows that specific version has that specific flag and syntax, and can give you something that actually works.
Key Insight: Architecture and Infrastructure Context Changes What's Possible
AI needs to understand not just what software you have, but how it's deployed. Is your Kubernetes cluster in AWS, on bare metal, in a private data center? Does it have internet connectivity? Are your servers in a VPC with security groups? Do you have a private container registry?
These details shape what's possible:
- Network constraints: "We're air-gapped; no outbound internet access" means AI can't suggest downloading packages from the internet. It needs to suggest solutions that work with what's locally available.
- Infrastructure type: "We're in AWS with VPC endpoints but no NAT gateway" means internet access is possible but constrained. "We're on-premise with no cloud" means certain cloud-native solutions won't work.
- Storage: "We have Longhorn for persistent storage" is different from "we have NFS shares" is different from "we have local SSD only." Each requires different config.
- Authentication: "We use Active Directory for all auth" means solutions need to integrate with AD, not assume local accounts.
Without this context, AI suggests solutions that are technically correct but don't fit your infrastructure.
Key Insight: Existing Tools and Constraints Are Part of Your Environment
You're not building from scratch. You already have tools, preferences, and constraints. AI needs to know what those are.
Tell AI:
- What you already have: "We use Terraform for all IaC, Helm for all Kubernetes deployments, Ansible for Linux config management."
- What you prefer not to use: "No Puppet (we standardized on Ansible)." "No external tools, only PowerShell cmdlets." "We can't use GPLv3 licenses."
- What constraints you have: "We can't install new packages without approval, and it takes a week." "We have no budget for new tools." "We need solutions that work offline."
These constraints eliminate suggestions that won't work and focus AI on realistic options.
Key Insight: Providing Error Messages and Log Snippets Makes AI Smarter
When you're troubleshooting and ask AI for help, include the error message and relevant log entries. AI can see patterns in actual output that it can't see from you describing the problem.
Instead of: "Our backup is failing."
Include: "Error message from the backup log: Error code 0x80070005: Access is denied. Path: \\\\nas.corp\\backups\\server01."
AI now knows it's a permissions issue, not a backup service crash or network issue. It can suggest exactly what to check rather than generic troubleshooting steps.
Or instead of: "Kubernetes pod won't start."
Include: The actual pod describe output or events:
Warning BackOff 2m (x5 over 3m) kubelet Back-off pulling image "ghcr.io/company/service:v1.2.3"
AI now knows the issue is an image pull failure and can suggest registry auth troubleshooting rather than general pod diagnostics.
Key Insight: Output Format Is Part of the Spec
How you ask for the answer shapes how useful it is. Don't just ask for the output, specify the format.
For code or configs, ask for:
- Language or format: "Provide as a Terraform .tf file, not HCL in prose."
- Structure: "Create a module with inputs and outputs, not a flat set of resources."
- Comments: "Include inline comments explaining each section, especially non-obvious choices."
- Ready-to-use: "This should be copy-paste ready with no manual modifications needed."
For documentation or analysis, ask for:
- Structure: "Markdown with headers, not prose paragraphs."
- Sections: "Break into: Symptoms, Root Cause, Resolution, Prevention, Links to Related Articles."
- Format: "Provide as a table with columns: Command, Purpose, Expected Output, Error Handling."
Example of how format matters:
Vague: "Explain how to troubleshoot Kubernetes pods."
You get: A 2000-word article about Kubernetes troubleshooting that you have to parse and extract steps from.
Specific: "Provide a Kubernetes pod troubleshooting checklist as a numbered list of commands with expected success output. Format as a markdown table with columns: Step, Command, Success Output, Failure Output."
You get: A checklist you can follow while troubleshooting, with clear success/failure criteria.
Key Insight: Asking for Validation and Testing Upfront Catches Issues Earlier
Don't just ask for code or a config. Ask AI to include validation steps. This catches problems before you deploy them.
Instead of: "Write a Bash script to configure networking."
Ask: "Write a Bash script to configure bonding on RHEL 9. Include a validation function that tests whether the bond is active and both slaves are up. Have the script exit with a non-zero code if validation fails."
Now the script has built-in checks. You know if it worked immediately rather than finding out later when traffic doesn't work.
Or instead of: "Write a Terraform module for ECS."
Ask: "Write a Terraform module for ECS. Include an outputs section that exports the ECS cluster ARN and service endpoint. Include a variable for the minimum number of container instances (with validation that it's at least 1)."
Now you know what the module creates and you can verify it worked by checking the outputs.
Practical Use Cases
Use Case 1: Generating a Compliant Database Backup Script
Scenario: You need a backup script for a production PostgreSQL database. It has to work on your specific hardware (older Linux server, not much free disk), avoid downtime, and include verification steps.
Weak prompt:
Write a PostgreSQL backup script.
What you get: A script that uses pg_dump, which is fine, but might not fit your constraints (it could need more space than you have, could lock the database).
Strong prompt:
I need a PostgreSQL backup script for our production database with these specifics:
Environment:
- PostgreSQL 13.12 on RHEL 8.9
- Database size: 250GB
- Available free space on /backups: 300GB (only room for one full backup)
- Database is online 24/7; we cannot afford downtime
- Backup must complete within 2 hours
Constraints:
- Use only built-in pg_dump or pg_basebackup (no external tools)
- Must not use --lock-database or equivalent (no exclusive locks)
- Must use compression to fit within available space
- Must include a verification step (restore to temp database to verify the backup is usable)
- Must include a cleanup step (delete backups older than 30 days)
- Must be resumable if interrupted
Output format: Provide the script with sections clearly marked:
1. Configuration variables (database name, backup path, retention days)
2. Pre-flight checks (space available, database connectivity)
3. Backup execution (with progress output)
4. Verification (restore to test database)
5. Cleanup and logging
Include inline comments explaining why each step is needed. Also provide: a cron entry to run this daily, and steps to verify the first backup worked before automating.
What you get: A script tailored to your constraints. It uses parallel backup because you have limited space and a large database. It includes verification so you know the backup is usable. It's designed around your 2-hour window.
Time saved: Instead of writing a generic script and then debugging why it fails (not enough space, takes too long, backup isn't actually recoverable), you get something production-ready on first delivery.
What you must do:
- Test the script on a copy of the database first, not production.
- Verify that verification step actually works (it imports the backup to a test database and checks it's usable).
- Monitor the first few automated runs to confirm timing and space usage.
Use Case 2: Generating Infrastructure Code for a Specific Platform
Scenario: You need to create an AWS VPC with specific security and network design. You're using Terraform, and this needs to work with your existing modules and practices.
Weak prompt:
Write Terraform code for an AWS VPC.
What you get: Basic VPC with a public subnet. Probably not what you need. Might not follow your naming conventions or practices.
Strong prompt:
We need a Terraform module to create an AWS VPC with these specifics:
Environment:
- AWS Account ID: 123456789 (non-prod)
- Region: us-east-1 primarily, but module should be region-agnostic
- We use Terraform 1.5 with AWS provider 5.0+
Network design:
- CIDR: 10.50.0.0/16
- 3 public subnets (10.50.1.0/24, 10.50.2.0/24, 10.50.3.0/24), one per AZ
- 3 private subnets (10.50.101.0/24, 10.50.102.0/24, 10.50.103.0/24): one per AZ
- Private subnets route through NAT gateways (one per AZ for HA)
- Public subnets have internet gateway
Constraints:
- Must use AWS best practices (tags, naming conventions)
- Must be a reusable module (not a flat Terraform file)
- Must define clear inputs (vpc_cidr, enable_nat_gateway, tags) and outputs (vpc_id, public_subnet_ids, private_subnet_ids, nat_gateway_ips)
- We already have a naming convention: [environment]-[component]-[detail] (example: nonprod-vpc-public)
- Must work with our existing modules (which expect subnets tagged with 'SubnetType: public/private')
Output format:
- Provide as a Terraform module structure with files: main.tf, variables.tf, outputs.tf
- Include comments in code explaining non-obvious choices
- Include a root-level variables.tf example showing how to call this module
- Do not hardcode any values (all configurable via variables)
- Include tags resource that applies our standard tags (Environment, Owner, CostCenter, CreatedBy)
Also provide: an example terraform.tfvars file showing how to use this module.
What you get: A module that fits your architecture, follows your naming conventions, works with your other modules, and is actually reusable. You can call it consistently across environments.
Before AI: You'd spend 2 hours building this from scratch, 1 hour ensuring it matches your standards, 1 hour testing it.
With AI + 30 minutes of your review: A production-ready module.
What you must do:
- Review the module structure and naming to ensure it matches your conventions.
- Test it by running terraform plan and verifying the subnets, gateways, and route tables are correct.
- Check that outputs are what your other modules expect.
Use Case 3: Generating a Monitoring Config for Your Actual Stack
Scenario: You run Prometheus and Grafana for monitoring, and you need to add monitoring for a specific service. But AI needs to know what you're actually running.
Weak prompt:
How do I set up Prometheus monitoring for an application?
What you get: Generic guidance about Prometheus exporters, targets, scrape configs. Some of it applies; much doesn't.
Strong prompt:
I need a Prometheus scrape config for monitoring our internal payment service. Details:
Current setup:
- Prometheus 2.47 running in Kubernetes 1.28
- Prometheus is in namespace "monitoring"
- Services are in namespace "payment-services"
- We use Kubernetes SD (service discovery via kube-apiserver)
- We have existing scrape configs for other services (I'll need to add to those, not replace)
Service details:
- Service name: "payment-processor"
- Deployment has 3 replicas
- Metrics endpoint: /metrics on port 9090 (needs HTTP, not HTTPS)
- Service doesn't have authentication (we're internal only)
- No custom labels needed; service discovery will provide pod labels
Constraints:
- Scrape interval: 15 seconds (match our existing Prometheus config)
- Must work with RBAC enabled (service account already exists)
- Should not scrape unwanted endpoints (only /metrics)
- Want relabel rules to add environment label
Output format: Provide the scrape config as valid YAML (copy-paste ready into prometheus.yml). Include comments explaining each line. Also provide: how to verify this works (test query to run), expected output, and how to debug if metrics aren't being scraped.
What you get: A scrape config that works immediately in your Prometheus, with explanation of what it does and how to verify it.
What you must do:
- Paste the config into your prometheus.yml.
- Reload Prometheus (no restart needed).
- Check the Prometheus UI Targets page to confirm the service is being scraped.
- Run one of the test queries to confirm metrics are flowing.
Examples
Example 1: Specifying Versions in Networking Config
Scenario: You need to configure VLAN 802.1Q tagging on your switch, and you ask AI for help.
Weak prompt:
How do I configure VLAN tagging on a switch?
What you get: Generic guidance that might apply to Cisco, might apply to Juniper, might apply to a proprietary switch. Probably doesn't match your specific device or OS version.
Strong prompt (with version):
I have a Cisco Catalyst 9300X switch running IOS-XE 17.3.4. I need to configure VLAN tagging (802.1Q) on interface GigabitEthernet1/0/1.
Current state:
- VLAN 100 exists (production)
- VLAN 200 exists (management)
- GigabitEthernet1/0/1 is currently untagged, assigned to default VLAN 1
- This port connects to a pfSense router that expects tagged traffic
Goal: Make GigabitEthernet1/0/1 a trunk port that carries both VLAN 100 and VLAN 200 in tagged form.
Constraints:
- Must not interrupt existing traffic (we're migrating gradually; other ports should remain unchanged)
- Must preserve any existing QoS rules on this port
- Should include verification commands to confirm the config is correct
Output format: Provide the exact CLI commands in the order to run them. Include what to expect after each command. Also: how to verify the trunk is working (show commands) and how to rollback if something goes wrong.
What you get: Exact commands for your switch version (not generic guidance). IOS-XE 17.3.4 has specific syntax, and AI knows it. Commands are in the right order. Includes verification steps.
Issue avoided: Generic guidance might have mentioned the older switchport mode trunk syntax, which works differently in newer versions. Or it might have assumed you want all VLANs allowed (not just 100 and 200).
What you must do:
- Verify the commands match your switch model (Catalyst 9300X uses the syntax AI provided).
- Run the commands on non-production first, or during a maintenance window.
- After running, use the show commands to verify the trunk is up and tagged frames are passing.
Example 2: Providing Error Output for Troubleshooting
Scenario: Your Docker container won't start, and you're asking AI to help troubleshoot.
Weak prompt:
My Docker container won't start. Help me debug.
What you get: Generic troubleshooting steps (check logs, verify image, check ports). Might not address your actual issue.
Strong prompt (with error details):
I have a Docker container that won't start. Here's the exact error:
Docker run command: docker run -d --name myapp --memory=512m -p 8080:8080 myregistry.azurecr.io/myapp:v1.2.3
Error output:
docker: Error response from daemon: failed to create shim: OCI runtime create failed: runc create failed: unable to start container process: exec: "/app/start.sh": permission denied: unknown.
The image builds successfully; the issue is at runtime. The Dockerfile is:
FROM alpine:3.18
COPY ./dist /app
RUN chmod +x /app/start.sh
EXPOSE 8080
CMD ["/app/start.sh"]
The start.sh file exists in ./dist and is executable locally. I'm running Docker on Windows with WSL2.
Constraints:
- The container should run as a non-root user (eventually; this is a dev container for now)
- We can't change the Dockerfile extensively (this is a legacy image)
- Need a solution that also works in our Linux production environment
Output format: Provide the likely causes (in order of probability), the exact diagnostic command to run for each, what to look for in the output, and the fix for the most likely cause. Also: how to verify the container starts after the fix.
What you get: AI reads "permission denied" on the shim and knows this is typically an execution issue with WSL2, or a file permissions issue in the image. Because you provided the Dockerfile and error, AI can see the issue (likely that the file isn't copied with execute bit intact into the image, or there's a WSL2-specific issue).
Issue avoided: Generic troubleshooting would suggest "check if Docker daemon is running" (irrelevant here) or "check image exists" (it does). With the error and context, AI zeros in on the real issue.
What you must do:
- Run the diagnostic commands AI suggests to confirm the actual cause.
- Apply the fix (likely: add RUN chmod +x /app/start.sh to Dockerfile, or rebuild with correct permissions).
- Test locally before pushing to the registry.
Example 3: Specifying Output Format for Ready-to-Use Code
Scenario: You need a Bash script for a production server, and you want it formatted so you can deploy it immediately without modifications.
Weak prompt:
Write a Bash script to monitor disk usage on Linux.
What you get: A script that might work, but you have to review it, possibly modify it for your environment, test it.
Strong prompt (with format):
I need a Bash script for a Linux server that monitors disk usage on all mounted filesystems and sends an alert if any mount point exceeds 80% used.
Environment:
- RHEL 9.2 servers
- This will run as a cron job every 4 hours
- We use email for alerts (sendmail available)
- No external tools (only shell builtins, df, mail)
Requirements:
- Check all mounted filesystems (not just /)
- Alert format: "ALERT: /path is 82% full (date/time)"
- Log the check to /var/log/disk-check.log with timestamp
- Exit cleanly even if an alert fails to send
- Include comments in the script explaining what each section does
Output format: Provide the complete, ready-to-use script. Every line of code should be production-ready and require zero modifications. Include:
1. A Bash shebang and header comment stating purpose, requirements, and last updated date
2. Clear variable section at the top (ALERT_THRESHOLD, LOGFILE, ADMIN_EMAIL) that I can modify if needed
3. The check logic with error handling
4. Logging and alert logic
5. A cron entry that goes at the bottom as a comment (so I can copy it directly)
Do NOT use any flags or tools that might not exist in RHEL 9. Do NOT assume any packages are installed beyond the base system.
What you get: A script you can copy directly into a file, chmod +x, and deploy. No modifications needed. Includes cron entry as a comment. Production-ready.
Before AI: You'd write this yourself (1-2 hours) or find a sample online and modify it.
With AI + 10 minutes of review: Ready to deploy.
What you must do:
- Review the script to ensure it matches your alert threshold and email address.
- Test locally first: run the script manually to ensure it produces correct output.
- Verify cron syntax is correct before deploying to multiple servers.
Anti-Patterns
Anti-Pattern 1: Assuming AI Knows Your Version/Architecture Without Telling It
Don't ask: "Write a load balancer config."
Ask: "Write an HA Proxy 2.8 config for load balancing three web servers."
Without version, AI might use syntax that doesn't exist in your version.
Anti-Pattern 2: Asking for Code Without Specifying How You'll Use It
Don't ask: "Write a Python script to backup files."
Ask: "Write a Python 3.11 script that runs via cron daily, with logging to /var/log/backup.log, resumable if interrupted, and exit code 1 on failure."
The usage context shapes what the code needs to do.
Anti-Pattern 3: Not Providing Error Messages or Log Output
Don't ask: "Something is broken in my config."
Ask: "My config fails with this error message: [exact error]. Here's what I tried: [steps]. Here's what succeeded before: [context]."
Error messages let AI pinpoint the issue instead of guessing.
Anti-Pattern 4: Asking for Output in an Unusable Format
Don't ask AI to explain something and then try to extract a config from the prose. Ask for the config directly: "Provide as a YAML file, not prose explanation."
Anti-Pattern 5: Omitting Constraints That Would Change the Answer
Don't ask for a backup solution without mentioning "we're air-gapped and can't use cloud storage." That constraint completely changes what's possible.
Human Judgment Checkpoints
Before you use AI-generated technical output:
Do the versions match? If AI references a flag or syntax you've never seen, verify it exists in your version before running it.
Does the output assume something about my environment that isn't true? (Internet connectivity, external tools, specific packages, admin access, etc.)
Have I tested this in a non-production environment? Even with detailed prompts, always test code and configs before production.
Can I roll back if this breaks something? If not, review more carefully before deploying.
Does the output include validation steps? If AI just gave you code without "here's how to verify it works," consider asking for verification steps before deploying.
Key Takeaways
- Specify versions for everything: OS, software, tools, dependencies. Vague versions lead to syntax that doesn't exist in your environment.
- Include architecture and infrastructure context: network constraints, existing tools, authentication methods, storage type. This shapes what's actually possible.
- Provide error messages and log snippets when troubleshooting. AI can see patterns in actual output that it can't infer from your description.
- Specify output format upfront: request code, configs, or documentation in a format you can use directly without modification.
- Always test in non-production first, especially for scripts and configs. Even with detailed prompts, real-world edge cases exist.
Skill.re