---
title: Strukturierte Ausgaben
url: https://platform.claude.com/docs/de/build-with-claude/structured-outputs
description: Erhalte validierte JSON-Ergebnisse aus Agent-Workflows
featureMetadata:
  status: ga
  zdr:
    eligibility: eligible
    note: Excludes [Covered Models](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention#model-specific-data-retention-requirements).
  supportedModels:
    - claude-fable-5-1
    - claude-mythos-5-1
    - claude-fable-5
    - claude-mythos-5
    - claude-mythos-preview
    - claude-opus-5-5
    - claude-opus-5
    - claude-opus-4-8
    - claude-opus-4-7
    - claude-opus-4-6
    - claude-sonnet-5-5
    - claude-sonnet-5
    - claude-sonnet-4-6
    - claude-sonnet-4-5-20250929
    - claude-opus-4-5-20251101
    - claude-haiku-5-5
    - claude-haiku-4-5-20251001
  supportedPlatforms:
    Claude API: ga
    Claude Platform on AWS: ga
    Amazon Bedrock:
      availability: ga
      note: Auf Amazon Bedrock sind strukturierte Ausgaben über die veraltete Integration [Amazon Bedrock (Opus 4.6 und früher)](https://platform.claude.com/docs/de/build-with-claude/claude-on-amazon-bedrock-legacy) für Claude Opus 4.6, Claude Sonnet 4.6, Claude Sonnet 4.5, Claude Opus 4.5 und Claude Haiku 4.5 verfügbar, nicht jedoch über [Claude in Amazon Bedrock](https://platform.claude.com/docs/de/build-with-claude/claude-in-amazon-bedrock).
    Google Cloud: ga
    Microsoft Foundry: ga
---

„Structured outputs“ (strukturierte Ausgaben) beschränken Claudes Antworten darauf, einem bestimmten Schema zu folgen, und stellen so gültige, parsbare Ausgaben für die nachgelagerte Verarbeitung sicher. Strukturierte Ausgaben bieten zwei sich ergänzende Funktionen:

* **JSON-Ausgaben** (`output_config.format`): Erhalte Claudes Antwort in einem bestimmten JSON-Format, zum Beispiel um Daten aus Bildern oder Text zu extrahieren, strukturierte Berichte zu erstellen oder API-Antworten zu formatieren. Diese Seite behandelt JSON-Ausgaben.
* **„Strict tool use“ (strikte Tool-Nutzung)** (`strict: true`): Garantiere die Schema-Validierung von Tool-Namen und -Eingaben. Siehe [Strikte Tool-Nutzung](https://platform.claude.com/docs/de/agents-and-tools/tool-use/strict-tool-use).

Du kannst diese Funktionen unabhängig voneinander oder [zusammen in derselben Anfrage](https://platform.claude.com/docs/de/build-with-claude/structured-outputs#using-both-features-together) verwenden.

## Warum strukturierte Ausgaben verwenden

Ohne strukturierte Ausgaben kann Claude fehlerhafte JSON-Antworten oder ungültige Tool-Eingaben generieren, die deine Anwendungen zum Absturz bringen. Selbst bei sorgfältigem Prompting kannst du auf Folgendes stoßen:

* Parsing-Fehler durch ungültige JSON-Syntax
* Fehlende Pflichtfelder
* Inkonsistente Datentypen
* Schema-Verletzungen, die Fehlerbehandlung und Wiederholungsversuche erfordern

Strukturierte Ausgaben garantieren schemakonforme Antworten durch „constrained decoding“ (eingeschränkte Dekodierung):

* **Immer gültig:** Keine `JSON.parse()`-Fehler mehr
* **Typsicher:** Garantierte Feldtypen und Pflichtfelder
* **Zuverlässig:** Keine Wiederholungsversuche bei Schema-Verletzungen nötig

## Funktionsweise

<Steps>
  <Step title="Definiere dein Schema">
    Beschreibe die gewünschte Struktur als JSON-Schema oder als Typ in deiner Sprache. Das Schema folgt JSON Schema, mit einigen [Einschränkungen](https://platform.claude.com/docs/de/build-with-claude/structured-outputs#json-schema-limitations).
  </Step>

  <Step title="Sende es in output_config.format">
    Die Anfrage enthält das Schema in `output_config.format` mit `type: "json_schema"`. SDK-Helfer setzen dies für dich.
  </Step>

  <Step title="Lies die Antwort">
    Claude gibt gültiges JSON, das deinem Schema entspricht, im Text-Content-Block der Antwort zurück. SDK-Helfer parsen es in deinen Typ.
  </Step>
</Steps>

## Verwendung

<Tabs>
  <Tab title="cURL">
    ```bash
    curl https://api.anthropic.com/v1/messages \
      -H "content-type: application/json" \
      -H "x-api-key: $ANTHROPIC_API_KEY" \
      -H "anthropic-version: 2023-06-01" \
      -d '{
        "model": "claude-opus-5-5",
        "max_tokens": 1024,
        "messages": [
          {
            "role": "user",
            "content": "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."
          }
        ],
        "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
            }
          }
        }
      }'
    ```

    Claude gibt JSON wie dieses im Text-Content-Block der Antwort zurück:

    ```json Output
    {
      "name": "John Smith",
      "email": "john@example.com",
      "plan_interest": "Enterprise",
      "demo_requested": true
    }
    ```
  </Tab>

  <Tab title="CLI">
    ```bash
    ant messages create \
      --transform 'content.#(type=="text").text|@fromstr' \
      --format jsonl <<'YAML'
    model: claude-opus-5-5
    max_tokens: 1024
    messages:
      - role: user
        content: >-
          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.
    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
    YAML
    ```

    Um nur einige Properties der JSON-Ausgabe auszugeben, übergib einen [GJSON-Pfad](https://platform.claude.com/docs/de/cli-sdks-libraries/cli/using#transform-output-with-gjson) an `--transform`.

    Das obige Beispiel gibt Folgendes aus:

    ```text Output wrap
    {"name":"John Smith","email":"john@example.com","plan_interest":"Enterprise","demo_requested":true}
    ```
  </Tab>

  <Tab title="Python">
    ```python
    from pydantic import BaseModel
    # ...


    class ContactInfo(BaseModel):
        name: str
        email: str
        plan_interest: str
        demo_requested: bool


    client = Anthropic()

    response = client.messages.parse(
        model="claude-opus-5-5",
        max_tokens=1024,
        messages=[
            {
                "role": "user",
                "content": (
                    "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."
                ),
            }
        ],
        output_format=ContactInfo,
    )

    print(response.parsed_output)
    ```

    Übergib ein [Pydantic](https://docs.pydantic.dev/)-Modell als `output_format` an `client.messages.parse()`, die empfohlene Methode. Das SDK transformiert das Schema des Modells, sendet es als `output_config.format`, validiert die Antwort und gibt das geparste Modell in `parsed_output` zurück.

    Das obige Beispiel gibt Folgendes aus:

    ```text Output wrap
    name='John Smith' email='john@example.com' plan_interest='Enterprise' demo_requested=True
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript
    import { z } from "zod";
    import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";

    const ContactInfoSchema = z.object({
      name: z.string(),
      email: z.string(),
      plan_interest: z.string(),
      demo_requested: z.boolean()
    });

    const client = new Anthropic();

    const response = await client.messages.parse({
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages: [
        {
          role: "user",
          content:
            "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."
        }
      ],
      output_config: { format: zodOutputFormat(ContactInfoSchema) }
    });

    // Automatisch geparst und validiert
    console.log(response.parsed_output);
    ```

    Umschließe ein [Zod](https://zod.dev/)-Schema mit `zodOutputFormat()` und übergib es als `output_config.format` an `client.messages.parse()`. `zodOutputFormat()` transformiert das Schema, und `parse()` validiert die Antwort und gibt das geparste Ergebnis in `parsed_output` zurück, typisiert passend zum Schema.

    Das obige Beispiel gibt Folgendes aus:

    ```javascript Output
    {
      name: 'John Smith',
      email: 'john@example.com',
      plan_interest: 'Enterprise',
      demo_requested: true
    }
    ```
  </Tab>

  <Tab title="C#">
    ```csharp
    using Anthropic;
    using Anthropic.Models.Messages;
    using Anthropic.Services;

    var client = new AnthropicClient();

    var response = await client.Messages.Create<ContactInfo>(new MessageCreateParams
    {
        Model = Model.ClaudeOpus5_5,
        MaxTokens = 1024,
        Messages = [new() {
            Role = Role.User,
            Content = "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."
        }],
    });

    if (response.Content.Select(block => block.Parsed()).OfType<ContactInfo>().FirstOrDefault() is { } contact)
    {
        Console.WriteLine(contact);
    }

    public record ContactInfo
    {
        public string Name { get; set; } = "";
        public string Email { get; set; } = "";
        public string PlanInterest { get; set; } = "";
        public bool DemoRequested { get; set; }
    }
    ```

    Übergib eine einfache C#-Klasse oder einen Record an die generische Überladung `Create<T>()`. Das SDK leitet aus dem Typ ein JSON-Schema ab, transformiert es und parst jeden Textblock zurück in diesen Typ.

    Das obige Beispiel gibt Folgendes aus:

    ```text Output wrap
    ContactInfo { Name = John Smith, Email = john@example.com, PlanInterest = Enterprise, DemoRequested = True }
    ```
  </Tab>

  <Tab title="Go">
    ```go
    type ContactInfo struct {
    	Name          string `json:"name"`
    	Email         string `json:"email"`
    	PlanInterest  string `json:"plan_interest"`
    	DemoRequested bool   `json:"demo_requested"`
    }

    func main() {
    	client := anthropic.NewClient()

    	var contact ContactInfo
    	_, err := client.Beta.Messages.New(context.Background(), anthropic.BetaMessageNewParams{
    		Model:     anthropic.ModelClaudeOpus5_5,
    		MaxTokens: 1024,
    		Messages: []anthropic.BetaMessageParam{
    			anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock(
    				"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.",
    			)),
    		},
    		OutputConfig: anthropic.BetaOutputConfigParam{
    			Format: anthropic.BetaJSONOutputFormatParam{Schema: &contact},
    		},
    	})
    	if err != nil {
    		panic(err)
    	}

    	fmt.Printf("%#v\n", contact)
    }
    ```

    <Note>
      Das Übergeben eines Structs als Schema befindet sich in Go in der Beta, daher verwendet dieses Beispiel `client.Beta.Messages.New`. Um das GA-`client.Messages.New` zu verwenden, übergib ein JSON-Schema wie unter [Ein rohes JSON-Schema verwenden](https://platform.claude.com/docs/de/build-with-claude/structured-outputs#using-a-raw-json-schema) gezeigt.
    </Note>

    Das SDK generiert und transformiert das JSON-Schema aus dem Struct und deserialisiert die Antwort in dieses.

    Das obige Beispiel gibt Folgendes aus:

    ```text Output wrap
    main.ContactInfo{Name:"John Smith", Email:"john@example.com", PlanInterest:"Enterprise", DemoRequested:true}
    ```
  </Tab>

  <Tab title="Java">
    ```java
    static class ContactInfo {
        public String name;
        public String email;
        public String plan_interest;
        public boolean demo_requested;
    }

    void main() throws Exception {
        AnthropicClient client = AnthropicOkHttpClient.fromEnv();

        StructuredMessageCreateParams<ContactInfo> params = MessageCreateParams.builder()
            .model(Model.CLAUDE_OPUS_5_5)
            .maxTokens(1024)
            .addUserMessage("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.")
            .outputConfig(ContactInfo.class)
            .build();

        StructuredMessage<ContactInfo> response = client.messages().create(params);
        ContactInfo contact = response.content().stream()
            .flatMap(block -> block.text().stream())
            .findFirst().orElseThrow().text();
        IO.println(new ObjectMapper().writeValueAsString(contact));
    }
    ```

    Wenn du eine Java-Klasse an `outputConfig()` übergibst, leitet das SDK daraus ein JSON-Schema ab und validiert das Schema. Der Builder erzeugt dann ein `StructuredMessageCreateParams<T>`. Anstatt das Schema zu transformieren, lehnt die lokale Validierung des SDK [von der API nicht unterstützte Constraints](https://platform.claude.com/docs/de/build-with-claude/structured-outputs#json-schema-limitations) ab. Lies das geparste Ergebnis mit `response.content().stream().flatMap(block -> block.text().stream()).findFirst().orElseThrow().text()`.

    Das obige Beispiel gibt Folgendes aus:

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

    <Note>
      Deklariere deine Schema-Klassen als Top-Level-Klassen oder als `static` verschachtelte Klassen. Diese Anforderung stammt aus der Jackson-Databind-Bibliothek (`com.fasterxml.jackson.databind`), die das SDK verwendet, um JSON-Antworten in deine Klasseninstanzen zu deserialisieren, und die keine nicht-statischen inneren Klassen instanziieren kann.
    </Note>

    <Accordion title="Generische Typlöschung">
      Java behält generische Typinformationen für Felder in den Metadaten der Klasse bei, aber in anderen Gültigkeitsbereichen gilt die generische Typlöschung (Type Erasure). Während ein JSON-Schema aus einem Feld `BookList.books` mit dem Typ `List<Book>` abgeleitet werden kann, kann aus einer lokalen Variable desselben Typs kein gültiges JSON-Schema abgeleitet werden.

      Wenn beim Konvertieren einer JSON-Antwort in eine Java-Klasseninstanz ein Fehler auftritt, enthält die Fehlermeldung die JSON-Antwort zur Unterstützung der Diagnose. Wenn deine JSON-Antwort sensible Informationen enthalten könnte, vermeide es, sie direkt zu protokollieren, oder stelle sicher, dass du alle sensiblen Details aus der Fehlermeldung entfernst.
    </Accordion>

    <Accordion title="Lokale Schema-Validierung">
      Strukturierte Ausgaben unterstützen eine [Teilmenge der JSON-Schema-Sprache](https://platform.claude.com/docs/de/build-with-claude/structured-outputs#json-schema-limitations). Das SDK generiert Schemas automatisch aus Klassen, um dieser Teilmenge zu entsprechen. Die Methode `outputConfig(Class<T>)` führt eine Validierungsprüfung des aus der angegebenen Klasse abgeleiteten Schemas durch.

      Wichtige Punkte:

      * **Lokale Validierung** erfolgt, ohne Anfragen an das entfernte KI-Modell zu senden.
      * **Entfernte Validierung** wird ebenfalls vom KI-Modell beim Empfang des JSON-Schemas durchgeführt.
      * **Versionskompatibilität:** Die lokale Validierung kann fehlschlagen, während die entfernte Validierung erfolgreich ist, wenn die SDK-Version veraltet ist.
      * **Lokale Validierung deaktivieren:** Übergib `JsonSchemaLocalValidation.NO`, wenn du auf Kompatibilitätsprobleme stößt:

      ```java
      import com.anthropic.core.JsonSchemaLocalValidation;
      // ...

      static class BookList {
          public List<String> books;
      }

      void main() {
          StructuredMessageCreateParams<BookList> createParams = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(2048)
              .outputConfig(BookList.class, JsonSchemaLocalValidation.NO)
              .addUserMessage("List some famous late twentieth century novels.")
              .build();
      }
      ```
    </Accordion>

    <Accordion title="Streaming">
      Strukturierte Ausgaben funktionieren auch mit Streaming. Da Antworten in Stream-Events eintreffen, musst du die vollständige Antwort sammeln, bevor du das JSON deserialisierst.

      Verwende `MessageAccumulator`, um die JSON-Strings aus dem Stream zu sammeln. Sobald sie gesammelt sind, rufe `MessageAccumulator.message(Class<T>)` auf, um die gesammelte `Message` in eine `StructuredMessage` zu konvertieren, die das JSON automatisch in deine Java-Klasse deserialisiert.
    </Accordion>

    <Accordion title="JSON-Schema-Properties">
      Wenn das SDK ein JSON-Schema aus deinen Java-Klassen ableitet, schließt es standardmäßig alle Properties ein, die durch `public`-Felder oder `public`-Getter-Methoden repräsentiert werden, und schließt nicht-`public`-Felder und Getter-Methoden aus.

      Du kannst die Sichtbarkeit mit Annotationen steuern:

      * `@JsonIgnore` schließt ein `public`-Feld oder eine Getter-Methode aus
      * `@JsonProperty` schließt ein nicht-`public`-Feld oder eine Getter-Methode ein

      Wenn du `private`-Felder mit `public`-Getter-Methoden definierst, leitet das SDK den Property-Namen vom Getter ab (zum Beispiel erzeugt das `private`-Feld `myValue` mit der `public`-Methode `getMyValue()` eine Property `"myValue"`). Um einen unkonventionellen Getter-Namen zu verwenden, annotiere die Methode mit `@JsonProperty`.

      Jede Klasse muss mindestens eine Property für das JSON-Schema definieren. Ein Validierungsfehler tritt auf, wenn keine Felder oder Getter-Methoden Schema-Properties erzeugen können, etwa wenn:

      * Es keine Felder oder Getter-Methoden in der Klasse gibt
      * Alle `public`-Member mit `@JsonIgnore` annotiert sind
      * Allen nicht-`public`-Membern `@JsonProperty`-Annotationen fehlen
      * Ein Feld einen `Map`-Typ verwendet, der ein leeres `"properties"`-Feld erzeugt
    </Accordion>

    <Accordion title="Komposition und Vererbung">
      Deine Java-Klassen können Komposition und Vererbung verwenden, um beim Definieren von JSON-Schemas Struktur zu teilen. Jedes Muster wirkt sich unterschiedlich auf die Ausgabestruktur aus.

      **Komposition** erzeugt verschachtelte JSON-Ausgaben. Ableitung eines Schemas aus der Klasse `Composed`, die `A` und `B` komponiert:

      ```java
      static class A {
          public String a;
      }

      static class B {
          public String b;
      }

      static class Composed {
          public A composedA;
          public B composedB;
      }
      ```

      Die JSON-Ausgabe hat diese verschachtelte Struktur:

      ```json
      {
        "composedA": { "a": "hello" },
        "composedB": { "b": "world" }
      }
      ```

      **Vererbung** erzeugt flache JSON-Ausgaben. Ableitung eines Schemas aus der Klasse `Derived`, die `Base` erweitert:

      ```java
      static class Base {
          public String a;
      }

      static class Derived extends Base {
          public String b;
      }
      ```

      Die JSON-Ausgabe hat diese flache Struktur:

      ```json
      {
        "a": "hello",
        "b": "world"
      }
      ```
    </Accordion>

    <Accordion title="Annotationen (Jackson und Swagger)">
      Du kannst Jackson-Databind-Annotationen verwenden, um das aus deinen Java-Klassen abgeleitete JSON-Schema anzureichern:

      ```java
      import com.fasterxml.jackson.annotation.JsonClassDescription;
      import com.fasterxml.jackson.annotation.JsonIgnore;
      import com.fasterxml.jackson.annotation.JsonPropertyDescription;

      static class Person {

        @JsonPropertyDescription("The first name and surname of the person")
        public String name;

        public int birthYear;

        @JsonPropertyDescription("The year the person died, or 'present' if the person is living.")
        public String deathYear;
      }

      @JsonClassDescription("The details of one published book")
      static class Book {

        public String title;
        public Person author;

        @JsonPropertyDescription("The year in which the book was first published.")
        public int publicationYear;

        @JsonIgnore
        public String genre;
      }

      static class BookList {
        public List<Book> books;
      }
      ```

      Zusammenfassung der Annotationen:

      * `@JsonClassDescription`: Fügt einer Klasse eine Beschreibung hinzu
      * `@JsonPropertyDescription`: Fügt einem Feld oder einer Getter-Methode eine Beschreibung hinzu
      * `@JsonIgnore`: Schließt ein `public`-Feld oder einen Getter aus dem Schema aus
      * `@JsonProperty`: Schließt ein nicht-`public`-Feld oder einen Getter in das Schema ein

      Wenn du `@JsonProperty(required = false)` verwendest, ignoriert das SDK den Wert `false`. Aus Klassen abgeleitete Schemas markieren immer alle Properties als erforderlich.

      Du kannst auch Swagger Core (OpenAPI 3) `@Schema`- und `@ArraySchema`-Annotationen für typspezifische Constraints verwenden:

      ```java
      import io.swagger.v3.oas.annotations.media.ArraySchema;
      import io.swagger.v3.oas.annotations.media.Schema;

      static class Article {

        @ArraySchema(minItems = 1)
        public List<String> authors;

        public String title;

        @Schema(format = "date")
        public String publicationDate;

        public int pageCount;
      }
      ```

      Die lokale Validierung prüft, dass du keine nicht unterstützten Constraint-Schlüsselwörter verwendet hast, aber Constraint-Werte werden nicht lokal validiert. Zum Beispiel kann ein nicht unterstützter `"format"`-Wert die lokale Validierung bestehen, aber einen entfernten Fehler verursachen.

      Wenn du sowohl Jackson- als auch Swagger-Annotationen verwendest, um dasselbe Schema-Feld zu setzen, hat die Jackson-Annotation Vorrang.
    </Accordion>
  </Tab>

  <Tab title="PHP">
    ```php
    use Anthropic\Lib\Concerns\StructuredOutputModelTrait;
    use Anthropic\Lib\Contracts\StructuredOutputModel;

    $client = new Client();

    class ContactInfo implements StructuredOutputModel
    {
        use StructuredOutputModelTrait;

        public string $name;
        public string $email;
        public string $plan_interest;
        public bool $demo_requested;
    }

    $message = $client->messages->create(
        maxTokens: 1024,
        messages: [
            [
                'role' => 'user',
                'content' => '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.',
            ],
        ],
        model: 'claude-opus-5-5',
        outputConfig: ['format' => ContactInfo::class],
    );

    $contact = $message->parsedOutput();
    if ($contact instanceof ContactInfo) {
        var_dump($contact);
    }
    ```

    Definiere eine Klasse, die `StructuredOutputModel` implementiert und `StructuredOutputModelTrait` verwendet, und übergib ihren Namen in `outputConfig: ['format' => MyClass::class]`. Das SDK leitet aus den PHP-8-Property-Typen der Klasse ein JSON-Schema ab, transformiert es und gibt eine typisierte Instanz über `$message->parsedOutput()` zurück.

    `parsedOutput()` gibt bei Erfolg deine Modellinstanz zurück oder `null` (oder ein Fehler-Array), wenn das Parsen fehlschlägt. Verwende `instanceof`, um den Typ einzugrenzen, bevor du auf Felder zugreifst.

    Das obige Beispiel gibt Folgendes aus:

    ```text Output wrap
    object(ContactInfo)#42 (4) {
      ["name"]=>
      string(10) "John Smith"
      ["email"]=>
      string(16) "john@example.com"
      ["plan_interest"]=>
      string(10) "Enterprise"
      ["demo_requested"]=>
      bool(true)
    }
    ```

    <Accordion title="Typinferenz">
      Das SDK bildet native PHP-8-Property-Typen auf JSON Schema ab:

      | PHP-Typ                                           | JSON Schema                         |
      | ------------------------------------------------- | ----------------------------------- |
      | `string`                                          | `"string"`                          |
      | `int`                                             | `"integer"`                         |
      | `float`                                           | `"number"`                          |
      | `bool`                                            | `"boolean"`                         |
      | `array`                                           | `"array"` (siehe folgenden Hinweis) |
      | `?type` (nullable)                                | Optionales Feld                     |
      | Klasse, die `StructuredOutputModel` implementiert | Verschachteltes Objekt              |

      Für `array`-Properties fügt das SDK nur dann ein `items`-Schema hinzu, wenn der Elementtyp ein verschachteltes `StructuredOutputModel` ist, deklariert mit `#[Constrained(itemClass: MyModel::class)]` oder einem `/** @var MyModel[] */`-Docblock. Arrays von Skalaren (`string[]`, `int[]`) erzeugen ein uneingeschränktes `{"type":"array"}`.

      Alle nicht-nullbaren Properties werden zu Pflichtfeldern.
    </Accordion>

    <Accordion title="Constraints mit dem Attribut #[Constrained]">
      Füge Constraints mit dem Attribut `#[Constrained]` hinzu:

      ```php
      use Anthropic\Lib\Attributes\Constrained;
      use Anthropic\Lib\Concerns\StructuredOutputModelTrait;
      use Anthropic\Lib\Contracts\StructuredOutputModel;

      class Address implements StructuredOutputModel { use StructuredOutputModelTrait; public string $street; }

      class Profile implements StructuredOutputModel
      {
          use StructuredOutputModelTrait;

          #[Constrained(description: 'Age in years', minimum: 0, maximum: 150)]
          public int $age;

          #[Constrained(format: 'email')]
          public string $email;

          #[Constrained(itemClass: Address::class, minItems: 1)]
          public array $addresses;
      }
      ```

      **Von der API durchgesetzte Constraints** (im Schema gesendet): `description`, `format`, `const`, `itemClass`, `minItems` (nur 0 oder 1).

      **Vom SDK validierte Constraints** (aus dem übertragenen Schema entfernt, an die Beschreibung angehängt und gegen die Antwort validiert): `minimum`, `maximum`, `multipleOf`, `minLength`, `maxLength`.
    </Accordion>
  </Tab>

  <Tab title="Ruby">
    ```ruby
    client = Anthropic::Client.new

    class ContactInfo < Anthropic::BaseModel
      required :name, String
      required :email, String
      required :plan_interest, String
      required :demo_requested, Anthropic::Boolean
    end

    message = client.messages.create(
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages: [{
        role: "user",
        content: "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."
      }],
      output_config: {format: ContactInfo}
    )

    contact = message.parsed_output
    puts contact
    ```

    Definiere eine Klasse, die `Anthropic::BaseModel` erweitert, und übergib sie als `output_config: {format: Model}` an `messages.create()`. Das SDK leitet aus der Klasse ein JSON-Schema ab, transformiert es und weist das geparste Ergebnis als typisiertes Ruby-Objekt dem Attribut `parsed_output` der Antwort zu.

    Das obige Beispiel gibt Folgendes aus:

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

    <Accordion title="Erweiterte Modellfunktionen">
      Das Ruby SDK unterstützt zusätzliche Funktionen zur Modelldefinition für reichhaltigere Schemas:

      * **Schlüsselwort `doc:`:** Füge Feldern Beschreibungen hinzu, um eine informativere Schema-Ausgabe zu erhalten
      * **`Anthropic::ArrayOf[T]`:** Typisierte Arrays. Übergib Constraints auf Array-Ebene (`min_items:`, `max_items:`) als Schlüsselwörter an `required`/`optional`, nicht an `ArrayOf` selbst
      * **`Anthropic::EnumOf[:a, :b]`:** Enum-Felder mit eingeschränkten Werten
      * **`Anthropic::UnionOf[T1, T2]`:** Union-Typen, die auf `anyOf` abgebildet werden

      ```ruby
      class FamousNumber < Anthropic::BaseModel
        required :value, Float
        optional :reason, String, doc: "why is this number mathematically significant?"
      end

      class Output < Anthropic::BaseModel
        required :numbers, Anthropic::ArrayOf[FamousNumber], min_items: 3, max_items: 5
      end

      message = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 1024,
        messages: [{role: "user", content: "give me some famous numbers"}],
        output_config: {format: Output}
      )

      message.parsed_output
      # => #<Output numbers=[#<FamousNumber value=3.14159... reason="Pi ist...">...]>
      ```
    </Accordion>
  </Tab>
</Tabs>

## Wie die SDK-Transformation funktioniert

Die meisten SDK-Helfer transformieren Schemas, die nicht unterstützte Funktionen verwenden. Die Transformationsschritte:

1. **Nicht unterstützte Constraints entfernen** (zum Beispiel `minimum`, `maximum`, `minLength`, `maxLength`)
2. **Beschreibungen aktualisieren**, indem jeder nicht unterstützte Constraint zur Beschreibung des Feldes hinzugefügt wird (zum Beispiel `{minimum: 100}`)
3. **`additionalProperties: false` hinzufügen** zu allen Objekten
4. **String-Formate filtern**, sodass nur die unterstützte Liste übrig bleibt
5. **Antworten validieren** gegen dein ursprüngliches Schema und alle seine Constraints, sofern der Helfer Antworten validiert

Claude erhält ein vereinfachtes Schema, aber ein Helfer, der Antworten validiert, setzt in deinem Code weiterhin jeden Constraint durch.

**Beispiel:** Ein Feld mit `minimum: 100` wird im gesendeten Schema zu einem einfachen Integer, und das SDK fügt `{minimum: 100}` zur Beschreibung des Feldes hinzu. Ein Helfer, der Antworten validiert, prüft die Antwort weiterhin gegen `minimum: 100`.

## Ein rohes JSON-Schema verwenden

Um ein JSON-Schema aus einer Datei, einer OpenAPI-Spezifikation oder aus Code zu verwenden, der es zur Laufzeit erstellt, übergib es in `output_config.format`.

<Tabs>
  <Tab title="cURL">
    ```bash
    curl https://api.anthropic.com/v1/messages \
      -H "content-type: application/json" \
      -H "x-api-key: $ANTHROPIC_API_KEY" \
      -H "anthropic-version: 2023-06-01" \
      -d '{
        "model": "claude-opus-5-5",
        "max_tokens": 1024,
        "messages": [
          {
            "role": "user",
            "content": "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."
          }
        ],
        "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
            }
          }
        }
      }'
    ```

    Claude gibt JSON wie dieses im Text-Content-Block der Antwort zurück:

    ```json Output
    {
      "name": "John Smith",
      "email": "john@example.com",
      "plan_interest": "Enterprise",
      "demo_requested": true
    }
    ```
  </Tab>

  <Tab title="CLI">
    ```bash
    ant messages create \
      --transform 'content.#(type=="text").text|@fromstr' \
      --format jsonl <<'YAML'
    model: claude-opus-5-5
    max_tokens: 1024
    messages:
      - role: user
        content: >-
          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.
    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
    YAML
    ```

    Das obige Beispiel gibt Folgendes aus:

    ```text Output wrap
    {"name":"John Smith","email":"john@example.com","plan_interest":"Enterprise","demo_requested":true}
    ```
  </Tab>

  <Tab title="Python">
    ```python
    client = anthropic.Anthropic()

    response = client.messages.create(
        model="claude-opus-5-5",
        max_tokens=1024,
        messages=[
            {
                "role": "user",
                "content": (
                    "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."
                ),
            }
        ],
        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)
    print(contact)
    ```

    Das obige Beispiel gibt Folgendes aus:

    ```text Output wrap
    {'name': 'John Smith', 'email': 'john@example.com', 'plan_interest': 'Enterprise', 'demo_requested': True}
    ```

    Um [von der API nicht unterstützte Constraints](https://platform.claude.com/docs/de/build-with-claude/structured-outputs#json-schema-limitations) in Feldbeschreibungen zu verschieben, leite das Schema vor dem Senden durch `transform_schema()` aus dem Paket `anthropic` und bearbeite das Ergebnis bei Bedarf. `transform_schema()` akzeptiert auch ein Pydantic-Modell. Anders als `client.messages.parse()` gibt es das transformierte Schema zurück, anstatt es zu senden.
  </Tab>

  <Tab title="TypeScript">
    ```typescript
    import { jsonSchemaOutputFormat } from "@anthropic-ai/sdk/helpers/json-schema";

    const client = new Anthropic();

    const response = await client.messages.parse({
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages: [
        {
          role: "user",
          content: "Extract contact info: John Smith, john@example.com, interested in the Pro plan"
        }
      ],
      output_config: {
        format: jsonSchemaOutputFormat({
          type: "object",
          properties: {
            name: { type: "string" },
            email: { type: "string" },
            planInterest: { type: "string" }
          },
          required: ["name", "email", "planInterest"],
          additionalProperties: false
        } as const)
      }
    });

    // response.parsed_output ist typisiert als { name: string; email: string; planInterest: string } | null
    console.log(response.parsed_output);
    ```

    Verwende `jsonSchemaOutputFormat()`, um ein einfaches JSON-Schema an `parse()` zu übergeben, ohne Zod zu installieren. Die API gibt eine Antwort zurück, die dem Schema entspricht, und wenn du das Schema mit `as const` deklarierst, wird der Typ für `parsed_output` von TypeScript automatisch entsprechend deinem Schema abgeleitet. Bei einem importierten oder generierten Schema ist `parsed_output` als `unknown` typisiert.

    Standardmäßig [transformiert der Helfer das Schema](https://platform.claude.com/docs/de/build-with-claude/structured-outputs#how-sdk-transformation-works) auf dieselbe Weise wie `zodOutputFormat()`. Übergib `{ transform: false }` als zweites Argument, um es unverändert zu senden. Anders als `zodOutputFormat()` validiert er die Antwort nicht, sodass er Verletzungen von [von der API nicht unterstützten Constraints](https://platform.claude.com/docs/de/build-with-claude/structured-outputs#json-schema-limitations) wie `minimum` nicht erkennt.

    Das obige Beispiel gibt Folgendes aus:

    ```javascript Output
    { name: 'John Smith', email: 'john@example.com', planInterest: 'Pro' }
    ```
  </Tab>

  <Tab title="C#">
    ```csharp
    using System.Text.Json;
    using Anthropic;
    using Anthropic.Models.Messages;

    var client = new AnthropicClient();

    var response = await client.Messages.Create(new MessageCreateParams
    {
        Model = Model.ClaudeOpus5_5,
        MaxTokens = 1024,
        Messages = [new() {
            Role = Role.User,
            Content = "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."
        }],
        OutputConfig = new OutputConfig
        {
            Format = new JsonOutputFormat
            {
                Schema = new Dictionary<string, JsonElement>
                {
                    ["type"] = JsonSerializer.SerializeToElement("object"),
                    ["properties"] = JsonSerializer.SerializeToElement(new
                    {
                        name = new { type = "string" },
                        email = new { type = "string" },
                        plan_interest = new { type = "string" },
                        demo_requested = new { type = "boolean" },
                    }),
                    ["required"] = JsonSerializer.SerializeToElement(
                        new[] { "name", "email", "plan_interest", "demo_requested" }),
                    ["additionalProperties"] = JsonSerializer.SerializeToElement(false),
                },
            },
        },
    });

    if (response.Content.Select(b => b.Value).OfType<TextBlock>().FirstOrDefault() is { } textBlock)
    {
        // Das JSON entspricht garantiert dem Schema
        var contact = JsonSerializer.Deserialize<JsonElement>(textBlock.Text);
        Console.WriteLine(contact);
    }
    ```

    Das obige Beispiel gibt Folgendes aus:

    ```text Output wrap
    {"name":"John Smith","email":"john@example.com","plan_interest":"Enterprise","demo_requested":true}
    ```
  </Tab>

  <Tab title="Go">
    ```go
    type ContactInfo struct {
    	Name          string `json:"name"`
    	Email         string `json:"email"`
    	PlanInterest  string `json:"plan_interest"`
    	DemoRequested bool   `json:"demo_requested"`
    }

    func main() {
    	client := anthropic.NewClient()

    	message, _ := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
    		Model:     anthropic.ModelClaudeOpus5_5,
    		MaxTokens: 1024,
    		Messages: []anthropic.MessageParam{
    			anthropic.NewUserMessage(anthropic.NewTextBlock(
    				"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.",
    			)),
    		},
    		OutputConfig: anthropic.OutputConfigParam{
    			Format: anthropic.JSONOutputFormatParam{
    				Schema: map[string]any{
    					"type": "object",
    					"properties": map[string]any{
    						"name":           map[string]string{"type": "string"},
    						"email":          map[string]string{"type": "string"},
    						"plan_interest":  map[string]string{"type": "string"},
    						"demo_requested": map[string]string{"type": "boolean"},
    					},
    					"required":             []string{"name", "email", "plan_interest", "demo_requested"},
    					"additionalProperties": false,
    				},
    			},
    		},
    	})

    	for _, block := range message.Content {
    		switch variant := block.AsAny().(type) {
    		case anthropic.TextBlock:
    			var contact ContactInfo
    			json.Unmarshal([]byte(variant.Text), &contact)
    			fmt.Printf("%#v\n", contact)
    		}
    	}
    }
    ```

    Das obige Beispiel gibt Folgendes aus:

    ```text Output wrap
    main.ContactInfo{Name:"John Smith", Email:"john@example.com", PlanInterest:"Enterprise", DemoRequested:true}
    ```

    Damit das SDK ein Map-Schema transformiert, leite es über die Beta-API durch `BetaJSONSchemaOutputFormat()`.
  </Tab>

  <Tab title="Java">
    ```java
    import com.anthropic.core.JsonValue;
    import com.anthropic.models.messages.JsonOutputFormat;
    // ...
    import com.anthropic.models.messages.OutputConfig;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;

    void main() throws Exception {
        AnthropicClient client = AnthropicOkHttpClient.fromEnv();

        JsonOutputFormat.Schema schema = JsonOutputFormat.Schema.builder()
            .putAdditionalProperty("type", JsonValue.from("object"))
            .putAdditionalProperty("properties", JsonValue.from(Map.of(
                "name", Map.of("type", "string"),
                "email", Map.of("type", "string"),
                "plan_interest", Map.of("type", "string"))))
            .putAdditionalProperty("required", JsonValue.from(
                List.of("name", "email", "plan_interest")))
            .putAdditionalProperty("additionalProperties", JsonValue.from(false))
            .build();

        OutputConfig outputConfig = OutputConfig.builder()
            .format(JsonOutputFormat.builder().schema(schema).build())
            .build();

        MessageCreateParams createParams = MessageCreateParams.builder()
            .model(Model.CLAUDE_OPUS_5_5)
            .maxTokens(1024)
            .outputConfig(outputConfig)
            .addUserMessage(
                "John Smith (john@example.com) is interested in our Enterprise plan.")
            .build();

        String json = client.messages().create(createParams).content().stream()
            .flatMap(contentBlock -> contentBlock.text().stream())
            .findFirst()
            .orElseThrow()
            .text();

        JsonNode contact = new ObjectMapper().readTree(json);
        IO.println(contact);
    }
    ```

    Das obige Beispiel gibt Folgendes aus:

    ```text Output wrap
    {"name":"John Smith","email":"john@example.com","plan_interest":"Enterprise"}
    ```

    Ein umfangreicheres Beispiel, das ein verschachteltes Schema mit Arrays und Beschreibungen erstellt, findest du in [`StructuredOutputsRawExample.java`](https://github.com/anthropics/anthropic-sdk-java/blob/main/anthropic-java-example/src/main/java/com/anthropic/example/StructuredOutputsRawExample.java) im SDK-Repository.
  </Tab>

  <Tab title="PHP">
    ```php
    use Anthropic\Messages\OutputConfig;
    use Anthropic\Messages\JSONOutputFormat;

    $client = new Client();

    $message = $client->messages->create(
        maxTokens: 1024,
        messages: [
            [
                'role' => 'user',
                'content' => 'Extract the key information from this email: '
                    . 'John Smith (john@example.com) is interested in our Enterprise plan.',
            ],
        ],
        model: 'claude-opus-5-5',
        outputConfig: OutputConfig::with(format: JSONOutputFormat::with(schema: [
            'type' => 'object',
            'properties' => [
                'name' => ['type' => 'string'],
                'email' => ['type' => 'string'],
                'plan_interest' => ['type' => 'string'],
            ],
            'required' => ['name', 'email', 'plan_interest'],
            'additionalProperties' => false,
        ])),
    );

    $textBlock = array_find($message->content, static fn ($block): bool => $block->type === 'text');
    $contact = json_decode($textBlock->text, associative: true);
    var_dump($contact);
    ```

    Übergib das Schema als assoziatives Array an `OutputConfig::with()` und dekodiere die Antwort mit `json_decode()`.

    Das obige Beispiel gibt Folgendes aus:

    ```text Output wrap
    array(3) {
      ["name"]=>
      string(10) "John Smith"
      ["email"]=>
      string(16) "john@example.com"
      ["plan_interest"]=>
      string(10) "Enterprise"
    }
    ```
  </Tab>

  <Tab title="Ruby">
    ```ruby
    client = Anthropic::Client.new

    response = client.messages.create(
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages: [
        {
          role: "user",
          content: "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."
        }
      ],
      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 = response.content.find { it.type == :text }.text
    contact = JSON.parse(text)
    p contact
    ```

    Das obige Beispiel gibt Folgendes aus:

    ```text Output wrap
    {"name" => "John Smith", "email" => "john@example.com", "plan_interest" => "Enterprise", "demo_requested" => true}
    ```
  </Tab>
</Tabs>

## Häufige Anwendungsfälle

<AccordionGroup>
  <Accordion title="Datenextraktion">
    Extrahiere strukturierte Daten aus unstrukturiertem Text:

    <CodeGroup>
      ```bash cURL
      curl https://api.anthropic.com/v1/messages \
        -H "content-type: application/json" \
        -H "x-api-key: $ANTHROPIC_API_KEY" \
        -H "anthropic-version: 2023-06-01" \
        -d '{
          "model": "claude-opus-5-5",
          "max_tokens": 4096,
          "messages": [
            {
              "role": "user",
              "content": "Extract invoice data from: Invoice #12345, Date: 2024-01-15, Total: $500.00"
            }
          ],
          "output_config": {
            "format": {
              "type": "json_schema",
              "schema": {
                "type": "object",
                "properties": {
                  "invoice_number": {"type": "string"},
                  "date": {"type": "string"},
                  "total_amount": {"type": "number"},
                  "line_items": {
                    "type": "array",
                    "items": {"type": "object", "additionalProperties": false}
                  },
                  "customer_name": {"type": "string"}
                },
                "required": ["invoice_number", "date", "total_amount", "line_items", "customer_name"],
                "additionalProperties": false
              }
            }
          }
        }'
      ```

      ```bash CLI
      ant messages create \
        --transform 'content.#(type=="text").text|@fromstr' \
        --format jsonl <<'YAML'
      model: claude-opus-5-5
      max_tokens: 4096
      messages:
        - role: user
          content: "Extract invoice data from: Invoice #12345, Date: 2024-01-15, Total: $500.00"
      output_config:
        format:
          type: json_schema
          schema:
            type: object
            properties:
              invoice_number: {type: string}
              date: {type: string}
              total_amount: {type: number}
              line_items:
                type: array
                items: {type: object, additionalProperties: false}
              customer_name: {type: string}
            required: [invoice_number, date, total_amount, line_items, customer_name]
            additionalProperties: false
      YAML
      ```

      ```python Python
      from pydantic import BaseModel


      class Invoice(BaseModel):
          invoice_number: str
          date: str
          total_amount: float
          line_items: list[dict]
          customer_name: str


      client = anthropic.Anthropic()
      invoice_text = "Invoice #12345, Date: 2024-01-15, Total: $500.00"

      response = client.messages.parse(
          model="claude-opus-5-5",
          max_tokens=4096,
          output_format=Invoice,
          messages=[
              {"role": "user", "content": f"Extract invoice data from: {invoice_text}"}
          ],
      )

      print(response.parsed_output)
      ```

      ```typescript TypeScript
      import { z } from "zod";
      import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";

      const client = new Anthropic();

      const InvoiceSchema = z.object({
        invoice_number: z.string(),
        date: z.string(),
        total_amount: z.number(),
        line_items: z.array(z.record(z.string(), z.any())),
        customer_name: z.string()
      });

      const invoiceText = "Invoice #12345, Date: 2024-01-15, Total: $500.00";
      const response = await client.messages.parse({
        model: "claude-opus-5-5",
        max_tokens: 4096,
        output_config: { format: zodOutputFormat(InvoiceSchema) },
        messages: [{ role: "user", content: `Extract invoice data from: ${invoiceText}` }]
      });
      console.log(response.parsed_output);
      ```

      ```csharp C#
      AnthropicClient client = new();

      string invoiceText = "Invoice #12345, Date: 2024-01-15, Total: $500.00";

      var parameters = new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 4096,
          OutputConfig = new OutputConfig
          {
              Format = new JsonOutputFormat
              {
                  Schema = new Dictionary<string, JsonElement>
                  {
                      ["type"] = JsonSerializer.SerializeToElement("object"),
                      ["properties"] = JsonSerializer.SerializeToElement(new
                      {
                          invoice_number = new { type = "string" },
                          date = new { type = "string" },
                          total_amount = new { type = "number" },
                          line_items = new
                          {
                              type = "array",
                              items = new
                              {
                                  type = "object",
                                  additionalProperties = false,
                              },
                          },
                          customer_name = new { type = "string" },
                      }),
                      ["required"] = JsonSerializer.SerializeToElement(new[] { "invoice_number", "date", "total_amount", "line_items", "customer_name" }),
                      ["additionalProperties"] = JsonSerializer.SerializeToElement(false),
                  },
              },
          },
          Messages = [new() { Role = Role.User, Content = $"Extract invoice data from: {invoiceText}" }]
      };

      var message = await client.Messages.Create(parameters);
      Console.WriteLine(message);
      ```

      ```go Go
      client := anthropic.NewClient()

      invoiceText := "Invoice #12345, Date: 2024-01-15, Total: $500.00"

      schema := map[string]any{
      	"type":                 "object",
      	"additionalProperties": false,
      	"properties": map[string]any{
      		"invoice_number": map[string]any{"type": "string"},
      		"date":           map[string]any{"type": "string"},
      		"total_amount":   map[string]any{"type": "number"},
      		"line_items": map[string]any{
      			"type": "array",
      			"items": map[string]any{
      				"type":                 "object",
      				"additionalProperties": false,
      				"properties": map[string]any{
      					"description": map[string]any{"type": "string"},
      					"quantity":    map[string]any{"type": "number"},
      					"unit_price":  map[string]any{"type": "number"},
      				},
      				"required": []string{"description", "quantity", "unit_price"},
      			},
      		},
      		"customer_name": map[string]any{"type": "string"},
      	},
      	"required": []string{"invoice_number", "date", "total_amount", "line_items", "customer_name"},
      }

      response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
      	Model:     anthropic.ModelClaudeOpus5_5,
      	MaxTokens: 4096,
      	OutputConfig: anthropic.OutputConfigParam{
      		Format: anthropic.JSONOutputFormatParam{
      			Schema: schema,
      		},
      	},
      	Messages: []anthropic.MessageParam{
      		anthropic.NewUserMessage(anthropic.NewTextBlock(fmt.Sprintf("Extract invoice data from: %s", invoiceText))),
      	},
      })
      if err != nil {
      	log.Fatal(err)
      }
      for _, block := range response.Content {
      	switch variant := block.AsAny().(type) {
      	case anthropic.TextBlock:
      		fmt.Println(variant.Text)
      	}
      }
      ```

      ```java Java
      import com.fasterxml.jackson.annotation.JsonProperty;

      static class LineItem {
          @JsonProperty("description")
          public String description;

          @JsonProperty("quantity")
          public int quantity;

          @JsonProperty("unit_price")
          public double unitPrice;
      }

      static class Invoice {
          @JsonProperty("invoice_number")
          public String invoiceNumber;

          @JsonProperty("date")
          public String date;

          @JsonProperty("total_amount")
          public double totalAmount;

          @JsonProperty("line_items")
          public List<LineItem> lineItems;

          @JsonProperty("customer_name")
          public String customerName;
      }

      void main() {
          AnthropicClient client = AnthropicOkHttpClient.fromEnv();

          String invoiceText = "Invoice #12345, Date: 2024-01-15, Total: $500.00";

          StructuredMessageCreateParams<Invoice> params = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(4096L)
              .outputConfig(Invoice.class)
              .addUserMessage("Extract invoice data from: " + invoiceText)
              .build();

          StructuredMessage<Invoice> response = client.messages().create(params);
          Invoice invoice = response.content().stream()
              .flatMap(block -> block.text().stream())
              .findFirst().orElseThrow().text();
          IO.println(invoice.invoiceNumber + ": $" + invoice.totalAmount);
      }
      ```

      ```php PHP
      use Anthropic\Lib\Concerns\StructuredOutputModelTrait;
      use Anthropic\Lib\Contracts\StructuredOutputModel;

      $client = new Client();

      class Invoice implements StructuredOutputModel
      {
          use StructuredOutputModelTrait;

          public string $invoice_number;
          public string $date;
          public float $total_amount;
          public array $line_items;
          public string $customer_name;
      }

      $invoiceText = "Invoice #12345, Date: 2024-01-15, Total: $500.00";

      $message = $client->messages->create(
          maxTokens: 4096,
          messages: [
              ['role' => 'user', 'content' => "Extract invoice data from: $invoiceText"]
          ],
          model: 'claude-opus-5-5',
          outputConfig: ['format' => Invoice::class],
      );

      $invoice = $message->parsedOutput();
      if ($invoice instanceof Invoice) {
          echo "Invoice {$invoice->invoice_number}: \${$invoice->total_amount}\n";
      }
      ```

      ```ruby Ruby
      client = Anthropic::Client.new

      class LineItem < Anthropic::BaseModel
        required :description, String
        required :amount, Float
      end

      class Invoice < Anthropic::BaseModel
        required :invoice_number, String
        required :date, String
        required :total_amount, Float
        required :line_items, Anthropic::ArrayOf[LineItem]
        required :customer_name, String
      end

      invoice_text = "Invoice #12345, Date: 2024-01-15, Total: $500.00"

      message = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 4096,
        output_config: {format: Invoice},
        messages: [
          {role: "user", content: "Extract invoice data from: #{invoice_text}"}
        ]
      )

      invoice = message.parsed_output
      puts "Invoice #{invoice.invoice_number}: $#{invoice.total_amount}"
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Klassifizierung">
    Klassifiziere Inhalte mit strukturierten Kategorien:

    <CodeGroup>
      ```bash cURL
      curl https://api.anthropic.com/v1/messages \
        -H "content-type: application/json" \
        -H "x-api-key: $ANTHROPIC_API_KEY" \
        -H "anthropic-version: 2023-06-01" \
        -d '{
          "model": "claude-opus-5-5",
          "max_tokens": 1024,
          "messages": [
            {
              "role": "user",
              "content": "Classify this feedback: Great product, fast shipping!"
            }
          ],
          "output_config": {
            "format": {
              "type": "json_schema",
              "schema": {
                "type": "object",
                "properties": {
                  "category": {"type": "string"},
                  "confidence": {"type": "number"},
                  "tags": {"type": "array", "items": {"type": "string"}},
                  "sentiment": {"type": "string"}
                },
                "required": ["category", "confidence", "tags", "sentiment"],
                "additionalProperties": false
              }
            }
          }
        }'
      ```

      ```bash CLI
      ant messages create \
        --transform 'content.#(type=="text").text|@fromstr' \
        --format jsonl <<'YAML'
      model: claude-opus-5-5
      max_tokens: 1024
      messages:
        - role: user
          content: "Classify this feedback: Great product, fast shipping!"
      output_config:
        format:
          type: json_schema
          schema:
            type: object
            properties:
              category:
                type: string
              confidence:
                type: number
              tags:
                type: array
                items:
                  type: string
              sentiment:
                type: string
            required:
              - category
              - confidence
              - tags
              - sentiment
            additionalProperties: false
      YAML
      ```

      ```python Python
      from pydantic import BaseModel

      client = Anthropic()


      class Classification(BaseModel):
          category: str
          confidence: float
          tags: list[str]
          sentiment: str


      feedback_text = "Great product, but the delivery was slow."
      response = client.messages.parse(
          model="claude-opus-5-5",
          max_tokens=1024,
          output_format=Classification,
          messages=[{"role": "user", "content": f"Classify this feedback: {feedback_text}"}],
      )

      print(response.parsed_output)
      ```

      ```typescript TypeScript
      import { z } from "zod";
      import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";

      const client = new Anthropic();

      const ClassificationSchema = z.object({
        category: z.string(),
        confidence: z.number(),
        tags: z.array(z.string()),
        sentiment: z.string()
      });

      const feedbackText = "Great product, but the delivery was slow.";
      const response = await client.messages.parse({
        model: "claude-opus-5-5",
        max_tokens: 1024,
        output_config: { format: zodOutputFormat(ClassificationSchema) },
        messages: [{ role: "user", content: `Classify this feedback: ${feedbackText}` }]
      });

      console.log(response.parsed_output);
      ```

      ```csharp C#
      string feedbackText = "Great product, fast shipping!";

      var parameters = new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 1024,
          Messages = [new() { Role = Role.User, Content = $"Classify this feedback: {feedbackText}" }],
          OutputConfig = new OutputConfig
          {
              Format = new JsonOutputFormat
              {
                  Schema = new Dictionary<string, JsonElement>
                  {
                      ["type"] = JsonSerializer.SerializeToElement("object"),
                      ["properties"] = JsonSerializer.SerializeToElement(new
                      {
                          category = new { type = "string" },
                          confidence = new { type = "number" },
                          tags = new { type = "array", items = new { type = "string" } },
                          sentiment = new { type = "string" },
                      }),
                      ["required"] = JsonSerializer.SerializeToElement(new[] { "category", "confidence", "tags", "sentiment" }),
                      ["additionalProperties"] = JsonSerializer.SerializeToElement(false),
                  },
              },
          },
      };

      var message = await client.Messages.Create(parameters);
      Console.WriteLine(message);
      ```

      ```go Go
      feedbackText := "Great product, fast shipping!"

      schema := map[string]any{
      	"type": "object",
      	"properties": map[string]any{
      		"category":   map[string]any{"type": "string"},
      		"confidence": map[string]any{"type": "number"},
      		"tags":       map[string]any{"type": "array", "items": map[string]any{"type": "string"}},
      		"sentiment":  map[string]any{"type": "string"},
      	},
      	"required":             []string{"category", "confidence", "tags", "sentiment"},
      	"additionalProperties": false,
      }

      response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
      	Model:     anthropic.ModelClaudeOpus5_5,
      	MaxTokens: 1024,
      	OutputConfig: anthropic.OutputConfigParam{
      		Format: anthropic.JSONOutputFormatParam{
      			Schema: schema,
      		},
      	},
      	Messages: []anthropic.MessageParam{
      		anthropic.NewUserMessage(anthropic.NewTextBlock(fmt.Sprintf("Classify this feedback: %s", feedbackText))),
      	},
      })
      if err != nil {
      	log.Fatal(err)
      }
      for _, block := range response.Content {
      	switch variant := block.AsAny().(type) {
      	case anthropic.TextBlock:
      		var result map[string]any
      		json.Unmarshal([]byte(variant.Text), &result)
      		fmt.Println(result)
      	}
      }
      ```

      ```java Java
      import com.fasterxml.jackson.annotation.JsonProperty;

      static class Classification {
          @JsonProperty("category")
          public String category;

          @JsonProperty("confidence")
          public double confidence;

          @JsonProperty("tags")
          public List<String> tags;

          @JsonProperty("sentiment")
          public String sentiment;
      }

      void main() {
          AnthropicClient client = AnthropicOkHttpClient.fromEnv();

          String feedbackText = "Great product, fast shipping!";

          StructuredMessageCreateParams<Classification> params = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024L)
              .outputConfig(Classification.class)
              .addUserMessage("Classify this feedback: " + feedbackText)
              .build();

          StructuredMessage<Classification> response = client.messages().create(params);
          Classification result = response.content().stream()
              .flatMap(block -> block.text().stream())
              .findFirst().orElseThrow().text();
          IO.println(result.category + " (" + result.confidence + ")");
      }
      ```

      ```php PHP
      use Anthropic\Lib\Concerns\StructuredOutputModelTrait;
      use Anthropic\Lib\Contracts\StructuredOutputModel;

      $client = new Client();

      class Classification implements StructuredOutputModel
      {
          use StructuredOutputModelTrait;

          public string $category;
          public float $confidence;
          public array $tags;
          public string $sentiment;
      }

      $feedbackText = "Great product, fast shipping!";

      $message = $client->messages->create(
          maxTokens: 1024,
          messages: [
              ['role' => 'user', 'content' => "Classify this feedback: {$feedbackText}"]
          ],
          model: 'claude-opus-5-5',
          outputConfig: ['format' => Classification::class],
      );

      $result = $message->parsedOutput();
      if ($result instanceof Classification) {
          echo "{$result->category} ({$result->confidence}): {$result->sentiment}\n";
      }
      ```

      ```ruby Ruby
      client = Anthropic::Client.new

      class Classification < Anthropic::BaseModel
        required :category, String
        required :confidence, Float
        required :tags, Anthropic::ArrayOf[String]
        required :sentiment, String
      end

      feedback_text = "Great product, fast shipping!"

      message = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 1024,
        output_config: {format: Classification},
        messages: [
          {role: "user", content: "Classify this feedback: #{feedback_text}"}
        ]
      )
      puts message.parsed_output
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Formatierung von API-Antworten">
    Generiere API-fertige Antworten:

    <CodeGroup>
      ```bash cURL
      curl https://api.anthropic.com/v1/messages \
        -H "content-type: application/json" \
        -H "x-api-key: $ANTHROPIC_API_KEY" \
        -H "anthropic-version: 2023-06-01" \
        -d '{
          "model": "claude-opus-5-5",
          "max_tokens": 1024,
          "messages": [
            {
              "role": "user",
              "content": "Process this request: ..."
            }
          ],
          "output_config": {
            "format": {
              "type": "json_schema",
              "schema": {
                "type": "object",
                "properties": {
                  "status": {"type": "string"},
                  "data": {"type": "object", "additionalProperties": false},
                  "errors": {
                    "type": "array",
                    "items": {"type": "object", "additionalProperties": false}
                  },
                  "metadata": {"type": "object", "additionalProperties": false}
                },
                "required": ["status", "data", "metadata"],
                "additionalProperties": false
              }
            }
          }
        }'
      ```

      ```bash CLI
      ant messages create \
        --transform 'content.#(type=="text").text' \
        --raw-output <<'YAML'
      model: claude-opus-5-5
      max_tokens: 1024
      output_config:
        format:
          type: json_schema
          schema:
            type: object
            properties:
              status:
                type: string
              data:
                type: object
                additionalProperties: false
              errors:
                type: array
                items:
                  type: object
                  additionalProperties: false
              metadata:
                type: object
                additionalProperties: false
            required:
              - status
              - data
              - metadata
            additionalProperties: false
      messages:
        - role: user
          content: "Process this request: ..."
      YAML
      ```

      ```python Python
      from pydantic import BaseModel

      client = Anthropic()


      class APIResponse(BaseModel):
          status: str
          data: dict
          errors: list[dict] | None
          metadata: dict


      response = client.messages.parse(
          model="claude-opus-5-5",
          max_tokens=1024,
          output_format=APIResponse,
          messages=[{"role": "user", "content": "Process this request: ..."}],
      )

      print(response.parsed_output)
      ```

      ```typescript TypeScript
      import { z } from "zod";
      import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";

      const client = new Anthropic();

      const APIResponseSchema = z.object({
        status: z.string(),
        data: z.record(z.string(), z.any()),
        errors: z.array(z.record(z.string(), z.any())).optional(),
        metadata: z.record(z.string(), z.any())
      });

      const response = await client.messages.parse({
        model: "claude-opus-5-5",
        max_tokens: 1024,
        output_config: { format: zodOutputFormat(APIResponseSchema) },
        messages: [{ role: "user", content: "Process this request..." }]
      });

      console.log(response.parsed_output);
      ```

      ```csharp C#
      var parameters = new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 1024,
          Messages = [new() { Role = Role.User, Content = "Process this request: ..." }],
          OutputConfig = new OutputConfig
          {
              Format = new JsonOutputFormat
              {
                  Schema = new Dictionary<string, JsonElement>
                  {
                      ["type"] = JsonSerializer.SerializeToElement("object"),
                      ["properties"] = JsonSerializer.SerializeToElement(new
                      {
                          status = new { type = "string" },
                          data = new { type = "object", additionalProperties = false },
                          errors = new
                          {
                              type = "array",
                              items = new { type = "object", additionalProperties = false },
                          },
                          metadata = new { type = "object", additionalProperties = false },
                      }),
                      ["required"] = JsonSerializer.SerializeToElement(new[] { "status", "data", "metadata" }),
                      ["additionalProperties"] = JsonSerializer.SerializeToElement(false),
                  },
              },
          },
      };

      var message = await client.Messages.Create(parameters);
      Console.WriteLine(message);
      ```

      ```go Go
      client := anthropic.NewClient()

      response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
      	Model:     anthropic.ModelClaudeOpus5_5,
      	MaxTokens: 1024,
      	OutputConfig: anthropic.OutputConfigParam{
      		Format: anthropic.JSONOutputFormatParam{
      			Schema: map[string]any{
      				"type":                 "object",
      				"additionalProperties": false,
      				"properties": map[string]any{
      					"status": map[string]any{
      						"type": "string",
      					},
      					"data": map[string]any{
      						"type":                 "object",
      						"additionalProperties": false,
      					},
      					"errors": map[string]any{
      						"type": "array",
      						"items": map[string]any{
      							"type":                 "object",
      							"additionalProperties": false,
      						},
      					},
      					"metadata": map[string]any{
      						"type":                 "object",
      						"additionalProperties": false,
      					},
      				},
      				"required": []string{"status", "data", "metadata"},
      			},
      		},
      	},
      	Messages: []anthropic.MessageParam{
      		anthropic.NewUserMessage(anthropic.NewTextBlock("Process this request: ...")),
      	},
      })
      if err != nil {
      	log.Fatal(err)
      }
      for _, block := range response.Content {
      	switch variant := block.AsAny().(type) {
      	case anthropic.TextBlock:
      		fmt.Println(variant.Text)
      	}
      }
      ```

      ```java Java
      import com.fasterxml.jackson.annotation.JsonProperty;

      static class APIData {
          @JsonProperty("message")
          public String message;

          @JsonProperty("resource_id")
          public String resourceId;
      }

      static class APIError {
          @JsonProperty("code")
          public String code;

          @JsonProperty("message")
          public String message;
      }

      static class APIMetadata {
          @JsonProperty("request_id")
          public String requestId;

          @JsonProperty("timestamp")
          public String timestamp;
      }

      static class APIResponse {
          @JsonProperty("status")
          public String status;

          @JsonProperty("data")
          public APIData data;

          @JsonProperty("errors")
          public List<APIError> errors;

          @JsonProperty("metadata")
          public APIMetadata metadata;
      }

      void main() {
          AnthropicClient client = AnthropicOkHttpClient.fromEnv();

          StructuredMessageCreateParams<APIResponse> params = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024L)
              .outputConfig(APIResponse.class)
              .addUserMessage("Process this request: ...")
              .build();

          StructuredMessage<APIResponse> response = client.messages().create(params);
          APIResponse result = response.content().stream()
              .flatMap(block -> block.text().stream())
              .findFirst().orElseThrow().text();
          IO.println(result.status);
      }
      ```

      ```php PHP
      use Anthropic\Lib\Attributes\Constrained;
      use Anthropic\Lib\Concerns\StructuredOutputModelTrait;
      use Anthropic\Lib\Contracts\StructuredOutputModel;

      $client = new Client();

      class Payload implements StructuredOutputModel { use StructuredOutputModelTrait; public string $message; }

      class APIError implements StructuredOutputModel { use StructuredOutputModelTrait; public string $code; public string $detail; }

      class Metadata implements StructuredOutputModel { use StructuredOutputModelTrait; public string $request_id; }

      class APIResponse implements StructuredOutputModel
      {
          use StructuredOutputModelTrait;

          public string $status;
          public Payload $data;
          #[Constrained(itemClass: APIError::class)]
          public ?array $errors;
          public Metadata $metadata;
      }

      $message = $client->messages->create(
          maxTokens: 1024,
          messages: [
              ['role' => 'user', 'content' => 'Process this request: ...']
          ],
          model: 'claude-opus-5-5',
          outputConfig: ['format' => APIResponse::class],
      );

      $result = $message->parsedOutput();
      if ($result instanceof APIResponse) {
          echo "{$result->status}: {$result->data->message}\n";
      }
      ```

      ```ruby Ruby
      client = Anthropic::Client.new

      class Payload < Anthropic::BaseModel
        required :message, String
      end

      class APIError < Anthropic::BaseModel
        required :code, String
        required :detail, String
      end

      class Metadata < Anthropic::BaseModel
        required :request_id, String
      end

      class APIResponse < Anthropic::BaseModel
        required :status, String
        required :data, Payload
        optional :errors, Anthropic::ArrayOf[APIError]
        required :metadata, Metadata
      end

      message = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 1024,
        output_config: {format: APIResponse},
        messages: [
          {role: "user", content: "Process this request: ..."}
        ]
      )
      puts message.parsed_output
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

## Strikte Tool-Nutzung

Um die JSON-Schema-Konformität von Tool-Eingaben mit grammatikbeschränktem Sampling durchzusetzen, siehe [Strikte Tool-Nutzung](https://platform.claude.com/docs/de/agents-and-tools/tool-use/strict-tool-use).

### Beide Funktionen zusammen verwenden

JSON-Ausgaben und strikte Tool-Nutzung lösen unterschiedliche Probleme und arbeiten zusammen:

* **JSON-Ausgaben** steuern Claudes Antwortformat (was Claude sagt)
* **Strikte Tool-Nutzung** validiert Tool-Parameter (wie Claude deine Funktionen aufruft)

In Kombination kann Claude Tools mit garantiert gültigen Parametern aufrufen UND strukturierte JSON-Antworten zurückgeben. Das ist nützlich für agentische Workflows, bei denen du sowohl zuverlässige Tool-Aufrufe als auch strukturierte Endausgaben benötigst.

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "messages": [
        {
          "role": "user",
          "content": "Help me plan a trip to Paris departing May 15, 2026"
        }
      ],
      "output_config": {
        "format": {
          "type": "json_schema",
          "schema": {
            "type": "object",
            "properties": {
              "summary": {"type": "string"},
              "next_steps": {"type": "array", "items": {"type": "string"}}
            },
            "required": ["summary", "next_steps"],
            "additionalProperties": false
          }
        }
      },
      "tools": [
        {
          "name": "search_flights",
          "strict": true,
          "input_schema": {
            "type": "object",
            "properties": {
              "destination": {"type": "string"},
              "date": {"type": "string", "format": "date"}
            },
            "required": ["destination", "date"],
            "additionalProperties": false
          }
        }
      ]
    }'
  ```

  ```bash CLI
  ant messages create <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  messages:
    - role: user
      content: Help me plan a trip to Paris departing May 15, 2026
  # JSON-Ausgaben: strukturiertes Antwortformat
  output_config:
    format:
      type: json_schema
      schema:
        type: object
        properties:
          summary:
            type: string
          next_steps:
            type: array
            items:
              type: string
        required: [summary, next_steps]
        additionalProperties: false
  # Strikte Tool-Nutzung: garantierte Tool-Parameter
  tools:
    - name: search_flights
      strict: true
      input_schema:
        type: object
        properties:
          destination:
            type: string
          date:
            type: string
            format: date
        required: [destination, date]
        additionalProperties: false
  YAML
  ```

  ```python Python
  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      messages=[
          {
              "role": "user",
              "content": "Help me plan a trip to Paris departing May 15, 2026",
          }
      ],
      # JSON-Ausgaben: strukturiertes Antwortformat
      output_config={
          "format": {
              "type": "json_schema",
              "schema": {
                  "type": "object",
                  "properties": {
                      "summary": {"type": "string"},
                      "next_steps": {"type": "array", "items": {"type": "string"}},
                  },
                  "required": ["summary", "next_steps"],
                  "additionalProperties": False,
              },
          }
      },
      # Strikte Tool-Nutzung: garantierte Tool-Parameter
      tools=[
          {
              "name": "search_flights",
              "strict": True,
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "destination": {"type": "string"},
                      "date": {"type": "string", "format": "date"},
                  },
                  "required": ["destination", "date"],
                  "additionalProperties": False,
              },
          }
      ],
  )

  print(response)
  ```

  ```typescript TypeScript
  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Help me plan a trip to Paris departing May 15, 2026" }],
    // JSON-Ausgaben: strukturiertes Antwortformat
    output_config: {
      format: {
        type: "json_schema",
        schema: {
          type: "object",
          properties: {
            summary: { type: "string" },
            next_steps: { type: "array", items: { type: "string" } }
          },
          required: ["summary", "next_steps"],
          additionalProperties: false
        }
      }
    },
    // Strikte Tool-Nutzung: garantierte Tool-Parameter
    tools: [
      {
        name: "search_flights",
        description: "Search for available flights to a destination on a specific date",
        strict: true,
        input_schema: {
          type: "object",
          properties: {
            destination: { type: "string" },
            date: { type: "string", format: "date" }
          },
          required: ["destination", "date"],
          additionalProperties: false
        }
      }
    ]
  });

  // Claude ruft ggf. zuerst das Tool auf (tool_use) oder antwortet mit JSON (text)
  console.log("Stop reason:", response.stop_reason);
  for (const block of response.content) {
    switch (block.type) {
      case "tool_use":
        console.log(`Tool call: ${block.name}(${JSON.stringify(block.input)})`);
        break;
      case "text":
        console.log("Response:", block.text);
        break;
    }
  }
  ```

  ```csharp C#
  var parameters = new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Messages = [new() { Role = Role.User, Content = "Help me plan a trip to Paris departing May 15, 2026" }],
      // JSON-Ausgaben: strukturiertes Antwortformat
      OutputConfig = new OutputConfig
      {
          Format = new JsonOutputFormat
          {
              Schema = new Dictionary<string, JsonElement>
              {
                  ["type"] = JsonSerializer.SerializeToElement("object"),
                  ["properties"] = JsonSerializer.SerializeToElement(new
                  {
                      summary = new { type = "string" },
                      next_steps = new { type = "array", items = new { type = "string" } },
                  }),
                  ["required"] = JsonSerializer.SerializeToElement(new[] { "summary", "next_steps" }),
                  ["additionalProperties"] = JsonSerializer.SerializeToElement(false),
              },
          },
      },
      // Strikte Tool-Nutzung: garantierte Tool-Parameter
      Tools =
      [
          new Tool
          {
              Name = "search_flights",
              Strict = true,
              InputSchema = new InputSchema(new Dictionary<string, JsonElement>
              {
                  ["properties"] = JsonSerializer.SerializeToElement(new Dictionary<string, object>
                  {
                      ["destination"] = new { type = "string" },
                      ["date"] = new { type = "string", format = "date" },
                  }),
                  ["required"] = JsonSerializer.SerializeToElement(new[] { "destination", "date" }),
                  ["additionalProperties"] = JsonSerializer.SerializeToElement(false),
              }),
          }
      ],
  };

  var message = await client.Messages.Create(parameters);
  Console.WriteLine(message);
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Help me plan a trip to Paris departing May 15, 2026")),
  	},
  	// JSON-Ausgaben: strukturiertes Antwortformat
  	OutputConfig: anthropic.OutputConfigParam{
  		Format: anthropic.JSONOutputFormatParam{
  			Schema: map[string]any{
  				"type":                 "object",
  				"additionalProperties": false,
  				"properties": map[string]any{
  					"summary":    map[string]any{"type": "string"},
  					"next_steps": map[string]any{"type": "array", "items": map[string]any{"type": "string"}},
  				},
  				"required": []string{"summary", "next_steps"},
  			},
  		},
  	},
  	// Strikte Tool-Nutzung: garantierte Tool-Parameter
  	Tools: []anthropic.ToolUnionParam{
  		{OfTool: &anthropic.ToolParam{
  			Name:   "search_flights",
  			Strict: anthropic.Bool(true),
  			InputSchema: anthropic.ToolInputSchemaParam{
  				Properties: map[string]any{
  					"destination": map[string]any{"type": "string"},
  					"date":        map[string]any{"type": "string", "format": "date"},
  				},
  				Required: []string{"destination", "date"},
  				ExtraFields: map[string]any{
  					"additionalProperties": false,
  				},
  			}}},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }
  fmt.Println(response.Content)
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  // JSON-Ausgaben: strukturiertes Antwortformat
  JsonOutputFormat.Schema outputSchema = JsonOutputFormat.Schema.builder()
      .putAdditionalProperty("type", JsonValue.from("object"))
      .putAdditionalProperty("properties", JsonValue.from(Map.of(
          "summary", Map.of("type", "string"),
          "next_steps", Map.of("type", "array", "items", Map.of("type", "string"))
      )))
      .putAdditionalProperty("required", JsonValue.from(List.of("summary", "next_steps")))
      .putAdditionalProperty("additionalProperties", JsonValue.from(false))
      .build();

  // Strikte Tool-Nutzung: garantierte Tool-Parameter
  InputSchema toolSchema = InputSchema.builder()
      .properties(JsonValue.from(Map.of(
          "destination", Map.of("type", "string"),
          "date", Map.of("type", "string", "format", "date")
      )))
      .putAdditionalProperty("required", JsonValue.from(List.of("destination", "date")))
      .putAdditionalProperty("additionalProperties", JsonValue.from(false))
      .build();

  MessageCreateParams params = MessageCreateParams.builder()
      .model(Model.CLAUDE_OPUS_5_5)
      .maxTokens(1024L)
      .addUserMessage("Help me plan a trip to Paris departing May 15, 2026")
      .outputConfig(OutputConfig.builder()
          .format(JsonOutputFormat.builder().schema(outputSchema).build())
          .build())
      .addTool(Tool.builder()
          .name("search_flights")
          .description("Search for available flights to a destination on a specific date")
          .strict(true)
          .inputSchema(toolSchema)
          .build())
      .build();

  Message response = client.messages().create(params);
  IO.println(response);
  ```

  ```php PHP
  use Anthropic\Lib\Concerns\StructuredOutputModelTrait;
  use Anthropic\Lib\Contracts\StructuredOutputModel;
  use Anthropic\Messages\ToolUseBlock;

  $client = new Client();

  class TripPlan implements StructuredOutputModel
  {
      use StructuredOutputModelTrait;

      public string $summary;
      public array $next_steps;
  }

  $message = $client->messages->create(
      maxTokens: 1024,
      messages: [
          ['role' => 'user', 'content' => 'Help me plan a trip to Paris departing May 15, 2026']
      ],
      model: 'claude-opus-5-5',
      // JSON-Ausgaben: strukturiertes Antwortformat
      outputConfig: ['format' => TripPlan::class],
      // Strikte Tool-Nutzung: garantierte Tool-Parameter
      tools: [
          [
              'name' => 'search_flights',
              'strict' => true,
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'destination' => ['type' => 'string'],
                      'date' => ['type' => 'string', 'format' => 'date']
                  ],
                  'required' => ['destination', 'date'],
                  'additionalProperties' => false
              ]
          ]
      ],
  );

  // Claude ruft ggf. zuerst das Tool auf (tool_use) oder antwortet mit JSON (text)
  $plan = $message->parsedOutput();
  if ($plan instanceof TripPlan) {
      echo $plan->summary, "\n";
  } elseif ($toolUse = array_find($message->content, fn($block) => $block instanceof ToolUseBlock)) {
      echo "Tool call: {$toolUse->name}(", json_encode($toolUse->input), ")\n";
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  message = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [
      {role: "user", content: "Help me plan a trip to Paris departing May 15, 2026"}
    ],
    # JSON-Ausgaben: strukturiertes Antwortformat
    output_config: {
      format: {
        type: :json_schema,
        schema: {
          type: "object",
          properties: {
            summary: {type: "string"},
            next_steps: {type: "array", items: {type: "string"}}
          },
          required: ["summary", "next_steps"],
          additionalProperties: false
        }
      }
    },
    # Strikte Tool-Nutzung: garantierte Tool-Parameter
    tools: [
      {
        name: "search_flights",
        strict: true,
        input_schema: {
          type: "object",
          properties: {
            destination: {type: "string"},
            date: {type: "string", format: "date"}
          },
          required: ["destination", "date"],
          additionalProperties: false
        }
      }
    ]
  )
  puts message
  ```
</CodeGroup>

## Wichtige Überlegungen

### Grammatik-Kompilierung und Caching

Strukturierte Ausgaben verwenden eingeschränktes Sampling mit kompilierten Grammatik-Artefakten. Das bringt einige Leistungsmerkmale mit sich, die du kennen solltest:

* **Latenz der ersten Anfrage:** Wenn du ein bestimmtes Schema zum ersten Mal verwendest, entsteht zusätzliche „latency“ (Latenz), während die Grammatik kompiliert wird

* **Automatisches Caching:** Kompilierte Grammatiken werden ab der letzten Verwendung 24 Stunden lang gecacht, wodurch nachfolgende Anfragen deutlich schneller werden

* **Cache-Invalidierung:** Der Cache wird invalidiert, wenn du Folgendes änderst:

  * Die JSON-Schema-Struktur
  * Die Menge der Tools in deiner Anfrage (bei gleichzeitiger Verwendung von strukturierten Ausgaben und Tool-Nutzung)
  * Das Ändern nur der Felder `name` oder `description` invalidiert den Cache nicht

### Prompt-Modifikation und Token-Kosten

Bei der Verwendung strukturierter Ausgaben erhält Claude automatisch einen zusätzlichen „system prompt“ (System-Prompt), der das erwartete Ausgabeformat erklärt. Das bedeutet:

* Deine Anzahl an Eingabe-Token ist etwas höher
* Der eingefügte Prompt kostet dich Token wie jeder andere System-Prompt
* Das Ändern des Parameters `output_config.format` invalidiert jeden [Prompt-Cache](https://platform.claude.com/docs/de/build-with-claude/prompt-caching) für diesen Konversationsstrang

### JSON-Schema-Einschränkungen

Strukturierte Ausgaben unterstützen Standard-JSON-Schema mit einigen Einschränkungen. Sowohl JSON-Ausgaben als auch strikte Tool-Nutzung teilen diese Einschränkungen.

<Accordion title="Unterstützte Funktionen">
  * Alle Basistypen: object, array, string, integer, number, boolean, null
  * `enum` (nur Strings, Zahlen, Booleans oder Nulls – keine komplexen Typen). Einen Hinweis zur Groß-/Kleinschreibung findest du unter [Ungültige Ausgaben](https://platform.claude.com/docs/de/build-with-claude/structured-outputs#invalid-outputs).
  * `const`
  * `anyOf` und `allOf` (mit Einschränkungen – `allOf` mit `$ref` wird nicht unterstützt)
  * `$ref`, `$def` und `definitions` (externes `$ref` wird nicht unterstützt)
  * `default`-Property für alle unterstützten Typen
  * `required` und `additionalProperties` (muss für Objekte auf `false` gesetzt sein)
  * String-Formate: `date-time`, `time`, `date`, `duration`, `email`, `hostname`, `uri`, `ipv4`, `ipv6`, `uuid`
  * Array-`minItems` (nur die Werte 0 und 1 werden unterstützt)
</Accordion>

<Accordion title="Nicht unterstützt">
  * Rekursive Schemas
  * Komplexe Typen innerhalb von Enums
  * Externes `$ref` (zum Beispiel `'$ref': 'http://...'`)
  * Numerische Constraints (wie `minimum`, `maximum`, `multipleOf`)
  * String-Constraints (`minLength`, `maxLength`)
  * Array-Constraints über `minItems` von 0 oder 1 hinaus
  * `additionalProperties` auf etwas anderes als `false` gesetzt

  Wenn du eine nicht unterstützte Funktion verwendest, erhältst du einen 400-Fehler mit Details.
</Accordion>

<Accordion title="Pattern-Unterstützung (Regex)">
  **Unterstützte Regex-Funktionen:**

  * Vollständiges Matching (`^...$`) und partielles Matching
  * Quantifizierer: `*`, `+`, `?`, einfache `{n,m}`-Fälle
  * Zeichenklassen: `[]`, `.`, `\d`, `\w`, `\s`
  * Gruppen: `(...)`

  **NICHT unterstützt:**

  * Rückverweise auf Gruppen (zum Beispiel `\1`, `\2`)
  * Lookahead-/Lookbehind-Assertions (zum Beispiel `(?=...)`, `(?!...)`)
  * Wortgrenzen: `\b`, `\B`
  * Komplexe `{n,m}`-Quantifizierer mit großen Bereichen

  Einfache Regex-Muster funktionieren gut. Komplexe Muster können zu 400-Fehlern führen.
</Accordion>

<Tip>
  SDK-Helfer können Schemas mit [von der API nicht unterstützten Constraints](https://platform.claude.com/docs/de/build-with-claude/structured-outputs#json-schema-limitations) transformieren. Siehe [Wie die SDK-Transformation funktioniert](https://platform.claude.com/docs/de/build-with-claude/structured-outputs#how-sdk-transformation-works).
</Tip>

### Reihenfolge der Properties

Bei der Verwendung strukturierter Ausgaben behalten Properties in Objekten ihre in deinem Schema definierte Reihenfolge bei, mit einer wichtigen Einschränkung: **Erforderliche Properties erscheinen zuerst, gefolgt von optionalen Properties**.

Zum Beispiel bei diesem Schema:

```json
{
  "type": "object",
  "properties": {
    "notes": { "type": "string" },
    "name": { "type": "string" },
    "email": { "type": "string" },
    "age": { "type": "integer" }
  },
  "required": ["name", "email"],
  "additionalProperties": false
}
```

Die Ausgabe ordnet die Properties wie folgt:

1. `name` (erforderlich, in Schema-Reihenfolge)
2. `email` (erforderlich, in Schema-Reihenfolge)
3. `notes` (optional, in Schema-Reihenfolge)
4. `age` (optional, in Schema-Reihenfolge)

Das bedeutet, die Ausgabe könnte so aussehen:

```json
{
  "name": "John Smith",
  "email": "john@example.com",
  "notes": "Interested in enterprise plan",
  "age": 35
}
```

Wenn die Reihenfolge der Properties in der Ausgabe für deine Anwendung wichtig ist, markiere alle Properties als erforderlich oder berücksichtige diese Umordnung in deiner Parsing-Logik.

### Ungültige Ausgaben

Obwohl strukturierte Ausgaben in den meisten Fällen Schema-Konformität garantieren, gibt es Szenarien, in denen die Ausgabe möglicherweise nicht deinem Schema entspricht:

**Ablehnungen** (`stop_reason: "refusal"`)

Claude behält seine Sicherheits- und Hilfsbereitschaftseigenschaften auch bei der Verwendung strukturierter Ausgaben bei. Wenn Claude eine Anfrage aus Sicherheitsgründen ablehnt:

* Die Antwort hat `stop_reason: "refusal"`
* Du erhältst einen 200-Statuscode
* Dir werden die generierten Token in Rechnung gestellt
* Die Ausgabe entspricht möglicherweise nicht deinem Schema, da die Ablehnungsnachricht Vorrang vor Schema-Constraints hat

Eine Property, die nach dem Nachdenken des Modells oder nach schrittweisem Reasoning fragt, kann zu einer `reasoning_extraction`-Ablehnung führen. Frage stattdessen nach einer kurzen Erklärung. Siehe [Reasoning in Thinking-Blöcken belassen](https://platform.claude.com/docs/de/build-with-claude/refusals-and-fallback#keep-reasoning-in-thinking-blocks).

**Token-Limit erreicht** (`stop_reason: "max_tokens"`)

Wenn die Antwort abgeschnitten wird, weil das `max_tokens`-Limit erreicht wurde:

* Die Antwort hat `stop_reason: "max_tokens"`
* Die Ausgabe ist möglicherweise unvollständig und entspricht nicht deinem Schema
* Wiederhole die Anfrage mit einem höheren `max_tokens`-Wert, um die vollständige strukturierte Ausgabe zu erhalten

**Groß-/Kleinschreibung von Enum-Werten**

Strukturierte Ausgaben garantieren nicht die Groß-/Kleinschreibung von String-`enum`- und `const`-Werten: Claude kann einen Wert zurückgeben, der sich von deinem Schema nur in der Groß-/Kleinschreibung unterscheidet, typischerweise beim ersten Buchstaben eines Wortes nach einem Leerzeichen. Zum Beispiel bei diesem Schema:

```json
{
  "type": "string",
  "enum": ["Conversation Topic 1", "Conversation Topic 2", "Conversation topic 3"]
}
```

Die Ausgabe kann `"Conversation Topic 3"` (großes „T“) enthalten, obwohl dieser exakte Wert nicht im Enum steht. Die Antwort wird normal abgeschlossen, ohne Fehler und ohne speziellen `stop_reason`. Das gilt sowohl für JSON-Ausgaben als auch für strikte Tool-Nutzung. Vergleiche Enum-Werte ohne Berücksichtigung der Groß-/Kleinschreibung und vermeide Enum-Werte, die sich nur in der Groß-/Kleinschreibung unterscheiden.

### Grenzen der Schema-Komplexität

Strukturierte Ausgaben funktionieren, indem deine JSON-Schemas in eine Grammatik kompiliert werden, die Claudes Ausgabe einschränkt. Komplexere Schemas erzeugen größere Grammatiken, deren Kompilierung länger dauert. Zum Schutz vor übermäßigen Kompilierungszeiten setzt die API mehrere Komplexitätsgrenzen durch.

#### Explizite Grenzen

Die folgenden Grenzen gelten für alle Anfragen mit `output_config.format` oder `strict: true`:

| Grenze                    | Wert | Beschreibung                                                                                                                                                                                                                     |
| ------------------------- | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Strikte Tools pro Anfrage | 20   | Maximale Anzahl von Tools mit `strict: true`. Nicht-strikte Tools zählen nicht zu dieser Grenze.                                                                                                                                 |
| Optionale Parameter       | 24   | Gesamtzahl optionaler Parameter über alle strikten Tool-Schemas und JSON-Ausgabe-Schemas hinweg. Jeder Parameter, der nicht in `required` aufgeführt ist, zählt zu dieser Grenze.                                                |
| Parameter mit Union-Typen | 16   | Gesamtzahl der Parameter, die `anyOf` oder Typ-Arrays (zum Beispiel `"type": ["string", "null"]`) über alle strikten Schemas hinweg verwenden. Diese sind besonders teuer, da sie exponentielle Kompilierungskosten verursachen. |

<Note>
  Diese Grenzen gelten für die kombinierte Gesamtsumme über alle strikten Schemas in einer einzelnen Anfrage. Wenn du zum Beispiel 4 strikte Tools mit jeweils 6 optionalen Parametern hast, erreichst du die Grenze von 24 Parametern, obwohl kein einzelnes Tool komplex erscheint.
</Note>

#### Zusätzliche interne Grenzen

Über die expliziten Grenzen in der vorstehenden Tabelle hinaus gibt es zusätzliche interne Grenzen für die Größe der kompilierten Grammatik. Diese Grenzen existieren, weil sich Schema-Komplexität nicht auf eine einzige Dimension reduzieren lässt: Funktionen wie optionale Parameter, Union-Typen, verschachtelte Objekte und die Anzahl der Tools interagieren auf eine Weise miteinander, die die kompilierte Grammatik unverhältnismäßig groß machen kann.

Wenn diese Grenzen überschritten werden, erhältst du einen 400-Fehler mit der Meldung „Schema is too complex for compilation.“ Diese Fehler bedeuten, dass die kombinierte Komplexität deiner Schemas das übersteigt, was effizient kompiliert werden kann, selbst wenn jede einzelne Grenze in der vorstehenden Tabelle eingehalten wird. Als letzte Absicherung setzt die API außerdem ein **Kompilierungs-Timeout von 180 Sekunden** durch. Schemas, die alle expliziten Prüfungen bestehen, aber sehr große kompilierte Grammatiken erzeugen, können dieses Timeout erreichen.

#### Tipps zur Reduzierung der Schema-Komplexität

Wenn du an Komplexitätsgrenzen stößt, probiere diese Strategien in dieser Reihenfolge:

1. **Markiere nur kritische Tools als strikt.** Wenn du viele Tools hast, reserviere dies für Tools, bei denen Schema-Verletzungen echte Probleme verursachen, und verlasse dich bei einfacheren Tools auf Claudes natürliche Einhaltung.

2. **Reduziere optionale Parameter.** Mache Parameter wo möglich `required`. Jeder optionale Parameter verdoppelt ungefähr einen Teil des Zustandsraums der Grammatik. Wenn ein Parameter immer einen sinnvollen Standardwert hat, erwäge, ihn erforderlich zu machen und Claude diesen Standardwert explizit angeben zu lassen.

3. **Vereinfache verschachtelte Strukturen.** Tief verschachtelte Objekte mit optionalen Feldern potenzieren die Komplexität. Flache Strukturen wo möglich ab.

4. **Teile in mehrere Anfragen auf.** Wenn du viele strikte Tools hast, erwäge, sie auf separate Anfragen oder Sub-Agenten aufzuteilen.

Bei anhaltenden Problemen mit gültigen Schemas [kontaktiere den Support](https://support.claude.com/en/articles/9015913-how-to-get-support) mit deiner Schema-Definition.

## Migration von der Beta

Der Parameter `output_format` wurde nach `output_config.format` verschoben, und Beta-Header sind nicht mehr erforderlich. Der Parameter `output_format` ist abgekündigt und wird in Zukunft entfernt. Um ihn dennoch zu verwenden, füge den Beta-Header `structured-outputs-2025-11-13` hinzu. Ohne ihn gibt die API einen 400-Fehler zurück.

Das Python-SDK (v1.0 und höher) akzeptiert `output_format={...}` bei `client.beta.messages.create()` oder `count_tokens()` nicht und löst einen `TypeError` aus. Verwende stattdessen `output_config`. Siehe [Ein rohes JSON-Schema verwenden](https://platform.claude.com/docs/de/build-with-claude/structured-outputs#using-a-raw-json-schema) für die aktualisierte API-Form.

## Datenaufbewahrung

Prompts und Antworten werden bei der Verwendung strukturierter Ausgaben mit ZDR verarbeitet. Das JSON-Schema selbst wird jedoch zu Optimierungszwecken vorübergehend für bis zu 24 Stunden seit der letzten Verwendung gecacht. Über die API-Antwort hinaus werden keine Prompt- oder Antwortdaten aufbewahrt.

Strukturierte Ausgaben sind HIPAA-fähig, aber **PHI darf nicht in JSON-Schema-Definitionen enthalten sein**. Die API kompiliert JSON-Schemas in Grammatiken, die getrennt vom Nachrichteninhalt gecacht werden, und diese gecachten Schemas erhalten nicht denselben PHI-Schutz wie Prompts und Antworten. Füge keine PHI in Schema-Property-Namen, `enum`-Werte, `const`-Werte oder reguläre Ausdrücke in `pattern` ein. PHI sollte nur im Nachrichteninhalt (Prompts und Antworten) erscheinen, wo es durch HIPAA-Schutzmaßnahmen geschützt ist.

Zur ZDR- und HIPAA-Fähigkeit über alle Funktionen hinweg siehe [API und Datenaufbewahrung](https://platform.claude.com/docs/de/manage-claude/api-and-data-retention).

## Funktionskompatibilität

**Funktioniert mit:**

* **[Batch-Verarbeitung](https://platform.claude.com/docs/de/build-with-claude/batch-processing):** Verarbeite strukturierte Ausgaben in großem Umfang mit 50 % Rabatt
* **[Token-Zählung](https://platform.claude.com/docs/de/build-with-claude/token-counting):** Zähle Token ohne Kompilierung
* **[Streaming](https://platform.claude.com/docs/de/build-with-claude/streaming):** Streame strukturierte Ausgaben wie normale Antworten
* **[Kombinierte Verwendung](https://platform.claude.com/docs/de/build-with-claude/structured-outputs#using-both-features-together):** Verwende JSON-Ausgaben (`output_config.format`) und strikte Tool-Nutzung (`strict: true`) zusammen in derselben Anfrage

**Inkompatibel mit:**

* **[Zitate](https://platform.claude.com/docs/de/build-with-claude/citations):** Zitate erfordern das Verschachteln von Zitatblöcken mit Text, was mit strikten JSON-Schema-Constraints kollidiert. Gibt einen 400-Fehler zurück, wenn Zitate mit `output_config.format` aktiviert sind.
* **Message Prefilling:** Inkompatibel mit JSON-Ausgaben

<Tip>
  **Geltungsbereich der Grammatik:** Grammatiken gelten nur für Claudes direkte Ausgabe, nicht für Tool-Nutzungsaufrufe, Tool-Ergebnisse oder Thinking-Tags (bei Verwendung von [Thinking](https://platform.claude.com/docs/de/build-with-claude/thinking)). Der Grammatikzustand wird zwischen Abschnitten zurückgesetzt, sodass Claude frei denken kann und dennoch in der endgültigen Antwort strukturierte Ausgaben erzeugt.
</Tip>

## Nächste Schritte

<CardGroup cols={2}>
  <Card title="Zitate" icon="book-bookmark" href="https://platform.claude.com/docs/de/build-with-claude/citations">
    Lass Claude seine Quellen zitieren, wenn es Fragen zu bereitgestellten Dokumenten beantwortet.
  </Card>

  <Card title="Strikte Tool-Nutzung" icon="check" href="https://platform.claude.com/docs/de/agents-and-tools/tool-use/strict-tool-use">
    Setze die JSON-Schema-Konformität von Claudes Tool-Eingaben mit grammatikbeschränktem Sampling durch.
  </Card>

  <Card title="Tool-Nutzung mit Claude" icon="wrench" href="https://platform.claude.com/docs/de/agents-and-tools/tool-use/overview">
    Verbinde Claude mit externen Tools und APIs. Erfahre, wo Tools ausgeführt werden und wie die agentische Schleife funktioniert.
  </Card>

  <Card title="Preise" icon="calculator" href="https://platform.claude.com/docs/de/about-claude/pricing">
    Erfahre mehr über Anthropics Preisstruktur für Modelle und Funktionen.
  </Card>
</CardGroup>
