Amazon Bedrock Structured Output: Schema-compliant AI responses

Machine Learning


Today we are announcing structured output for Amazon Bedrock. This is a feature that fundamentally changes the way you get validated JSON responses from your underlying models through constrained decoding for schema compliance.

This represents a paradigm shift in AI application development. Instead of validating the JSON response and creating fallback logic in case the response fails, you can proceed directly to building with the data. With structured output, you can build zero-validation data pipelines that trust model outputs, reliable agent systems that confidently call external functions, and simplified application architectures without retry logic.

In this post, we explore the challenges of traditional JSON generation and how structured output solves them. This article describes two core mechanisms: the JSON Schema output format and rigorous tooling, along with implementation details, best practices, and practical code examples. Whether you’re building data extraction pipelines, agent workflows, or AI-powered APIs, learn how to use structured output to create reliable, production-ready applications. A companion Jupyter notebook provides practical examples of all the features described here.

Traditional JSON generation issues

For years, getting structured data from language models has required writing detailed prompts, hoping for the best, and building elaborate error handling systems. Even with careful prompting, developers routinely encounter problems such as:

  • Analysis failure: Invalid JSON syntax that breaks json.loads() phone
  • missing field: A required data point is missing from the response
  • Type mismatch: A string that expects an integer. Downstream processing is interrupted.
  • Schema violation: Responses that are technically parsed but do not match the data model.

In production systems, these failures are even worse. A single bad response can cascade through the pipeline, requiring retries and increasing latency and cost. If your model is an agent workflow that calls a tool, invalid parameters can completely abort the function call.

Consider a reservation system that requires . passengers: int. If you don’t enforce the schema, your model may be returned passengers: "two" or passengers: "2"– Syntactically valid JSON, but semantically incorrect as a function signature.

What changes with structured output?

Structured output in Amazon Bedrock is not an incremental improvement, but a fundamental shift from a probabilistic to a deterministic output format. Amazon Bedrock constrains the model response to conform to the specified JSON schema through constrained decoding. Two complementary mechanisms are available:

Features the purpose Use case
JSON Schema output format Control the model response format Data extraction, report generation, API responses
Use of rigorous tools Validate tool parameters Agent workflows, function calls, and multi-step automation

These features can be used individually or in combination, giving you precise control over both your model’s output and how your functions are called.

Structured output gives you:

  • always valid: No more JSON.parse() error or parsing exception
  • type safe: Field type is applied and required fields are always present.
  • reliable: No retries required for schema violations
  • Ready for production: Deploy with confidence at enterprise scale

How structured output works

Structured output uses constrained sampling with compiled grammar artifacts. When you make a request, the following happens:

  1. Schema validation: Amazon Bedrock validates JSON Schemas against a supported JSON Schema Draft 2020-12 subset.
  2. grammar compilation: For new schemas, Amazon Bedrock compiles the grammar (the first request may take a while)
  3. caching: Compiled grammars are cached for 24 hours, speeding up subsequent requests.
  4. constrained generation: The model generates a token that produces valid JSON that matches the schema.

Performance considerations:

  • First request latency: Initial compilation can add latency to new schemas
  • cached performance: Subsequent requests with the same schema have minimal overhead
  • cache scope: Grammars are cached per account for 24 hours from first access

Changing the JSON schema structure or the tool’s input schema invalidates the cache, but only changes. name or description Not in the field.

Start structured output

The following example shows structured output using the Converse API.

import boto3
import json
# Initialize the Bedrock Runtime client
bedrock_runtime = boto3.client(
    service_name="bedrock-runtime",
    region_name="us-east-1"  # Choose your preferred region
)
# Define your JSON schema
extraction_schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string", "description": "Customer name"},
        "email": {"type": "string", "description": "Customer email address"},
        "plan_interest": {"type": "string", "description": "Product plan of interest"},
        "demo_requested": {"type": "boolean", "description": "Whether a demo was requested"}
    },
    "required": ["name", "email", "plan_interest", "demo_requested"],
    "additionalProperties": False
}
# Make the request with structured outputs
response = bedrock_runtime.converse(
    modelId="us.anthropic.claude-opus-4-5-20251101-v1:0",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "text": "Extract the key information from this email: John Smith (john@example.com) is interested in our Enterprise plan and wants to schedule a demo for next Tuesday at 2pm."
                }
            ]
        }
    ],
    inferenceConfig={
        "maxTokens": 1024
    },
    outputConfig={
        "textFormat": {
            "type": "json_schema",
            "structure": {
                "jsonSchema": {
                    "schema": json.dumps(extraction_schema),
                    "name": "lead_extraction",
                    "description": "Extract lead information from customer emails"
                }
            }
        }
    }
)
# Parse the schema-compliant JSON response
result = json.loads(response["output"]["message"]["content"][0]["text"])
print(json.dumps(result, indent=2))

output:

{
  "name": "John Smith",
  "email": "john@example.com",
  "plan_interest": "Enterprise",
  "demo_requested": true
}

The response conforms to the schema, so no additional validation is required.

Requirements and best practices

Follow these guidelines to use structured output effectively:

  • set additionalProperties: false to all objects. This is required for structured output to work. Without this, the schema will not be accepted.
{
  "type": "object",
  "properties": {
    "name": {"type": "string"}
  },
  "required": ["name"],
  "additionalProperties": false
}

  • Use meaningful field names and descriptions. The model uses the property name and description to understand what data to extract. A clear name such as customer_email performs better than common names like field1.
  • use enum For constrained values. If a field has a limited set of valid values, use: enum To constrain your choices. This improves accuracy and produces valid values.
  • Start with the basics and then add complexity. Start with the minimum required fields and gradually add complexity. Basic schemas compile faster and are easier to maintain.
  • Reuse schemas to take advantage of caching. Structure your application to reuse schemas across requests. 24-hour grammar caching significantly improves performance for repeated queries.
  • check stopReason In every reaction. Two scenarios can generate nonconforming responses. Rejection (if the model is rejected for safety reasons) and Token Restriction (if: max_tokens (reached before completion). Handle both cases in your code.
  • Test with realistic data before deployment. Validate your schema against input representative of your production environment. Edge cases in real-world data often reveal schema design issues.

Supported JSON Schema features:

  • All basic types: object, array, string, integer, number, boolean, null
  • enum (string, number, boolean, or null only)
  • const, anyOf, allOf (with restrictions)
  • $ref, $defand definitions (internal reference only)
  • String format: date-time, time, date, duration, email, hostname, uri, ipv4, ipv6, uuid
  • array minItems (values ​​0 and 1 only)

What’s not supported:

  • recursive schema
  • external $ref References
  • Numerical constraints (minimum, maximum, multipleOf)
  • String constraints (minLength, maxLength)
  • additionalProperties set to something other than false

Using rigorous tools for agent workflows

When building an application where the model calls a tool, strict: true Constrain the tool parameters to exactly match the input schema in the tool definition.

import boto3
import json
bedrock_runtime = boto3.client('bedrock-runtime', region_name="us-east-1")
response = bedrock_runtime.converse(
    modelId="us.anthropic.claude-opus-4-5-20251101-v1:0",
    messages=[
        {
            "role": "user",
            "content": [{"text": "What's the weather like in San Francisco?"}]
        }
    ],
    inferenceConfig={"maxTokens": 1024},
    toolConfig={
        "tools": [
            {
                "toolSpec": {
                    "name": "get_weather",
                    "description": "Get the current weather for a specified location",
                    "strict": True,  # Enable strict mode
                    "inputSchema": {
                        "json": {
                            "type": "object",
                            "properties": {
                                "location": {
                                    "type": "string",
                                    "description": "The city and state, e.g., San Francisco, CA"
                                },
                                "unit": {
                                    "type": "string",
                                    "enum": ["celsius", "fahrenheit"],
                                    "description": "Temperature unit"
                                }
                            },
                            "required": ["location", "unit"],
                            "additionalProperties": False
                        }
                    }
                }
            }
        ]
    }
)
# Tool inputs conform to the schema
for content_block in response["output"]["message"]["content"]:
    if "toolUse" in content_block:
        tool_input = content_block["toolUse"]["input"]
        print(f"Tool: {content_block['toolUse']['name']}")
        print(f"Input: {json.dumps(tool_input, indent=2)}")

and strict: truestructured output constrains the output as follows:

  • of location field is always a string
  • of unit The field is always either celsius or fahrenheit
  • No unexpected fields appear in input

Practical applications across industries

This notebook demonstrates use cases across a variety of industries.

  • financial services: Extract structured data from revenue reports, loan applications, and compliance documents. In structured output, all required fields are present and correctly populated for downstream processing.
  • health care: Parses clinical notes to create structured, schema-compliant records. Extract patient information, diagnosis, and treatment plans into validated JSON for EHR integration.
  • e-commerce: Build a reliable product catalog enrichment pipeline. Extract specifications, categories, and attributes from product descriptions for consistent and reliable results.
  • legal: Analyzes contracts, extracting key terms, parties, dates, and obligations and converting them into a structured format suitable for contract management systems.
  • customer service: Build an intelligent ticket routing and response system where extracted intents, sentiment, and entities match your application’s data model.

Choosing the right approach

Our testing revealed a clear pattern for when to use each feature.

Use the JSON Schema output format when:

  • When you need model response with a specific structure
  • Building a data extraction pipeline
  • Generating API-enabled responses
  • Create structured reports or summaries

Use the tool strictly in the following cases:

  • Building an agent system that calls external functions
  • Implementing multi-step workflows using toolchains
  • Require validated parameter types for function calls
  • Connect AI to databases, APIs, or external services

Use both together when:

  • Build complex agents that require validated tool calls and structured final responses
  • Creating a system where the results of intermediate tools feed into structured output
  • Implementing enterprise workflows that require end-to-end schema compliance

API Comparison: Converse vs. InvokeModel

Both the Converse and InvokeModel APIs support structured output with slightly different parameter formats.

side Converse API InvokeModel (human Claude) InvokeModel (open weight model)
Schema location outputConfig.textFormat output_config.format response_format
tool strict flag toolSpec.strict tools[].strict tools[].function.strict
schema format JSON string input jsonSchema.schema JSON object schema JSON object json_schema.schema
Ideal for these people conversational workflow One Turn Reasoning (Claude) Single turn inference (open weight)

Note: The InvokeModel API uses different request field names depending on the model type. For the human Claude model, use: output_config.format For JSON Schema output. For open weight models, use: response_format Instead.

Choose the Converse API for multi-turn conversations, and choose the InvokeModel API when you need direct access to the model in a provider-specific request format.

Supported models and availability

Structured output is generally available in all commercial AWS Regions for some Amazon Bedrock model providers.

  • human
  • deep seek
  • google
  • mini max
  • Mistral AI
  • Moonshot AI
  • Nvidia
  • OpenAI
  • Kwen

This feature works seamlessly with:

  • Cross-region inference: Use structured output across AWS Regions without any additional setup
  • batch inference: Handle large volumes with schema-compliant output
  • streaming: Stream a structured response. ConverseStream or InvokeModelWithResponseStream

conclusion

In this post, we discovered how Amazon Bedrock’s structured output reduces uncertainty in AI-generated JSON through validated, schema-compliant responses. Using the JSON Schema output format and rigorous tooling, you can build reliable data extraction pipelines, robust agent workflows, and production-ready AI applications without custom parsing or validation logic. Whether you’re extracting data from documents, building intelligent automation, or creating AI-powered APIs, structured output provides the reliability your applications demand.

Structured output is now generally available on Amazon Bedrock. To use structured output with the Converse API, update to the latest AWS SDK. For more information, see the Amazon Bedrock documentation and view sample notebooks.

What workflows can unlock validated, schema-compliant JSON in my organization? The notebook has everything you need to find out.


About the author

Jeffrey Zeng

Jeffrey Zeng is a Worldwide Specialist Solutions Architect for Generative AI at AWS and leads third-party models at Amazon Bedrock. He focuses on agent coding and workflows, and has hands-on experience helping customers build and deploy AI solutions from proof of concept to production.

Jonathan Evans

Jonathan Evans is a Worldwide Solutions Architect for Generative AI at AWS, helping customers leverage cutting-edge AI technology to solve complex business challenges using Anthropic Claude models on Amazon Bedrock. With a background in AI/ML engineering and hands-on experience supporting machine learning workflows in the cloud, Jonathan is passionate about making advanced AI accessible and impactful for organizations of all sizes.



Source link