Close Menu
SkytikSkytik

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    What's Hot

    At Least 32 People Dead After a Mine Bridge Collapsed Due to Overcrowding

    November 17, 2025

    Here’s how I turned a Raspberry Pi into an in-car media server

    November 17, 2025

    Beloved SF cat’s death fuels Waymo criticism

    November 17, 2025
    Facebook X (Twitter) Instagram
    • About Us
    • Contact Us
    SkytikSkytik
    • Home
    • AI Tools
    • Online Tools
    • Tech News
    • Guides
    • Reviews
    • SEO & Marketing
    • Social Media Tools
    SkytikSkytik
    Home»AI Tools»A Hands-On Guide to Anthropic’s New Structured Output Capabilities
    AI Tools

    A Hands-On Guide to Anthropic’s New Structured Output Capabilities

    AwaisBy AwaisNovember 25, 2025No Comments12 Mins Read0 Views
    Facebook Twitter Pinterest LinkedIn Telegram Tumblr Email
    A Hands-On Guide to Anthropic’s New Structured Output Capabilities
    Share
    Facebook Twitter LinkedIn Pinterest Email

    announced Structured Outputs for its top models in its API, a new feature designed to ensure that model-generated outputs exactly match the JSON Schemas provided by developers. 

    This solves a problem many developers face when a system or process consumes an LLM’s output for further processing. It’s essential for that system to “know” what to expect as its input so it can process it accordingly. 

    Similarly, when displaying model output to a user, you want this to be in the same format each time. 

    So far, it’s been a pain to ensure consistent output formats from Anthropic models. However, it appears that Anthropic has now solved this problem for its top models anyway. From their announcement (linked at the end of the article), they say, 

    The Claude Developer Platform now supports structured outputs for Claude Sonnet 4.5 and Opus 4.1. Available in public beta, this feature ensures API responses always match your specified JSON schemas or tool definitions. 

    Now, one thing to remember before we look at some example code, is that Anthropic guarantees that the model’s output will adhere to a specified format, not that any output will be 100% accurate. The models can and may still hallucinate occasionally. 

    So you might get perfectly formatted incorrect answers! 

    Setting up our dev environment 

    Before we look at some sample Python code, it’s best practice to create a separate development environment where you can install any necessary software and experiment with coding. Now, anything you do in this environment will be siloed and won’t impact any of your other projects. 

    I’ll be using Miniconda for this, but you can use whatever method you’re most familiar with. 

    If you want to go down the Miniconda route and don’t already have it, you must install it first. Get it using this link:

    https://docs.anaconda.com/miniconda/ 

    To follow along with my examples, you’ll also need an Anthropic API key and some credit on your account. For reference, I used 12 cents to run the code in this article. If you already have an Anthropic account, you can get an API key using the Anthropic console at https://console.anthropic.com/settings/keys.  

    1/ Create our new dev environment and install the required libraries 

    this on WSL2 Ubuntu for Windows.

    (base) $ conda create -n anth_test python=3.13 -y 
    (base) $ conda activate anth_test 
    (anth_test) $ pip install anthropic beautifulsoup4 requests 
    (anth_test) $ pip install httpx jupyter 

    2/ Start Jupyter 

    Now type in ‘jupyter notebook’ into your command prompt. You should see a jupyter notebook open in your browser. If that doesn’t happen automatically, you’ll likely see a screenful of information after the command. Near the bottom, you’ll find a URL to copy and paste into your browser. It’ll look similar to this:

    http://127.0.0.1:8888/tree?token=3b9f7bd07b6966b41b68e2350721b2d0b6f388d248cc69

    Code Examples

    In our two coding examples, we will use the new output_format parameter available in the beta API. When specifying the structured output, we can use two different styles.

    1. Raw JSON Schema.

    As the name suggests, the structure is defined by a JSON schema block passed directly to the output format definition.

    2. A Pydantic model class.

    This is a regular Python class using Pydantic’s BaseModel that specifies the data we want the model to output. It’s a much more compact way to define a structure than a JSON schema.

    Example code 1 — Text summarisation 

    This is useful if you have a bunch of different texts you want to summarise, but want the summaries to have the same structure. In this example, we’ll process the Wikipedia entries for some famous scientists and retrieve specific key facts about them in a highly organised way.

    In our summary, we want to output the following structure for each scientist,

    • The name of the Scientist
    • When and where they were born
    • Their main claim to fame
    • The year they won the Nobel Prize
    • When and where they died

    Note: Most text in Wikipedia, excluding quotations, has been released under the Creative Commons Attribution-Sharealike 4.0 International License (CC-BY-SA) and the GNU Free Documentation License (GFDL) In short this means that you are free:

    to Share — copy and redistribute the material in any medium or format

    to Adapt — remix, transform, and build upon the material

    for any purpose, even commercially.

    Let’s break the code into manageable sections, each with an explanation.

    First, we import the required third-party libraries and set up connections to Anthropic using our API Key.

    import anthropic
    import httpx
    import requests
    import json
    import os
    from bs4 import BeautifulSoup
    
    http_client = httpx.Client()
    api_key = 'YOUR_API_KEY'
    client = anthropic.Anthropic(
        api_key=api_key,
        http_client=http_client
    )

    This is the function that will scrape Wikipedia for us.

    def get_article_content(url):
        try:
            headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'}
            response = requests.get(url, headers=headers)
            soup = BeautifulSoup(response.content, "html.parser")
            article = soup.find("div", class_="mw-body-content")
            if article:
                content = "\n".join(p.text for p in article.find_all("p"))
                return content[:15000] 
            else:
                return ""
        except Exception as e:
            print(f"Error scraping {url}: {e}")
            return ""

    Next, we define our JSON schema, which specifies the exact format for the model’s output.

    summary_schema = {
        "type": "object",
        "properties": {
            "name": {"type": "string", "description": "The name of the Scientist"},
            "born": {"type": "string", "description": "When and where the scientist was born"},
            "fame": {"type": "string", "description": "A summary of what their main claim to fame is"},
            "prize": {"type": "integer", "description": "The year they won the Nobel Prize. 0 if none."},
            "death": {"type": "string", "description": "When and where they died. 'Still alive' if living."}
        },
        "required": ["name", "born", "fame", "prize", "death"],
        "additionalProperties": False
    }

    This function serves as the interface between our Python script and the Anthropic API. Its primary goal is to take unstructured text (an article) and force the AI to return a structured data object (JSON) containing specific fields, such as the scientist’s name, birth date, and Nobel Prize details.

    The function calls client.messages.create to send a request to the model. It sets the temperature to 0.2, which lowers the model’s creativity to ensure the extracted data is factual and precise. The extra_headers parameter enables a specific beta feature that is not yet standard. By passing the anthropic-beta header with the value structured-outputs-2025-11-13, the code tells the API to activate the Structured Outputs logic for this specific request, forcing it to produce valid JSON that matches your defined structure.

    Because the output_format parameter is used, the model returns a raw string that is guaranteed to be valid JSON. The line json.loads(response.content[0].text) parses this string into a native Python dictionary, making the data immediately ready for programmatic use.

    def get_article_summary(text: str):
        if not text: return None
        
        try:
            response = client.messages.create(
                model="claude-sonnet-4-5", # Use the latest available model
                max_tokens=1024,
                temperature=0.2,
                messages=[
                    {"role": "user", "content": f"Summarize this article:\n\n{text}"}
                ],
                # Enable the beta feature
                extra_headers={
                    "anthropic-beta": "structured-outputs-2025-11-13"
                },
                # Pass the new parameter here
                extra_body={
                    "output_format": {
                        "type": "json_schema",
                        "schema": summary_schema
                    }
                }
            )
    
            # The API returns the JSON directly in the text content
            return json.loads(response.content[0].text)
    
        except anthropic.BadRequestError as e:
            print(f"API Error: {e}")
            return None
        except Exception as e:
            print(f"Error: {e}")
            return None

    This is where we pull everything together. The various URLs we want to scrape are defined. Their contents are passed to the model for processing, before the end results are displayed.

    urls = [
        "https://en.wikipedia.org/wiki/Albert_Einstein",
        "https://en.wikipedia.org/wiki/Richard_Feynman",
        "https://en.wikipedia.org/wiki/James_Clerk_Maxwell",
        "https://en.wikipedia.org/wiki/Alan_Guth"
    ]
    
    print("Scraping and analyzing articles...")
    
    for i, url in enumerate(urls):
        print(f"\n--- Processing Article {i+1} ---")
        content = get_article_content(url)
        
        if content:
            summary = get_article_summary(content)
            if summary:
                print(f"Scientist: {summary.get('name')}")
                print(f"Born:      {summary.get('born')}")
                print(f"Fame:      {summary.get('fame')}")
                print(f"Nobel:     {summary.get('prize')}")
                print(f"Died:      {summary.get('death')}")
            else:
                print("Failed to generate summary.")
        else:
            print("Skipping (No content)")
    
    print("\nDone.")

    When I ran the above code, I got this output.

    Scraping and analyzing articles...
    
    --- Processing Article 1 ---
    Scientist: Albert Einstein
    Born:      14 March 1879 in Ulm, Kingdom of Württemberg, German Empire
    Fame:      Developing the theory of relativity and the mass-energy equivalence formula E = mc2, plus contributions to quantum theory including the photoelectric effect
    Nobel:     1921
    Died:      18 April 1955
    
    --- Processing Article 2 ---
    Scientist: Richard Phillips Feynman
    Born:      May 11, 1918, in New York City
    Fame:      Path integral formulation of quantum mechanics, quantum electrodynamics, Feynman diagrams, and contributions to particle physics including the parton model
    Nobel:     1965
    Died:      February 15, 1988
    
    --- Processing Article 3 ---
    Scientist: James Clerk Maxwell
    Born:      13 June 1831 in Edinburgh, Scotland
    Fame:      Developed the classical theory of electromagnetic radiation, unifying electricity, magnetism, and light through Maxwell's equations. Also key contributions to statistical mechanics, color theory, and numerous other fields of physics and mathematics.
    Nobel:     0
    Died:      5 November 1879
    
    --- Processing Article 4 ---
    Scientist: Alan Harvey Guth
    Born:      February 27, 1947 in New Brunswick, New Jersey
    Fame:      Pioneering the theory of cosmic inflation, which proposes that the early universe underwent a phase of exponential expansion driven by positive vacuum energy density
    Nobel:     0
    Died:      Still alive
    
    Done.

    Not too shabby! Alan Guth will be delighted that he’s still alive, but alas, he hasn’t yet won a Nobel Prize. Also, note that James Clerk Maxwell had died before the Nobel Prize was in operation.

    Example code 2 — Automated Code Security & Refactoring Agent.

    Here is a completely different use case and a very practical example for software engineering. Usually, when you ask an LLM to “fix code,” it gives you a conversational response mixed with code blocks. This makes it hard to integrate into a CI/CD pipeline or an IDE plugin.

    By using Structured Outputs, we can force the model to return the clean code, a list of specific bugs found, and a security risk assessment in a single, machine-readable JSON object.

    The Scenario

    We will feed the model a Python function containing a dangerous SQL Injection vulnerability and poor coding practices. The model must identify the specific flaws and rewrite the code securely.

    import anthropic
    import httpx
    import os
    import json
    from pydantic import BaseModel, Field, ConfigDict
    from typing import List, Literal
    
    # --- SETUP ---
    http_client = httpx.Client()
    api_key = 'YOUR_API_KEY'
    client = anthropic.Anthropic(api_key=api_key, http_client=http_client)
    
    # Intentionally bad code
    bad_code_snippet = """
    import sqlite3
    
    def get_user(u):
        conn = sqlite3.connect('app.db')
        c = conn.cursor()
        # DANGER: Direct string concatenation
        query = "SELECT * FROM users WHERE username = '" + u + "'"
        c.execute(query)
        return c.fetchall()
    """
    
    # --- DEFINE SCHEMA WITH STRICT CONFIG ---
    # We add model_config = ConfigDict(extra="forbid") to ensure 
    # "additionalProperties": false is generated in the schema.
    
    class BugReport(BaseModel):
        model_config = ConfigDict(extra="forbid") 
        
        severity: Literal["Low", "Medium", "High", "Critical"]
        line_number_approx: int = Field(description="The approximate line number where the issue exists.")
        issue_type: str = Field(description="e.g., 'Security', 'Performance', 'Style'")
        description: str = Field(description="Short explanation of the bug.")
    
    class CodeReviewResult(BaseModel):
        model_config = ConfigDict(extra="forbid") 
        
        is_safe_to_run: bool = Field(description="True only if no Critical/High security risks exist.")
        detected_bugs: List[BugReport]
        refactored_code: str = Field(description="The complete, fixed Python code string.")
        explanation: str = Field(description="A brief summary of changes made.")
    
    # --- API CALL ---
    try:
        print("Analyzing code for security vulnerabilities...\n")
        
        response = client.messages.create(
            model="claude-sonnet-4-5", 
            max_tokens=2048,
            temperature=0.0,
            messages=[
                {
                    "role": "user", 
                    "content": f"Review and refactor this Python code:\n\n{bad_code_snippet}"
                }
            ],
            extra_headers={
                "anthropic-beta": "structured-outputs-2025-11-13"
            },
            extra_body={
                "output_format": {
                    "type": "json_schema",
                    "schema": CodeReviewResult.model_json_schema()
                }
            }
        )
    
        # Parse Result
        result = json.loads(response.content[0].text)
    
        # --- DISPLAY OUTPUT ---
        print(f"Safe to Run: {result['is_safe_to_run']}")
        print("-" * 40)
        
        print("BUGS DETECTED:")
        for bug in result['detected_bugs']:
            # Color code the severity (Red for Critical)
            prefix = "🔴" if bug['severity'] in ["Critical", "High"] else "🟡"
            print(f"{prefix} [{bug['severity']}] Line {bug['line_number_approx']}: {bug['description']}")
    
        print("-" * 40)
        print("REFACTORED CODE:")
        print(result['refactored_code'])
    
    except anthropic.BadRequestError as e:
        print(f"API Schema Error: {e}")
    except Exception as e:
        print(f"Error: {e}")

    This code acts as an automated security auditor. Instead of asking the AI to “chat” about code, it forces the AI to fill out a strict, digital form containing specific details about bugs and security risks.

    Here is how it works in three simple steps.

    1. First, the code defines exactly what the answer must look like using Python classes in conjunction with Pydantic. It tells the AI: “Give me a JSON object containing a list of bugs, a severity rating (like ‘Critical’ or ‘Low’) for each, and the fixed code string.”
    2. When sending the vulnerable code to the API, it passes the Pydantic blueprint using the output_format parameter. This strictly constrains the model, preventing it from hallucinating or adding conversational filler. It must return valid data matching your blueprint.
    3. The script receives the AI’s response, which is guaranteed to be machine-readable JSON. It then automatically parses this data to display a clean report, flagging the SQL injection as a “Critical” issue for example and printing the secure, refactored version of the code.

    Here is the output I received after running the code.

    Analyzing code for security vulnerabilities...
    
    Safe to Run: False
    ----------------------------------------
    BUGS DETECTED:
    🔴 [Critical] Line 7: SQL injection vulnerability due to direct string concatenation in query construction. Attacker can inject malicious SQL code through the username parameter.
    🟡 [Medium] Line 4: Database connection and cursor are not properly closed, leading to potential resource leaks.
    🟡 [Low] Line 1: Function parameter name 'u' is not descriptive. Should use meaningful variable names.
    ----------------------------------------
    REFACTORED CODE:
    import sqlite3
    from contextlib import closing
    
    def get_user(username):
        """
        Retrieve user information from the database by username.
        
        Args:
            username (str): The username to search for
            
        Returns:
            list: List of tuples containing user data, or empty list if not found
        """
        with sqlite3.connect('app.db') as conn:
            with closing(conn.cursor()) as cursor:
                # Use parameterized query to prevent SQL injection
                query = "SELECT * FROM users WHERE username = ?"
                cursor.execute(query, (username,))
                return cursor.fetchall()

    Why is this powerful?

    Integration-ready. You could run this script in a GitHub Action. If is_safe_to_run is False, you can automatically block a Pull Request.

    Separation of concerns. You get the metadata (bugs, severity) separate from the content (the code). You don’t have to use Regex to strip out “Here is your fixed code” text from the response.

    Strict typing. The severity field is constrained to specific Enum values (Critical, High, etc.), ensuring your downstream logic doesn’t break when the model returns “Severe” instead of “Critical” for example.

    Summary

    Anthropic’s release of native Structured Outputs is a game-changer for developers who need reliability, not just conversation. By enforcing strict JSON schemas, we can now treat Large Language Models less like chatbots and more like deterministic software components.

    In this article, I demonstrated how to use this new beta feature to streamline data extraction and output, and build automated workflows that integrate seamlessly with Python code. If you’re a user of Anthropic’s API, the days of writing fragile Regex to parse AI responses are finally over.

    For more information about this new beta feature, click the link below to visit Anthropics’ official documentation page.

    https://platform.claude.com/docs/en/build-with-claude/structured-outputs

    Anthropics capabilities Guide HandsOn Output Structured
    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    Awais
    • Website

    Related Posts

    Escaping the SQL Jungle | Towards Data Science

    March 21, 2026

    A Gentle Introduction to Nonlinear Constrained Optimization with Piecewise Linear Approximations

    March 21, 2026

    Agentic RAG Failure Modes: Retrieval Thrash, Tool Storms, and Context Bloat (and How to Spot Them Early)

    March 21, 2026

    Multi-Hop Data Synthesis for Generalizable Vision-Language Reasoning

    March 21, 2026

    Instagram for small business: 2026 guide to growth

    March 20, 2026

    How to Measure AI Value

    March 20, 2026
    Leave A Reply Cancel Reply

    Top Posts

    At Least 32 People Dead After a Mine Bridge Collapsed Due to Overcrowding

    November 17, 20250 Views

    Here’s how I turned a Raspberry Pi into an in-car media server

    November 17, 20250 Views

    Beloved SF cat’s death fuels Waymo criticism

    November 17, 20250 Views
    Don't Miss

    Plantain and Black Bean Salad Recipe

    March 22, 2026

    Step 1Preheat the oven to 400°F (200°C). Line a sheet pan with parchment paper.Step 2In…

    What Is Buttermilk? How It’s Made and Used

    March 22, 2026

    Why your law firm’s best leads don’t convert after research

    March 22, 2026

    For Demi Lovato, Learning to Cook Meant Starting to Heal

    March 21, 2026
    Stay In Touch
    • Facebook
    • YouTube
    • TikTok
    • WhatsApp
    • Twitter
    • Instagram
    Latest Reviews

    A Gentle Introduction to Nonlinear Constrained Optimization with Piecewise Linear Approximations

    March 21, 2026

    23 Radish Recipes for Salads, Pickles, and More

    March 21, 2026
    Most Popular

    13 Trending Songs on TikTok in Nov 2025 (+ How to Use Them)

    November 18, 20257 Views

    How to watch the 2026 GRAMMY Awards online from anywhere

    February 1, 20263 Views

    Corporate Reputation Management Strategies | Sprout Social

    November 19, 20252 Views
    Our Picks

    At Least 32 People Dead After a Mine Bridge Collapsed Due to Overcrowding

    November 17, 2025

    Here’s how I turned a Raspberry Pi into an in-car media server

    November 17, 2025

    Beloved SF cat’s death fuels Waymo criticism

    November 17, 2025

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    Facebook X (Twitter) Instagram Pinterest YouTube Dribbble
    • About Us
    • Contact Us
    • Privacy Policy
    • Terms & Conditions
    • Disclaimer

    © 2025 skytik.cc. All rights reserved.

    Type above and press Enter to search. Press Esc to cancel.