← Back to blog
Analysis

After Bedrock opened Claude structured outputs on 20 October 2026, which text block holds the Haiku 5.5 JSON?

Published 2026-10-21Updated 2026-10-21About 12 minJSON Toolbox

Where this note goes

As of 2026-10-21, AWS announced on 2026-10-20 that Claude on Amazon Bedrock can use structured outputs. The user-guide classification example sets the model to global.anthropic.claude-haiku-5-5. The JSON is not the first content block. It is the block whose type is text, and only after stop_reason is end_turn. Do not parse text truncated by max_tokens. Why a local schema still closes the object: why AI models like JSON. The 12 October note described Bedrock before this capability: why Haiku 5.5 still needs a local JSON check.

You classify a ticket with Haiku 5.5: category, priority, sentiment, and whether to escalate. Bedrock can now generate against the schema you send. The page says no extra validation is required. The same set of pages also says to read stop_reason first, and lists keywords that return 400 immediately. Miss one step, and a thinking block or a half-written string lands in the database.

What 20 October actually opened

As of 2026-10-21, from the AWS What's New post dated 2026-10-20 and the Bedrock user guide:

  • Two endpoints: bedrock-runtime and bedrock-mantle. On runtime you can use Converse, InvokeModel, or the Anthropic Messages API. On mantle you use the Anthropic Messages API, at a URL shaped like https://bedrock-mantle.{region}.api.aws/anthropic/v1/messages.
  • Two mechanisms: a JSON Schema output format, and strict: true on a tool. You can use them separately or in the same request.
  • Model range: the user guide names the Sonnet, Opus, Haiku, Fable, and Mythos families, and says support varies by model and endpoint. Regions are on the model card. The Haiku 5.5 classification example uses global.anthropic.claude-haiku-5-5.
  • Not every profile: the docs give an example. On the India inference profile in.anthropic, structured outputs are not supported for Claude Haiku 4.5. This page does not list every Haiku 5.5 inference profile.

As of 2026-10-12, the Claude platform release notes said Amazon Bedrock had no structured outputs for Claude Haiku 5.5. Read again on 2026-10-21, that sentence is no longer in the 7 October bullet. Follow the Haiku 5.5 example in the AWS user guide. Do not let the older “not available” line block a request the current page shows.

One line. Haiku 5.5 on Bedrock can return structured JSON. Confirm end_turn, then read the text block.

The JSON is in the text block, not the first block

When stop_reason is end_turn, the classification example takes the content block whose type is text, then JSON.parse. For max_tokens, the docs say to raise the limit and retry. They do not treat that text as a complete result.

The Claude release notes still say Haiku 5.5 has adaptive thinking on by default, so a reply can start with a thinking block. Unless you set thinking.display to summarized, the thinking text is omitted. The example does not read content[0]. The first block can be thinking. The JSON is in a later text block.

The same Haiku 5.5 note still says temperature, top_p, and top_k can return 400. A generic InvokeModel example includes "temperature": 1.0. The Haiku 5.5 classification example does not. Follow the classification example. Do not copy sampling parameters from the generic example.

InvokeModel and Converse do not carry the same schema JSON

An InvokeModel request for Claude puts the schema in output_config.format. schema is an object, not a string:

{
  "anthropic_version": "bedrock-2023-05-31",
  "max_tokens": 512,
  "output_config": {
    "format": {
      "type": "json_schema",
      "schema": {
        "type": "object",
        "properties": {
          "category": {"type": "string", "enum": ["billing", "technical", "account", "sales", "other"]},
          "priority": {"type": "string", "enum": ["low", "medium", "high", "urgent"]},
          "escalate": {"type": "boolean"}
        },
        "required": ["category", "priority", "escalate"],
        "additionalProperties": false
      }
    }
  }
}

Converse uses outputConfig.textFormat. In the example, structure.jsonSchema.schema is a string, and the schema is inside that string, along with name and description. An InvokeModel object inside Converse, or a Converse string inside InvokeModel, is not the documented shape.

The first time Bedrock sees a schema, it compiles a grammar. The docs say this can take up to a few minutes. A compiled grammar is cached for 24 hours for the same account and the same schema, encrypted with AWS-managed keys. Unsupported keywords are not compiled. They return 400 immediately.

Keywords outside the subset return 400

“Get validated JSON results from models” describes a subset of JSON Schema Draft 2020-12:

  • Present: object, array, string, integer, number, boolean, null. enum is strings, numbers, booleans, or nulls only. const, anyOf, and allOf (it says “with limitations” and does not list them on this page). Internal $ref, $def, and definitions. String format lists date-time, time, date, duration, email, hostname, uri, ipv4, ipv6, and uuid. Array minItems allows only 0 and 1.
  • Absent: recursive schemas, external $ref, minimum, maximum, multipleOf, minLength, maxLength, and additionalProperties set to anything other than false.

The reference keyword on this page is $def, not the more common 2020-12 keyword $defs. If a local draft uses $defs, do not assume Bedrock accepts it. Try the word this page uses. A failure is a 400, not a formatting error during generation.

The InvokeModel Claude examples set additionalProperties: false. The Converse strict-tool example omits the field. The unsupported list rejects values other than false. This page does not say what omission means. Close it to false locally before you send, so a 400 is not mistaken for the model ignoring the schema.

Citations on Anthropic models also return 400 when combined with structured outputs. The docs say enabling both makes the model return 400.

The classification example’s line “no additional validation is required” means constrained decoding already holds syntax and required fields. It cannot hold ranges outside the subset, because those keywords never enter the request.

strict tools constrain inputs

The final JSON and the tool input are two contracts. The mantle example sets strict: true on get_weather. In input_schema, location is a string, unit is celsius or fahrenheit, and additionalProperties is false. The model returns a tool_use block. The input is input, not the classification object inside text.

InvokeModel strict tools sit in the tools array, and input_schema needs additionalProperties: false. Converse puts them on toolConfig.tools[].toolSpec, with strict: true and the schema as an object in inputSchema.json.

How to check it in JSON Toolbox

The two schemas below are local shapes. The first checks only the format layer: schema must be an object, and additionalProperties on that object must be false. A minimum written on the schema object itself fails. A minimum nested under properties is not caught here; scan for that before you send. The second checks the ticket parsed after end_turn. Neither is an official Bedrock schema.

{
  "format_schema": {
    "type": "object",
    "properties": {
      "type": { "const": "json_schema" },
      "schema": {
        "type": "object",
        "properties": {
          "type": { "const": "object" },
          "additionalProperties": { "const": false }
        },
        "required": ["type", "additionalProperties"],
        "not": { "required": ["minimum"] }
      }
    },
    "required": ["type", "schema"]
  },
  "ticket_schema": {
    "type": "object",
    "properties": {
      "category": { "type": "string", "enum": ["billing", "technical", "account", "sales", "other"] },
      "priority": { "type": "string", "enum": ["low", "medium", "high", "urgent"] },
      "escalate": { "type": "boolean" }
    },
    "required": ["category", "priority", "escalate"],
    "additionalProperties": false
  },
  "ok_format": {
    "type": "json_schema",
    "schema": { "type": "object", "additionalProperties": false }
  },
  "schema_as_string": {
    "type": "json_schema",
    "schema": "{\"type\":\"object\",\"additionalProperties\":false}"
  },
  "ok_ticket": { "category": "technical", "priority": "urgent", "escalate": true },
  "bad_priority": { "category": "technical", "priority": "2", "escalate": true }
}
  1. Paste the four samples into JSON format. All four parse. The value of schema_as_string.schema is a string, not an object.
  2. Use JSON → Schema on ok_ticket, then add enum, required, and additionalProperties: false. Do not put ranges into the schema you send to Bedrock.
  3. In Schema validator, ok_format should pass format_schema. schema_as_string should fail. That string shape is the Converse example, not InvokeModel.
  4. ok_ticket should pass ticket_schema. bad_priority should fail. Tool inputs go to Function Calling. Notes for the final object go to structured output.

The data stays in the browser. First reject a string schema and a priority of "2", then call global.anthropic.claude-haiku-5-5.

FAQ

If stop_reason is end_turn, can you skip validation?

That sentence is about syntax. Ranges outside the subset are not enforced. After end_turn, still check enums and business fields.

Is the first content block the JSON?

Not always. A thinking block can come first. Read the block whose type is text.

If the schema includes minimum, will Bedrock enforce the range?

No. minimum, maximum, minLength, and maxLength return 400. Keep ranges local.

Do Converse and InvokeModel carry the schema as the same JSON?

No. InvokeModel wants an object. The Converse example puts the schema in a string.

Is this the same note as the Haiku 5.5 piece?

No. That one was checked on 2026-10-12. This one is the Haiku 5.5 example in the Bedrock user guide after 2026-10-20.

Summary

As of 2026-10-21, Bedrock structured outputs were announced on 2026-10-20. The Haiku 5.5 classification example uses global.anthropic.claude-haiku-5-5 and puts an object in output_config.format.schema. Read the text block only when stop_reason is end_turn. Do not parse max_tokens. The first block can be thinking. minimum, and additionalProperties set to anything other than false, return 400. The Converse example stores the schema as a string. Next, reject a string schema and an enum miss, then choose runtime or mantle.