CertSafari
    Anthropic Claude Certified Developer – Foundations (CCDV-F)· Lessons

    Domain 6 · Lesson 18/25

    Structured outputs and strict tool use

    Output Handling

    11 min read
    3.67% of exam
    3 sources
    Published 12 Oct 2026
    Docs as of 30 Sep 2026

    What you will be able to do

    • Explain why JSON requested only through the prompt breaks downstream parsers, and how constrained decoding prevents it
    • Send a JSON schema in output_config.format, directly or through client.messages.parse()
    • Enable strict: true on a tool and know which toolsets reject it
    • Pick a fallback when structured outputs can't express the schema you need

    Key concept

    Constrained decoding — Claude's token sampling is limited to output that is valid under a schema you supply. Because the shape is enforced while the output is generated, the result always parses and always has the required fields and types. You don't need to hope the model followed the instructions.

    1.Why JSON requested in the prompt breaks pipelines

    Whatever consumes Claude's output is usually code: a json.loads(), a database insert, a function that expects passengers to be an integer. Code does not tolerate approximations. Ask for JSON in the prompt alone and most responses will parse. Then one arrives with a trailing sentence, a missing key or a number written as a string, and the job fails at 3 a.m. on a record nobody can reproduce.

    Careful prompting lowers how often this happens, but it can't bring the rate to zero. Four kinds of failure keep appearing: parsing errors from invalid JSON syntax, missing required fields, inconsistent data types, and schema violations that you have to catch and retry. A booking tool shows the type problem clearly. It needs passengers: int, and without enforcement Claude might send "two" or "2".

    Structured outputs fix this at generation time. Claude's sampling is restricted so that only schema-valid output can be produced. That makes the result always valid (no more JSON.parse() errors), type safe (required fields and their types are guaranteed), and reliable, because there are no schema violations left to retry. The feature has two parts, and you can use them separately or together in one request. JSON outputs shape Claude's response. Strict tool use shapes the arguments Claude passes to your tools.

    Checkpoint 1 of 7· Check yourself

    A team asks for JSON with a detailed system prompt and a worked example. Their parser still fails now and then. Which explanation fits?

    Sources12

    2.JSON outputs with output_config.format

    There are three steps to a JSON output. Describe the structure you want as a JSON schema, or as a type in your language. Send it in the request's output_config.format with type: "json_schema". Then read the result from the response's text content block. The schema follows JSON Schema, with some limitations. The raw request looks like this:

    A raw JSON schema sent in output_config.format, with the text block parsed afterwardspython
        output_config={
            "format": {
                "type": "json_schema",
                "schema": {
                    "type": "object",
                    "properties": {
                        "name": {"type": "string"},
                        "email": {"type": "string"},
                        "plan_interest": {"type": "string"},
                        "demo_requested": {"type": "boolean"},
                    },
                    "required": ["name", "email", "plan_interest", "demo_requested"],
                    "additionalProperties": False,
                },
            }
        },
    )
    text = next(block.text for block in response.content if block.type == "text")
    contact = json.loads(text)

    Checkpoint 2 of 7· Put it in order

    Put the steps for getting a JSON output in order

    1. 1.Read the JSON from the response's text content block
    2. 2.Send the schema in output_config.format with type: "json_schema"
    3. 3.Define the structure as a JSON schema or as a type in your language

    The recommended route in Python is the SDK helper. Pass a Pydantic model to client.messages.parse() as output_format=. The SDK converts the model to a schema, sends it as output_config.format, validates the response and returns the typed object in parsed_output. output_format is the helper's argument and output_config.format is the request field the helper fills in. They are the same feature at two layers.

    Some JSON Schema constraints can't be expressed in the sent schema, and the helpers deal with that without hiding it. Constraints such as minimum, maximum, minLength and maxLength are removed from the schema Claude receives and written into the field's description instead. The helpers also add additionalProperties: false to every object and filter string formats down to the supported list. A helper that validates responses still checks the result against your original schema in your own code. Take a field with minimum: 100: it goes to Claude as a plain integer with {minimum: 100} in its description, and the response is still validated against minimum: 100. If you build the request yourself, transform_schema() from the anthropic package does the same conversion and returns the schema for you to edit instead of sending it.

    Checkpoint 3 of 7· Check yourself

    Your Pydantic model declares quantity with a minimum of 100, and you call client.messages.parse(). What does Claude's schema contain, and where is the minimum enforced?

    Sources1

    3.Strict tool use: guaranteed tool inputs

    Agents fail in a different place. The risk is not the final answer but the arguments Claude passes to your functions. If a create_booking handler gets "2" where it expected 2, or gets no value for a required field, it throws at runtime partway through a multistep task. Setting strict: true on a tool definition compiles its input_schema into a grammar, using the same pipeline as structured outputs, and limits Claude's sampling to inputs that match it.

    strict is a top-level property of the tool, next to name, description and input_schema. With it on, you get two guarantees. The input in every tool_use block follows your input_schema, and the tool name is always valid: one of the tools you provided, or a server tool. Your handler can drop the validate-and-retry loop for tool arguments.

    Checkpoint 4 of 7· Fill the gap

    Which key turns on schema-guaranteed inputs for this tool?

                "name": "get_weather",
                "description": "Get the current weather in a given location",
                " ? ": True,  # Enable strict mode

    Strict mode has three operational limits. The computer use and browser use toolset entries (computer_toolset_20260801 and browser_toolset_20260801) don't accept strict: true, and a request that sets it on either one is rejected. Compiled tool schemas are cached for up to 24 hours after last use, apart from message content. Strict tool use is HIPAA eligible, but that cache doesn't get the same PHI protections as prompts and responses. Keep PHI out of property names, enum values, const values and pattern regexes.

    The two structured-output features compared
    FeatureWhere you set itWhat it constrainsWhere the result arrives
    JSON outputsoutput_config.format with type: "json_schema"Claude's responseThe response's text content block
    Strict tool usestrict: true on the tool definitionTool names and tool inputsThe input field of the tool_use block

    Checkpoint 5 of 7· Check yourself

    An agent defines a custom search_flights tool and the computer_toolset_20260801 entry, and sets strict: true on both. What happens?

    Sources2

    4.When structured outputs can't be used

    Before giving up on constrained decoding, check whether the obstacle is just an unsupported constraint. A minimum, a maximum or a string length doesn't block structured outputs. transform_schema() or a validating SDK helper moves it into the description and checks it in your code. The cases that do force a fallback are a model where structured outputs aren't available and a schema that needs features the supported subset doesn't cover.

    For those cases, you go back to asking for the format in the prompt. The techniques are taught in [Prompting for output format](lesson:6.2). In short: define the format precisely with JSON, XML or a template, prefill the assistant turn, and constrain with examples. What changes in your pipeline is that the output no longer comes with a guarantee. Every failure mode constrained decoding removed is possible again: syntax errors, missing fields, wrong types. Wrap the parse in error handling, validate against the schema in code, and budget for retries. You already had these steps before structured outputs existed.

    Checkpoint 6 of 7· Check yourself

    A feature runs on a model without structured outputs, so the team switches to a precise JSON template plus an example in the prompt. What should change in the code that consumes the output?

    Checkpoint 7 of 7· Exam question

    A weather tool occasionally fails because an upstream API times out. The integration currently returns a bare tool_result of "error" with is_error: true, and Claude keeps repeating the same failing call in a loop. What change to the tool_result content would most likely stop the repeated failing calls?

    Sources13

    Exam traps

    Each one states something that sounds right. Open it to see what is actually true.

    1. 1.A clear enough prompt with an example makes Claude's JSON reliable enough for an unguarded parser.Why is that wrong?

      Prompting only improves the odds. Malformed JSON, missing fields and wrong types are ruled out only when constrained decoding enforces the schema.

      Covered in Why JSON requested in the prompt breaks pipelines

    2. 2.strict: true can be set on every entry in the tools array, including the computer and browser use toolsets.Why is that wrong?

      Those two toolset entries reject strict: true, and a request that sets it on either one fails.

      Covered in Strict tool use: guaranteed tool inputs

    Sources

    Every claim above is drawn from one of these pages, quoted as it was written on the date shown.

    1. 1.
      “Without structured outputs, Claude can generate malformed JSON responses or invalid tool inputs that break your applications.”
      ↩︎ Why JSON requested in the prompt breaks pipelines
      “You can use these features independently or together in the same request.”
      ↩︎ Why JSON requested in the prompt breaks pipelines
      “The SDK transforms the model's schema, sends it as output_config.format, validates the response, and returns the parsed model in parsed_output.”
      ↩︎ JSON outputs with output_config.format
      “A field with minimum: 100 becomes a plain integer in the sent schema”
      ↩︎ JSON outputs with output_config.format
      “pass the schema through transform_schema() from the anthropic package before sending it”
      ↩︎ When structured outputs can't be used
      “Structured outputs guarantee schema-compliant responses through constrained decoding”
      ↩︎ Key concept
      “Even with careful prompting, you may encounter:”
      ↩︎ Exam trap 1
      “The request carries the schema in output_config.format with type: "json_schema"”
      ↩︎ Checkpoint
      “Claude receives a simplified schema, but a helper that validates responses still enforces every constraint in your code.”
      ↩︎ Checkpoint
      “Schema violations requiring error handling and retries”
      ↩︎ Checkpoint
    2. 2.
      “Without strict mode, Claude might provide passengers: "two" or passengers: "2".”
      ↩︎ Why JSON requested in the prompt breaks pipelines
      “Setting strict: true on a tool definition guarantees Claude's tool inputs match your JSON Schema”
      ↩︎ Strict tool use: guaranteed tool inputs
      “Tool name is always valid (from provided tools or server tools)”
      ↩︎ Strict tool use: guaranteed tool inputs
      “Do not include PHI in input_schema property names, enum values, const values, or pattern regular expressions.”
      ↩︎ Strict tool use: guaranteed tool inputs
      “a request that sets it on either entry is rejected”
      ↩︎ Exam trap 2
      “The computer use and browser use toolset entries (computer_toolset_20260801 and browser_toolset_20260801) don't accept strict: true”
      ↩︎ Checkpoint
    3. 3.
      “Precisely define your desired output format using JSON, XML, or custom templates”
      ↩︎ When structured outputs can't be used

    Continue to page 2 of 2

    Validating Claude responses before you use them

    Spotted a mistake, or was something unclear? Tell us.