Salidas estructuradas para modelos de Anthropic Claude en Amazon Bedrock
Structured outputs for Anthropic Claude models on Amazon Bedrock
Anshika Saxena
Amazon Bedrock ahora admite salidas estructuradas para todos los modelos de Anthropic Claude, tanto en los puntos finales de tiempo de ejecución como en los de fondo, donde el modelo está disponible.
Ya sea que llame a Claude a través de Boto3 y las API de bedrock-runtime o a través de la API de Messages y el punto final de bedrock-mantle, ahora puede recibir respuestas JSON compatibles con el esquema que se ajusten a una estructura definida. Ya no necesitas un análisis personalizado, una lógica
de reintentos o un posprocesamiento.
Aplicaciones prácticas
Con los resultados estructurados para Claude en Amazon Bedrock, puede automatizar tareas confiables que cumplan con los esquemas en todos los sectores. Algunos ejemplos incluyen extraer todos los campos obligatorios de los informes de resultados financieros y los documentos de cumplimiento, analizar las notas clínicas para convertirlas en historias clínicas electrónicas (EHR) y enriquecer los catálogos de productos con resultados consistentes y validados. También puede analizar los contratos para determinar las condiciones, las partes y las obligaciones clave, o gestionar de forma inteligente las solicitudes de soporte de forma que las intenciones, las opiniones y las entidades coincidan siempre con el modelo
de datos de su aplicación.
¿Qué cambia con los resultados estructurados en Amazon Bedrock?
Las salidas estructuradas utilizan una decodificación restringida para aplicar el esquema JSON durante la generación de los tokens, no después del hecho. El modelo no produce tokens que infrinjan tu esquema. Esto cambia el formato de salida de probabilístico a
determinista.
Ahora hay dos mecanismos complementarios disponibles en ambos puntos de enlace de Amazon Bedrock:
Característica
Propósito
Caso de uso
Formato de salida del esquema JSON
Controla la estructura de respuesta del modelo
Extracción de datos, generación de informes, respuestas de API
Uso estricto de herramientas
Valide los parámetros de la herramienta comparándolos con los esquemas
Flujos de trabajo de agencia, llamadas a funciones, automatización de varios pasos
Qué significa esto para ti
Cada respuesta es un JSON válido, por lo que ya no encontrarás errores de JSON.parse () ni excepciones de análisis. Las respuestas también son seguras: los tipos de campo son obligatorios y los campos obligatorios siempre están presentes. Como los resultados siempre se ajustan a tu esquema, no necesitas volver a intentarlo para gestionar las infracciones del esquema, lo que hace que la integración sea más fiable. Los resultados estructurados también limitan las respuestas a solo los campos que defina el esquema, lo que reduce el recuento de tokens de salida y puede reducir los costos de inferencia para cargas de trabajo de gran volumen. Estas propiedades hacen que las salidas estructuradas estén listas para la producción, por lo que puedes implementarlas a escala sin necesidad
de código de validación de esquemas adicional.
Disponibilidad y modelos compatibles
Los resultados estructurados funcionan con la inferencia por lotes, por lo que puede procesar grandes volúmenes de solicitudes de forma asincrónica y, al mismo tiempo, recibir resultados que cumplan con el esquema. En el punto final de ejecución básico, también funciona con la inferencia entre regiones, por lo que puede utilizarla en todas las regiones de AWS sin necesidad de realizar ninguna configuración adicional. Si necesita respuestas en tiempo real, puede transmitir respuestas estructuradas
como eventos mecanografiados.
Cómo funciona
Cuando haces una solicitud con un esquema JSON, esto es lo que ocurre entre bastidores:
Validación de esquemas: Amazon Bedrock valida su esquema JSON comparándolo con el subconjunto JSON Schema Draft 2020-12 compatible.
Compilación gramatical: para los esquemas nuevos, Amazon Bedrock compila un artefacto gramatical (la primera solicitud puede tardar un poco más).
Almacenamiento en caché: las gramáticas compiladas se almacenan en caché durante 24 horas, lo que acelera las solicitudes posteriores.
Generación restringida: el modelo genera tokens que producen un JSON válido que coincide con su esquema.
Consideraciones sobre el rendimiento
En
cuanto al rendimiento, la primera solicitud con un esquema nuevo puede tardar más, ya que Amazon Bedrock compila un artefacto gramatical antes de que comience la generación. Tras la compilación inicial, las solicitudes subsiguientes que utilizan el mismo esquema se ejecutan con una sobrecarga mínima, ya que la gramática compilada se almacena en caché. Esta caché depende de tu cuenta y dura 24 horas desde el primer acceso. Si cambias la estructura de tu esquema JSON, se invalida la caché y se activa una nueva compilación, mientras que si cambias solo los campos de nombre o descripción, la gramática almacenada en caché permanece intacta
.
Para empezar: salidas estructuradas con la API InvokeModel (bedrock-runtime)
La API InvokeModel toma el cuerpo de la solicitud nativo de Anthropic, por lo que el esquema pasa a output_config.format como un objeto JSON en lugar de una cadena JSON. El siguiente ejemplo muestra cómo extraer los datos estructurados de los clientes potenciales del correo electrónico de un cliente mediante boto3 con un modelo de Anthropic Claude
:
Python
importar boto3
importar json
REGION = «us-east-1" # Elige tu región preferida
bedrock_runtime = boto3.client (service_name="bedrock-runtime», region_name=REGION)
# Defina el esquema JSON para la salida estructurada
esquema = {
«tipo»: «objeto»,
«propiedades»: {
«nombre»: {"type»: «cadena», «descripción»: «Nombre del cliente"},
«email»: {"type»: «string», «description»: «Dirección de correo electrónico del cliente"},
«plan_interest»: {"type»: «string», «description»: «Plan de producto de interés"},
«demo_requested»: {"type»: «boolean», «description»: «Si se solicitó una demostración"}
},
«obligatorio»: ["nombre», «correo electrónico», «plan_interest», «demo_requested"],
«Propiedades adicionales»: falso
}
# Realice una solicitud con salidas estructuradas a través de la API InvokeModel
# (reutilizando el esquema definido para el ejemplo de Converse)
respuesta = bedrock_runtime.invoke_model (
modelid="global.anthropic.claude-Sonnet-5-5",
body=json.dumps ({
«anthropic_version»: «bedrock-2023-05-31",
«max_tokens»: 512,
«mensajes»: [
{"rol»: «usuario», «contenido»: (
«Paulo Santos (paulo@example.com) está interesado en nuestro plan Enterprise»
«y quiere programar una demostración para el próximo martes a las 14:00 horas».
)}
],
«output_config»: {"formato»: {"tipo»: «json_schema», «esquema»: esquema}}
})
)
body = json.loads (response ["body"] .read ())
# Compruebe el motivo de la detención antes de analizarla
si body ["stop_reason"] == «end_turn»:
result_text = next (b ["text"] para b en el cuerpo ["content"] si b ["type"] == «text»)
print (json.dumps (json.loads (result_text), indent=2))
elif body ["stop_reason"] == «max_tokens»:
print («Respuesta truncada:
La respuesta se ajusta a su esquema. No se requiere ninguna validación adicional
.
Para ver más ejemplos de uso de la API, incluida la API Messages, consulta el cuaderno de muestra adjunto.
Uso estricto de herramientas para los flujos de trabajo de las agencias
Amazon Bedrock Mantle está diseñado para aplicaciones de agencia con herramientas del lado del servidor, inferencias en segundo plano y conversaciones con estado. Gracias al uso estricto de las herramientas en el punto final de Bedrock-Mantle, ahora puede garantizar que los parámetros de la herramienta coincidan exactamente con su esquema de entrada. El siguiente ejemplo muestra cómo definir una herramienta con un cumplimiento estricto
del esquema:
Importar json
de la importación antrópica AnthropicBedrockmantle
# Reutilizar el cliente creado en el ejemplo de la API de mensajes
client = AnthropicBedrockmantle (aws_region="us-east-1")
mensaje = client.messages.create (
model="anthropic.claude-sonnet-5",
max_tokens=512,
messages= [{"role»: «user», «content»: «¿Qué tiempo hace en San Francisco?"}] ,
herramientas = [
{
«nombre»: «get_weather»,
«description»: «Obtiene el clima actual de una ubicación específica»,
«estricto»: Cierto,
«input_schema»: {
«tipo»: «objeto»,
«propiedades»: {
«ubicación»: {
«tipo»: «cadena»,
«descripción»: «La ciudad y el estado, p. ej., San Francisco, CA»
},
«unidad»: {
«tipo»: «cadena»,
«enumeración»: ["grados Celsius», «grados Fahrenheit"],
«descripción»: «Unidad de temperatura»
}
},
«obligatorio»: ["ubicación», «unidad"],
«Propiedades adicionales»: falso
}
}
]
)
Las entradas de #Tool se ajustan al esquema
para bloquear en message.content:
si block.type == «tool_use»:
print («fTool: {block.name}»)
print (f"Entrada: {json.dumps (block.input
, indent=2)}»)
La configuración estricta: verdadera restringe la entrada de la herramienta del modelo para que coincida exactamente con su esquema. El campo de ubicación es siempre una cadena y el campo de unidad siempre está en grados Celsius o Fahrenheit. El modelo no puede agregar campos fuera del esquema, por lo que la entrada de la herramienta contiene solo lo que especifica el esquema
.
Esto es especialmente útil para los casos de uso de agencias en Amazon Bedrock Mantle, donde los modelos organizan flujos de trabajo de varios pasos con herramientas del lado del servidor, como la búsqueda web y el intérprete de código.
Principales casos de uso de las salidas estructuradas de Claude
Las salidas estructuradas son las que más reducen la complejidad de la gestión de errores en tres patrones comunes:
Extracción de datos: extraiga campos de facturas, contratos, correos electrónicos y transcripciones en un JSON que siempre coincida con su esquema, listo para cargarse en bases de datos o sistemas de gestión de relaciones con los clientes (CRM).
Llamadas confiables a las herramientas de los agentes: valide los argumentos de la herramienta comparándolos con sus esquemas en el momento de la generación, de modo que los flujos de trabajo de los agentes de varios pasos se ejecuten sin errores derivados de entradas incorrectas.
Clasificación a escala: clasifique los tickets, los clientes potenciales o el contenido según su intención, prioridad y opinión para su clasificación, moderación y evaluación.
Claude Haiku 5.5 gestiona de forma fiable cargas de trabajo rápidas y repetitivas, como resúmenes, compactaciones, consultas a bases de datos y solicitudes de clasificación. El siguiente ejemplo muestra cómo clasificar y enrutar los datos entrantes mediante la API Invoke y Haiku
5.5:
importar boto3
importar json
REGION = «us-east-1" # Elige tu región preferida
bedrock_runtime = boto3.client (service_name="bedrock-runtime», region_name=REGION)
# Esquema de clasificación: las enumeraciones restringen la salida a un conjunto fijo de etiquetas
esquema = {
«tipo»: «objeto»,
«propiedades»: {
«categoría»: {
«tipo»: «cadena»,
«enum»: ["facturación», «técnico», «cuenta», «ventas», «otros"],
«description»: «Categoría principal de entrada»
},
«prioridad»: {
«tipo»: «cadena»,
«enum»: ["bajo», «medio», «alto», «urgente"],
«description»: «La urgencia se basa en el impacto empresarial»
},
«sentimiento»: {
«tipo»: «cadena»,
«enum»: ["positivo», «neutro», «negativo"],
«descripción»: «Sentimiento del cliente»
},
«escalate»: {"type»: «boolean», «description»: «Si un humano debe revisar inmediatamente"},
«reason»: {"type»: «string», «description»: «Justificación de la clasificación en una frase"}
},
«obligatorio»: ["categoría», «prioridad», «sentimiento», «escalar», «motivo"],
«Propiedades adicionales»: falso
}
billete = (
«Nuestras llamadas a la API de producción han fallado con 500 errores desde esta mañana. »
«Perdemos pedidos cada minuto. ¡Este es el segundo apagón de este mes!»
)
# Realice una solicitud con salidas estructuradas a través de la API InvokeModel
respuesta = bedrock_runtime.invoke_model (
modelid="global.anthropic.claude-haiku-5-5",
body=json.dumps ({
«anthropic_version»: «bedrock-2023-05-31",
«max_tokens»: 512,
«system»: «Eres un clasificador de tickets de soporte. Clasifica el ticket con precisión. «,
«mensajes»: [
{"role»: «usuario», «contenido»: f"Clasifica este ticket de soporte:\n\n{ticket} "}
],
«output_config»: {"formato»: {"tipo»: «json_schema», «esquema»: esquema}}
})
)
body = json.loads (response ["body"] .read ())
# Compruebe el motivo de la detención antes de analizarla
si body ["stop_reason"] == «end_turn»:
result_text = next (b ["text"] para b en el cuerpo ["content"] si b ["type"] == «text»)
resultado = json.loads (result_text)
print (json.dumps (resultado, indent=2))
# Distribuya el billete basándose en las etiquetas de validez garantizada
si el resultado ["escalar"]:
print (f"Pasando a estar de guardia: {result ['category']}/{result ['priority']}»)
elif body ["stop_reason"] == «max_tokens»:
print («Respuesta truncada:
aumenta los max_tokens y vuelve a intentarlo»)
Requisitos y mejores prácticas
Para utilizar los resultados estructurados de forma eficaz en Amazon Bedrock, siga estas directrices:
Establecer additionalProperties: false en todos los objetos: esto es necesario para que funcionen las salidas estructuradas. Sin él, tu esquema no será aceptado
.
Utilice nombres de campo y descripciones descriptivos: los modelos utilizan nombres y descripciones de propiedades para saber qué datos extraer.
Los nombres claros, como customer_email, superan a los nombres genéricos, como field1.
Usa la enumeración para valores restringidos: cuando un campo tiene un conjunto limitado de valores válidos, usa la enumeración para restringir las opciones.
Comience con lo básico y, a continuación, añada complejidad: comience con los campos mínimos obligatorios y añada complejidad de forma gradual. Los esquemas básicos se compilan más rápido, son más fáciles de depurar y reducen la carga útil de las solicitudes, ya que el esquema se tiene en cuenta para el tamaño de la carga útil de la API de Converse
.
Reutiliza
los esquemas para aprovechar las ventajas del almacenamiento en caché: estructura tu aplicación para reutilizar los esquemas en todas las solicitudes. La caché gramatical de 24 horas mejora el rendimiento de las consultas repetidas
.
Comprueba el motivo de la suspensión en cada respuesta: hay dos situaciones en las que se pueden dar respuestas no conformes: las rechazadas (cuando el modelo se niega por motivos de seguridad) y los límites simbólicos (cuando se alcanza el límite máximo de fichas antes de completarse). Maneja ambos casos
en tu código.
Realice pruebas con datos realistas antes de la implementación: valide sus esquemas comparándolos con datos representativos de la producción. Los casos extremos en datos reales suelen revelar problemas de diseño del esquema
.
Para obtener recomendaciones adicionales sobre prácticas recomendadas y diseño de esquemas, consulte Resultados estructurados en la Guía del usuario de Amazon Bedrock.
Funciones del esquema JSON compatibles
Todos los tipos básicos: objeto, matriz, cadena, entero, número, booleano, nulo.
enumeración (solo cadenas, números, valores booleanos o nulos).
const, anyOf, allOf(con limitaciones).
$ref, $def y definiciones (solo referencias internas).
Formatos de cadena: fecha y hora, fecha, duración, correo electrónico, nombre de host, uri, ipv4, ipv6, uuid.
Array minItems (solo valores 0 y 1).
No se admite
La API acepta estas palabras clave, pero no se aplican durante la generación. Una solicitud que las incluye devuelve una respuesta correcta y el modelo aún puede devolver valores que las infrinjan. Valide estas restricciones en su aplicación en lugar de confiar en el esquema para aplicarlas.
AdditionalProperties se establece en cualquier valor que no sea falso.
Conclusión
Los
resultados estructurados para los modelos de Anthropic Claude en Amazon Bedrock proporcionan la confiabilidad que requieren las aplicaciones de IA de producción. Ya está disponible tanto en el punto final de Bedrock-Runtime como en el de Bedrock-mantle. Al combinar el formato de salida del esquema JSON y el uso estricto de herramientas, puede crear canalizaciones de datos que no necesitan ninguna validación adicional. También puede crear flujos de trabajo de agencia confiables y aplicaciones de inteligencia artificial de producción sin una lógica personalizada de análisis
o reintento.
Los resultados estructurados para Claude en Amazon Bedrock ya están disponibles de forma general. Para obtener más información, consulte la documentación de Amazon Bedrock y explore nuestro cuaderno de ejemplo
.
¿Qué flujos de trabajo podrían mejorar en su organización un JSON validado y compatible con los esquemas? Comparte tus comentarios y preguntas en los
comentarios.
Acerca de los autores
Amazon Bedrock now supports structured outputs for all Anthropic Claude models, on both the bedrock-runtime and bedrock-mantle endpoints, where the model is available.
Whether you call Claude through Boto3 and the bedrock-runtime APIs or through the Messages API and the bedrock-mantle endpoint, you can now receive schema-compliant JSON responses that conform to a defined structure. You no longer need custom parsing, retry logic, or post-processing.
Practical applications
With structured outputs for Claude on Amazon Bedrock, you can automate reliable, schema-compliant tasks across industries. Examples include extracting every required field from financial earnings reports and compliance documents, parsing clinical notes into Electronic Health Records (EHR), and enriching product catalogs with consistent, validated results. You can also analyze contracts for key terms, parties, and obligations, or power intelligent support ticket routing where intents, sentiments, and entities always match your application’s data model.
What changes with structured outputs on Amazon Bedrock
Structured outputs use constrained decoding to enforce your JSON schema during token generation, not after the fact. The model doesn’t produce tokens that would violate your schema. This changes output formatting from probabilistic to deterministic.
Two complementary mechanisms are now available on both Amazon Bedrock endpoints:
Feature
Purpose
Use case
JSON Schema output format
Control the model’s response structure
Data extraction, report generation, API responses
Strict tool use
Validate tool parameters against schemas
Agentic workflows, function calling, multi-step automation
What this means for you
Each response is a valid JSON, so you no longer encounter JSON.parse() errors or parsing exceptions. Responses are also type safe: field types are enforced, and required fields are always present. Because outputs always conform to your schema, you don’t need retries to handle schema violations, making your integration more reliable. Structured outputs also constrains responses to only the fields your schema defines, which reduces output token count and can lower inference costs for high-volume workloads. These properties make structured outputs production ready, so you can deploy at scale without additional schema-validation code.
Supported models and availability
Structured outputs works with batch inference, so you can process large volumes of requests asynchronously while still receiving schema-compliant outputs. On the bedrock-runtime endpoint, it also works with cross-Region inference, so you can use it across AWS Regions without additional setup. If you need responses in real time, you can stream structured responses as typed events.
How it works
When you make a request with a JSON schema, here’s what happens behind the scenes:
Schema validation – Amazon Bedrock validates your JSON schema against the supported JSON Schema Draft 2020-12 subset.
Grammar compilation – For new schemas, Amazon Bedrock compiles a grammar artifact (the first request might take slightly longer).
Caching – Compiled grammars are cached for 24 hours, making subsequent requests faster.
Constrained generation – The model generates tokens that produce valid JSON matching your schema.
Performance considerations
For performance, the first request with a new schema might take longer because Amazon Bedrock compiles a grammar artifact before generation begins. After that initial compilation, subsequent requests using the same schema run with minimal overhead because the compiled grammar is cached. This cache is scoped to your account and lasts for 24 hours from first access. Changing the structure of your JSON schema invalidates the cache and triggers a fresh compilation, while changing only the name or description fields leaves the cached grammar intact.
Getting started: Structured outputs with the InvokeModel API (bedrock-runtime)
The InvokeModel API takes the Anthropic-native request body, so the schema goes in output_config.format as a JSON object rather than a JSON string. The following example shows how to extract the structured lead data from a customer email using boto3 with an Anthropic Claude model:
Python
import boto3
import json
REGION = "us-east-1" # Choose your preferred region
bedrock_runtime = boto3.client(service_name="bedrock-runtime", region_name=REGION)
# Define the JSON schema for structured output
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 a request with structured outputs via the InvokeModel API
# (reusing the schema defined for the Converse example)
response = bedrock_runtime.invoke_model(
modelId="global.anthropic.claude-sonnet-5-5",
body=json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 512,
"messages": [
{"role": "user", "content": (
"Paulo Santos (paulo@example.com) is interested in our Enterprise plan "
"and wants to schedule a demo for next Tuesday at 2pm."
)}
],
"output_config": {"format": {"type": "json_schema", "schema": schema}}
})
)
body = json.loads(response["body"].read())
# Check the stop reason before parsing
if body["stop_reason"] == "end_turn":
result_text = next(b["text"] for b in body["content"] if b["type"] == "text")
print(json.dumps(json.loads(result_text), indent=2))
elif body["stop_reason"] == "max_tokens":
print("Response truncated: increase max_tokens and retry.")
The response conforms to your schema. No additional validation is required.
For additional API usage examples, including the Messages API, see the accompanying sample notebook.
Strict tool use for agentic workflows
Amazon Bedrock Mantle is designed for agentic applications with server-side tools, background inference, and stateful conversations. With strict tool use on the bedrock-mantle endpoint, you can now guarantee that tool parameters match your input schema exactly. The following example shows how to define a tool with strict schema enforcement:
Import json
from anthropic import AnthropicBedrockMantle
# Reusing the client created in the Messages API example
client = AnthropicBedrockMantle(aws_region="us-east-1")
message = client.messages.create(
model="anthropic.claude-sonnet-5",
max_tokens=512,
messages=[{"role": "user", "content": "What's the weather like in San Francisco?"}],
tools=[
{
"name": "get_weather",
"description": "Get the current weather for a specified location",
"strict": True,
"input_schema": {
"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 block in message.content:
if block.type == "tool_use":
print(f"Tool: {block.name}")
print(f"Input: {json.dumps(block.input, indent=2)}")
Setting strict: true constrains the model’s tool input to match your schema exactly. The location field is always a string, and the unit field is always either celsius or fahrenheit. The model can’t add fields outside your schema, so the tool input contains only what your schema specifies.
This is especially valuable for agentic use cases on Amazon Bedrock Mantle, where models orchestrate multi-step workflows with server-side tools like web search and code interpreter.
Top use cases for Claude structured outputs
Structured outputs reduce error-handling complexity the most in three common patterns:
Data extraction: Extract fields from invoices, contracts, email, and transcripts into JSON that always matches your schema, ready to load into databases or customer relationship management (CRM) systems.
Reliable agent tool calls: Validate tool arguments against their schemas at generation time, so multi-step agent workflows run without failures from malformed input.
Classification at scale: Classify tickets, leads, or content by intent, priority, and sentiment for routing, moderation, and evaluation.
Claude Haiku 5.5 reliably handles quick and repetitive workloads such as summaries, compactions, database queries, and classification requests. The following example shows how to classify and route incoming data using the Invoke API and Haiku 5.5:
import boto3
import json
REGION = "us-east-1" # Choose your preferred region
bedrock_runtime = boto3.client(service_name="bedrock-runtime", region_name=REGION)
# Classification schema: enums restrict output to a fixed set of labels
schema = {
"type": "object",
"properties": {
"category": {
"type": "string",
"enum": ["billing", "technical", "account", "sales", "other"],
"description": "Primary ticket category"
},
"priority": {
"type": "string",
"enum": ["low", "medium", "high", "urgent"],
"description": "Urgency based on business impact"
},
"sentiment": {
"type": "string",
"enum": ["positive", "neutral", "negative"],
"description": "Customer sentiment"
},
"escalate": {"type": "boolean", "description": "Whether a human should review immediately"},
"reason": {"type": "string", "description": "One-sentence justification for the classification"}
},
"required": ["category", "priority", "sentiment", "escalate", "reason"],
"additionalProperties": False
}
ticket = (
"Our production API calls have been failing with 500 errors since this morning. "
"We're losing orders every minute. This is the second outage this month!"
)
# Make a request with structured outputs via the InvokeModel API
response = bedrock_runtime.invoke_model(
modelId="global.anthropic.claude-haiku-5-5",
body=json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 512,
"system": "You are a support ticket classifier. Classify the ticket accurately.",
"messages": [
{"role": "user", "content": f"Classify this support ticket:\n\n{ticket}"}
],
"output_config": {"format": {"type": "json_schema", "schema": schema}}
})
)
body = json.loads(response["body"].read())
# Check the stop reason before parsing
if body["stop_reason"] == "end_turn":
result_text = next(b["text"] for b in body["content"] if b["type"] == "text")
result = json.loads(result_text)
print(json.dumps(result, indent=2))
# Route the ticket based on the guaranteed-valid labels
if result["escalate"]:
print(f"Escalating to on-call: {result['category']} / {result['priority']}")
elif body["stop_reason"] == "max_tokens":
print("Response truncated: increase max_tokens and retry.")
Requirements and best practices
To use structured outputs effectively on Amazon Bedrock, follow these guidelines:
Set additionalProperties: false on all objects: This is required for structured outputs to work. Without it, your schema won’t be accepted.
Use descriptive field names and descriptions: Models use property names and descriptions to understand what data to extract. Clear names like customer_email outperform generic names like field1.
Use enum for constrained values: When a field has a limited set of valid values, use enum to constrain options.
Start basic, then add complexity: Begin with the minimum required fields and add complexity incrementally. Basic schemas compile faster, are easier to debug, and keep your request payload lean because the schema counts toward the Converse API payload size.
Reuse schemas to benefit from caching: Structure your application to reuse schemas across requests. The 24-hour grammar cache improves performance for repeated queries.
Check the stop reason in every response: Two scenarios can produce non-conforming responses: refusals (when the model declines for safety reasons) and token limits (when max_tokens is reached before completing). Handle both cases in your code.
Test with realistic data before deployment: Validate your schemas against production-representative inputs. Edge cases in real data often reveal schema design issues.
For additional best practices and schema design recommendations, see Structured outputs in the Amazon Bedrock User Guide.
Supported JSON Schema features
All basic types: object, array, string, integer, number, boolean, null.
enum (strings, numbers, booleans, or nulls only).
const, anyOf, allOf (with limitations).
$ref, $def, and definitions (internal references only).
These keywords are accepted by the API but are not enforced during generation. A request that includes them returns a successful response, and the model can still return values that violate them. Validate these constraints in your application rather than relying on the schema to enforce them.
additionalProperties set to anything other than false.
Conclusion
Structured outputs for Anthropic Claude models on Amazon Bedrock provides the reliability that production AI applications require. It is available now on both the bedrock-runtime and bedrock-mantle endpoints. By combining JSON Schema output format and strict tool use, you can build data pipelines that need no additional validation. You can also create reliable agentic workflows and production AI applications without custom parsing or retry logic.