Amazon Bedrock Ships Structured Outputs for Claude: Schema-Valid JSON on Both Endpoints
Structured outputs for Claude on Amazon Bedrock enforce JSON schemas during token generation on both endpoints. Here is what to change in your pipelines.
AWS has made structured outputs generally available for all Anthropic Claude models on Amazon Bedrock, where the model is available, per an Oct. 19 launch post on the AWS Machine Learning Blog. The feature works on both Bedrock endpoints: bedrock-runtime for teams calling Claude through Boto3, and bedrock-mantle for teams using the Messages API. Responses arrive as JSON that conforms to a schema you define, enforced during token generation rather than checked afterward. For anyone running Claude extraction, classification or tool-calling agents on Bedrock, the parse-and-retry glue most of those pipelines carry can come out.

Two mechanisms, one guarantee
Structured outputs use constrained decoding. Bedrock compiles your JSON schema into a grammar, and the model does not produce tokens that would violate it. AWS describes the shift as output formatting moving from probabilistic to deterministic. Two complementary mechanisms are available on both endpoints:
| Mechanism | Purpose | Best for |
|---|---|---|
| JSON Schema output format | Controls the structure of the model response | Data extraction, report generation, API responses |
| Strict tool use | Validates tool parameters against schemas | Agentic workflows, function calling, multi-step automation |
The practical consequences are reliability and cost. Every response is valid JSON, field types are enforced, required fields are always present, and no retries are needed to handle schema violations. Because responses are constrained to the fields your schema defines, output token counts shrink, which AWS notes can lower inference costs for high-volume workloads. For unattended lanes, that removes the failure mode that quietly re-bills prompts: a malformed JSON response, a retry, and another full generation.
How a request is processed
Per the post, Bedrock validates your schema against a supported JSON Schema Draft 2020-12 subset, compiles a grammar artifact for new schemas, caches compiled grammars for 24 hours scoped to your account, and then generates tokens under constraint. The first request with a new schema may take slightly longer while the grammar compiles; subsequent requests run with minimal overhead. The cache has an edge worth designing around: changing the structure of a schema invalidates it and triggers a fresh compilation, but changing only name or description fields leaves the cached grammar intact. Structured outputs also work with batch inference, with cross-Region inference on the bedrock-runtime endpoint, and with streaming, where responses arrive as typed events.
What to change in your code
The schema travels in the Anthropic-native request body under output_config.format, as a JSON object rather than a string. This example, adapted from the AWS post, classifies a support ticket with Claude Haiku 5.5:
import boto3, json
client = boto3.client(service_name="bedrock-runtime", region_name="us-east-1")
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!"
)
schema = {
"type": "object",
"properties": {
"category": {"type": "string", "enum": ["billing", "technical", "other"]},
"priority": {"type": "string", "enum": ["low", "medium", "high", "urgent"]},
"escalate": {"type": "boolean"},
},
"required": ["category", "priority", "escalate"],
"additionalProperties": False, # required, or the schema is rejected
}
response = client.invoke_model(
modelId="global.anthropic.claude-haiku-5-5",
body=json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 512,
"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())
if body["stop_reason"] == "end_turn":
result = json.loads(next(b["text"] for b in body["content"] if b["type"] == "text"))
elif body["stop_reason"] == "max_tokens":
raise ValueError("truncated: increase max_tokens and retry")
Two requirements will bite the unwary. First, additionalProperties: false is mandatory on every object; without it the schema is not accepted. Second, keep checking stop_reason in every response. AWS names exactly two scenarios that can still produce non-conforming output: a safety refusal, and hitting max_tokens before the JSON completes. Schema conformance is guaranteed only when the model actually finishes the turn.
For agentic lanes, strict tool use sets strict to true on a tool definition and guarantees parameters match the input schema exactly: enum fields stay enums, and the model cannot add fields outside the schema. The malformed-tool-input failure class disappears at generation time, which matters most for multi-step workflows with server-side tools like web search and code interpreter.
Design inside the enforced subset
The support matrix has a sharp edge: unsupported keywords are accepted by the API and return a successful response, but they are not enforced during generation. Recursive schemas, external $ref references, numerical constraints such as minimum and maximum, and string constraints such as minLength and maxLength all fall into this silent gap. If your current validator depends on them, keep that application-level check. The post’s remaining schema guidance: use descriptive field names and descriptions because the model reads them, use enum for constrained value sets, start with a minimal schema and add complexity incrementally, and reuse schemas so the 24-hour grammar cache pays off.
Why this matters beyond one feature
The Bedrock User Guide recommends the bedrock-runtime endpoint for new applications and lists more than 100 foundation models from providers including Anthropic, OpenAI and xAI. The Bedrock overview page says the platform powers generative AI for more than 100,000 organizations and never stores or uses customer data to train models. For teams already running Claude on Bedrock under those constraints, AWS positions structured outputs as production ready: deploy at scale without additional schema-validation code, because every finished response conforms to the enforced portion of the schema you sent. Keywords outside that subset, such as minimum, maxLength or recursive references, still need the application-level checks described above.
If you run managed agents across Bedrock and rival platforms, structured outputs change the failover math: a lane that emits schema-valid JSON can drop its provider-specific validation shim, but the shim returns the moment you fail over to a platform without constrained decoding. Related reading: GLM 5.3 on Bedrock, contract-testing tool schemas and AgentCore Payments.
The bottom line: schema enforcement moves from your retry handler into the inference call. Delete the parse-and-retry glue, keep the stop_reason checks, design inside the enforced subset, and reuse schemas so the grammar cache works for you.