Skip to content

Learn Agentic AI by Building One — A Hands-On Guide - Lesson 3: Structured Output — Getting JSON from AI

3 minute read
Content level: Intermediate
0

Introduction to how Agentic AI works behind the scene

Free text is great for chatting, but apps need structured data. If you want the AI to fill a form, update a database, or drive a UI — you need it to return JSON, not paragraphs.

The trick: tell the AI exactly what format you want in the prompt.

"Return JSON with keys: sentiment, confidence, summary"
→ {"sentiment": "positive", "confidence": 0.92, "summary": "..."}

This is the bridge between "AI as a chatbot" and "AI as a backend service."

The Code

We reuse our call_llm function from Lesson 2, then build a case classifier on top of it:

import json
import boto3

bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")


def call_llm(user_prompt: str, system_prompt: str = None) -> str:
    body = {
        "anthropic_version": "bedrock-2023-05-31",
        "max_tokens": 1024,
        "messages": [{"role": "user", "content": user_prompt}],
    }
    if system_prompt:
        body["system"] = system_prompt

    response = bedrock.invoke_model(
        modelId="us.anthropic.claude-sonnet-4-20250514-v1:0",
        contentType="application/json",
        accept="application/json",
        body=json.dumps(body),
    )
    result = json.loads(response["body"].read())
    return result["content"][0]["text"]

Now the interesting part — a function that uses AI to classify support cases and return structured JSON:

def analyze_case(case_subject: str) -> dict:
    """Use AI to analyze a support case and return structured data."""

    system = """You are a support case classifier. Given a case subject, return ONLY valid JSON:
{
  "category": "one of: compute, database, storage, networking, security, ai_ml, other",
  "urgency": "one of: critical, high, medium, low",
  "likely_root_cause": "brief one-line guess",
  "recommended_team": "which team should handle this"
}
Return ONLY the JSON object. No other text."""

    response = call_llm(f"Classify this support case: {case_subject}", system)

    # Parse the JSON from the AI's response
    # Strip markdown code fences if present
    cleaned = response.strip()
    if cleaned.startswith("```"):
        cleaned = cleaned.split("\n", 1)[1].rsplit("```", 1)[0]

    return json.loads(cleaned)

Notice the system prompt is very specific about the output format. The more precise you are, the more reliable the structured output.

Running It Against Real Cases

Let's classify some real support case subjects from our dashboard data:

test_cases = [
    "Issue with EC2 Instance - Rebooted",
    "RDS Timed-out waiting to acquire database connection",
    "EFS Throughput Utilization is high",
    "GuardDuty - S3 Finding - Exfiltration:S3/AnomalousBehavior",
]

for subject in test_cases:
    result = analyze_case(subject)
    print(f"Case: {subject}")
    print(f"  Category:    {result['category']}")
    print(f"  Urgency:     {result['urgency']}")
    print(f"  Root cause:  {result['likely_root_cause']}")
    print(f"  Team:        {result['recommended_team']}")

Output:

📋 Case: Issue with EC2 Instance - Rebooted
Category: compute
Urgency: medium
Root cause: Unexpected instance reboot due to hardware issue or system maintenance
Team: Infrastructure Operations

📋 Case: RDS Timed-out waiting to acquire database connection
Category: database
Urgency: high
Root cause: Connection pool exhaustion or database performance bottleneck
Team: Database Engineering Team

📋 Case: EFS Throughput Utilization is high
Category: storage
Urgency: high
Root cause: High I/O operations or insufficient provisioned throughput for EFS volume
Team: Storage Engineering Team

📋 Case: GuardDuty - S3 Finding - Exfiltration:S3/AnomalousBehavior
Category: security
Urgency: critical
Root cause: Potential unauthorized data exfiltration from S3 bucket detected by GuardDuty
Team: Security Incident Response Team

Key Takeaway

AI can return structured data, not just chat text. This lets you use AI as a "smart function" inside your code — classify tickets, extract entities, score sentiment, generate configs. The system prompt is your schema definition.

Next up: Lesson 4 — Giving AI memory so it remembers the conversation →

Previous: Lesson 2 —How to control its behavior with prompts →