---
title: SDK Java
url: https://platform.claude.com/docs/it/cli-sdks-libraries/sdks/java
description: Installa e configura l'SDK Java di Anthropic con pattern builder e supporto asincrono
---

L'SDK Java di Anthropic fornisce un accesso comodo alla Claude API da applicazioni scritte in Java. Utilizza il "builder pattern" (pattern builder) per creare le richieste e supporta operazioni sia sincrone che asincrone.

<Info>
  Per la documentazione delle funzionalità dell'API con esempi di codice, consulta il [riferimento API](https://platform.claude.com/docs/it/api/overview). Questa pagina tratta le funzionalità e la configurazione dell'SDK specifiche per Java.
</Info>

## Installazione

<Tabs>
  <Tab title="Gradle">
    ```kotlin
    implementation("com.anthropic:anthropic-java:2.73.0")
    ```
  </Tab>

  <Tab title="Maven">
    ```xml
    <dependency>
        <groupId>com.anthropic</groupId>
        <artifactId>anthropic-java</artifactId>
        <version>2.73.0</version>
    </dependency>
    ```
  </Tab>
</Tabs>

## Requisiti

Questa libreria richiede Java 8 o versioni successive.

<Note>
  L'SDK supporta Java 8 e versioni successive. Gli esempi di codice in questa documentazione sono scritti come [file sorgente compatti JDK 25](https://openjdk.org/jeps/512), utilizzando un punto di ingresso `void main()` essenziale e `IO.println()` per l'output. Le chiamate API in sé sono identiche su ogni JDK supportato; per compilare un esempio su una versione precedente, sostituisci `IO.println(...)` con `System.out.println(...)` e inserisci il corpo all'interno di `public static void main(String[] args)` dentro una classe.
</Note>

## Avvio rapido

```java
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;

// Configura usando le proprietà di sistema `anthropic.apiKey`, `anthropic.authToken` e `anthropic.baseUrl`
// Oppure configura usando le variabili d'ambiente `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN` e `ANTHROPIC_BASE_URL`
AnthropicClient client = AnthropicOkHttpClient.fromEnv();

MessageCreateParams params = MessageCreateParams.builder()
  .maxTokens(1024L)
  .addUserMessage("Hello, Claude")
  .model(Model.CLAUDE_OPUS_5_5)
  .build();

Message message = client.messages().create(params);
```

## Configurazione del client

### Configurazione della chiave API

Configura il client utilizzando proprietà di sistema o variabili d'ambiente:

```java
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

// Configura usando le proprietà di sistema `anthropic.apiKey`, `anthropic.authToken` e `anthropic.baseUrl`
// Oppure configura usando le variabili d'ambiente `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN` e `ANTHROPIC_BASE_URL`
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
```

Oppure configuralo manualmente:

```java
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

AnthropicClient client = AnthropicOkHttpClient.builder()
  .apiKey("my-anthropic-api-key")
  .build();
```

Oppure usa una combinazione di entrambi gli approcci:

```java
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

AnthropicClient client = AnthropicOkHttpClient.builder()
  // Configura tramite proprietà di sistema o variabili d'ambiente
  .fromEnv()
  .apiKey("my-anthropic-api-key")
  .build();
```

Per le opzioni di autenticazione, inclusa la Workload Identity Federation, consulta [Autenticazione](https://platform.claude.com/docs/it/manage-claude/authentication). Se la tua chiave API è una [chiave personale o di account di servizio](https://platform.claude.com/docs/it/manage-claude/authentication#key-types) con accesso a più workspace, imposta l'ID del workspace nell'header di richiesta `anthropic-workspace-id`; [Seleziona un workspace](https://platform.claude.com/docs/it/manage-claude/authentication#select-a-workspace) mostra l'opzione per singola richiesta per questo SDK.

### Opzioni di configurazione

| Setter      | Proprietà di sistema  | Variabile d'ambiente   | Obbligatorio | Valore predefinito            |
| ----------- | --------------------- | ---------------------- | ------------ | ----------------------------- |
| `apiKey`    | `anthropic.apiKey`    | `ANTHROPIC_API_KEY`    | false        | -                             |
| `authToken` | `anthropic.authToken` | `ANTHROPIC_AUTH_TOKEN` | false        | -                             |
| `baseUrl`   | `anthropic.baseUrl`   | `ANTHROPIC_BASE_URL`   | true         | `"https://api.anthropic.com"` |

Le proprietà di sistema hanno la precedenza sulle variabili d'ambiente.

<Tip>
  Non creare più di un client nella stessa applicazione. Ogni client dispone di un pool di connessioni e di pool di thread, che è più efficiente condividere tra le richieste.
</Tip>

### Modifica della configurazione

Per utilizzare temporaneamente una configurazione del client modificata riutilizzando gli stessi pool di connessioni e di thread, chiama `withOptions()` su qualsiasi client o servizio:

```java
import com.anthropic.client.AnthropicClient;

AnthropicClient clientWithOptions = client.withOptions(optionsBuilder -> {
  optionsBuilder.baseUrl("https://example.com");
  optionsBuilder.maxRetries(42);
});
```

Il metodo `withOptions()` non influisce sul client o servizio originale.

## Utilizzo asincrono

Il client predefinito è sincrono. Per passare all'esecuzione asincrona, chiama il metodo `async()`:

```java
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;

AnthropicClient client = AnthropicOkHttpClient.fromEnv();

MessageCreateParams params = MessageCreateParams.builder()
  .maxTokens(1024L)
  .addUserMessage("Hello, Claude")
  .model(Model.CLAUDE_OPUS_5_5)
  .build();

CompletableFuture<Message> message = client.async().messages().create(params);
```

Oppure crea un client asincrono fin dall'inizio:

```java
import com.anthropic.client.AnthropicClientAsync;
import com.anthropic.client.okhttp.AnthropicOkHttpClientAsync;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;

AnthropicClientAsync client = AnthropicOkHttpClientAsync.fromEnv();

MessageCreateParams params = MessageCreateParams.builder()
  .maxTokens(1024L)
  .addUserMessage("Hello, Claude")
  .model(Model.CLAUDE_OPUS_5_5)
  .build();

CompletableFuture<Message> message = client.messages().create(params);
```

Il client asincrono supporta le stesse opzioni di quello sincrono, tranne per il fatto che la maggior parte dei metodi restituisce dei `CompletableFuture`.

## Streaming

L'SDK definisce metodi che restituiscono stream di "chunk" (frammenti) di risposta, in cui ogni chunk può essere elaborato singolarmente non appena arriva, invece di attendere la risposta completa.

### Streaming sincrono

Questi metodi di streaming restituiscono `StreamResponse` per i client sincroni:

```java
import com.anthropic.core.http.StreamResponse;
import com.anthropic.models.messages.RawMessageStreamEvent;

try (StreamResponse<RawMessageStreamEvent> streamResponse = client.messages().createStreaming(params)) {
    streamResponse.stream().forEach(chunk -> {
        IO.println(chunk);
    });
    IO.println("No more chunks!");
}
```

### Streaming asincrono

Per i client asincroni, il metodo restituisce `AsyncStreamResponse`:

```java
import com.anthropic.core.http.AsyncStreamResponse;
import com.anthropic.models.messages.RawMessageStreamEvent;

client.async().messages().createStreaming(params).subscribe(chunk -> {
    IO.println(chunk);
});

// Se devi gestire errori o il completamento dello stream
client.async().messages().createStreaming(params).subscribe(new AsyncStreamResponse.Handler<>() {
    @Override
    public void onNext(RawMessageStreamEvent chunk) {
        IO.println(chunk);
    }

    @Override
    public void onComplete(Optional<Throwable> error) {
        if (error.isPresent()) {
            IO.println("Something went wrong!");
            throw new RuntimeException(error.get());
        } else {
            IO.println("No more chunks!");
        }
    }
});

// Oppure usa i future
client.async().messages().createStreaming(params)
    .subscribe(chunk -> {
        IO.println(chunk);
    })
    .onCompleteFuture()
    .whenComplete((unused, error) -> {
        if (error != null) {
            IO.println("Something went wrong!");
            throw new RuntimeException(error);
        } else {
            IO.println("No more chunks!");
        }
    });
```

Lo streaming asincrono utilizza un `Executor` dedicato per client, basato su un cached thread pool, per eseguire lo streaming senza bloccare il thread corrente. Per usare un `Executor` diverso:

```java
Executor executor = Executors.newFixedThreadPool(4);
client.async().messages().createStreaming(params).subscribe(
    chunk -> IO.println(chunk), executor
);
```

Oppure configura il client globalmente utilizzando il metodo `streamHandlerExecutor`:

```java
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

AnthropicClient client = AnthropicOkHttpClient.builder()
  .fromEnv()
  .streamHandlerExecutor(Executors.newFixedThreadPool(4))
  .build();
```

### Streaming con accumulatore di messaggi

Un `MessageAccumulator` può registrare lo stream di eventi nella risposta man mano che vengono elaborati e accumulare un oggetto `Message` simile a quello che sarebbe stato restituito dall'API non in streaming.

Per una risposta sincrona, aggiungi una chiamata `Stream.peek()` alla pipeline dello stream per accumulare ogni evento:

```java
import com.anthropic.core.http.StreamResponse;
import com.anthropic.helpers.MessageAccumulator;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.RawMessageStreamEvent;

MessageAccumulator messageAccumulator = MessageAccumulator.create();

try (StreamResponse<RawMessageStreamEvent> streamResponse =
         client.messages().createStreaming(createParams)) {
    streamResponse.stream()
            .peek(messageAccumulator::accumulate)
            .flatMap(event -> event.contentBlockDelta().stream())
            .flatMap(deltaEvent -> deltaEvent.delta().text().stream())
            .forEach(textDelta -> IO.print(textDelta.text()));
}

Message message = messageAccumulator.message();
```

Per una risposta asincrona, aggiungi il `MessageAccumulator` alla chiamata `subscribe()`:

```java
import com.anthropic.helpers.MessageAccumulator;
import com.anthropic.models.messages.Message;

MessageAccumulator messageAccumulator = MessageAccumulator.create();

client.async().messages()
        .createStreaming(createParams)
        .subscribe(event -> messageAccumulator.accumulate(event).contentBlockDelta().stream()
                .flatMap(deltaEvent -> deltaEvent.delta().text().stream())
                .forEach(textDelta -> IO.print(textDelta.text())))
        .onCompleteFuture()
        .join();

Message message = messageAccumulator.message();
```

È disponibile anche un `BetaMessageAccumulator` per l'accumulo di un oggetto `BetaMessage`. Si utilizza nello stesso modo del `MessageAccumulator`.

## Output strutturati

Per la documentazione completa sugli output strutturati, inclusi esempi Java, consulta [Output strutturati](https://platform.claude.com/docs/it/build-with-claude/structured-outputs).

## Uso degli strumenti

L'[uso degli strumenti con Claude](https://platform.claude.com/docs/it/agents-and-tools/tool-use/overview) ("tool use") ti consente di integrare strumenti e funzioni esterne direttamente nelle risposte del modello di IA. Invece di produrre testo semplice, il modello può generare istruzioni (con parametri) per chiamare uno strumento o una funzione quando appropriato. Tu definisci gli schemi JSON per gli strumenti e il modello utilizza gli schemi per determinare quando e come usare questi strumenti.

La funzionalità di uso degli strumenti supporta una modalità "strict" che garantisce che l'output JSON del modello di IA sia conforme allo schema JSON fornito nei parametri di input.

L'SDK può derivare automaticamente uno strumento e i suoi parametri dalla struttura di una classe Java arbitraria: il nome della classe (convertito in snake case) fornisce il nome dello strumento e i campi della classe definiscono i parametri dello strumento.

<Note>
  Dichiara le tue classi di strumenti come classi di primo livello o classi annidate `static`. Questo requisito deriva dalla libreria Jackson Databind (`com.fasterxml.jackson.databind`), che l'SDK utilizza per deserializzare gli input degli strumenti in istanze delle tue classi e che non può istanziare classi interne non statiche.
</Note>

### Definizione degli strumenti con annotazioni

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

enum Unit {
  CELSIUS,
  FAHRENHEIT;

  public String toString() {
    return switch (this) {
      case CELSIUS -> "C";
      case FAHRENHEIT -> "F";
    };
  }

  public double fromKelvin(double temperatureK) {
    return switch (this) {
      case CELSIUS -> temperatureK - 273.15;
      case FAHRENHEIT -> (temperatureK - 273.15) * 1.8 + 32.0;
    };
  }
}

@JsonClassDescription("Get the weather in a given location")
static class GetWeather {

  @JsonPropertyDescription("The city and state, e.g. San Francisco, CA")
  public String location;

  @JsonPropertyDescription("The unit of temperature")
  public Unit unit;

  public Weather execute() {
    double temperatureK = switch (location) {
      case "San Francisco, CA" -> 300.0;
      case "New York, NY" -> 310.0;
      case "Dallas, TX" -> 305.0;
      default -> 295;
    };
    return new Weather(String.format("%.0f%s", unit.fromKelvin(temperatureK), unit));
  }
}

static class Weather {

  public String temperature;

  public Weather(String temperature) {
    this.temperature = temperature;
  }
}
```

### Chiamata degli strumenti

Una volta definite le classi degli strumenti, aggiungile ai parametri del messaggio utilizzando `MessageCreateParams.Builder.addTool(Class<T>)` e poi chiamale se richiesto nella risposta del modello di IA. `BetaToolUseBlock.input(Class<T>)` può essere utilizzato per convertire i parametri di uno strumento in formato JSON in un'istanza della classe che definisce lo strumento.

Dopo aver chiamato lo strumento, usa `BetaToolResultBlockParam.Builder.contentAsJson(Object)` per restituire il risultato dello strumento al modello di IA:

```java
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.beta.messages.*;
import com.anthropic.models.messages.Model;

AnthropicClient client = AnthropicOkHttpClient.fromEnv();

MessageCreateParams.Builder createParamsBuilder = MessageCreateParams.builder()
        .model(Model.CLAUDE_OPUS_5_5)
        .maxTokens(2048)
        .addTool(GetWeather.class)
        .addUserMessage("What's the temperature in New York?");

client.beta().messages().create(createParamsBuilder.build()).content().stream()
        .flatMap(contentBlock -> contentBlock.toolUse().stream())
        .forEach(toolUseBlock -> createParamsBuilder
              // Aggiungi un messaggio che indica che è stato richiesto l'uso degli strumenti.
              .addAssistantMessageOfBetaContentBlockParams(
                      List.of(BetaContentBlockParam.ofToolUse(BetaToolUseBlockParam.builder()
                              .name(toolUseBlock.name())
                              .id(toolUseBlock.id())
                              .input(toolUseBlock._input())
                              .build())))
              // Aggiungi un messaggio con il risultato dell'uso degli strumenti richiesto.
              .addUserMessageOfBetaContentBlockParams(
                      List.of(BetaContentBlockParam.ofToolResult(BetaToolResultBlockParam.builder()
                              .toolUseId(toolUseBlock.id())
                              .contentAsJson(callTool(toolUseBlock))
                              .build()))));

client.beta().messages().create(createParamsBuilder.build()).content().stream()
        .flatMap(contentBlock -> contentBlock.text().stream())
        .forEach(textBlock -> IO.println(textBlock.text()));

private static Object callTool(BetaToolUseBlock toolUseBlock) {
  if (!"get_weather".equals(toolUseBlock.name())) {
    throw new IllegalArgumentException("Unknown tool: " + toolUseBlock.name());
  }

  GetWeather tool = toolUseBlock.input(GetWeather.class);
  return tool != null ? tool.execute() : new Weather("unknown");
}
```

### Conversione dei nomi degli strumenti

I nomi degli strumenti derivano dai nomi delle classi degli strumenti in camel case (ad esempio, `GetWeather`) e vengono convertiti in snake case (ad esempio, `get_weather`). I confini tra le parole iniziano dove il carattere corrente non è il primo carattere, è maiuscolo e il carattere precedente è minuscolo oppure il carattere successivo è minuscolo. Ad esempio, `MyJSONParser` diventa `my_json_parser` e `ParseJSON` diventa `parse_json`. Questa conversione può essere sovrascritta utilizzando l'annotazione `@JsonTypeName`.

### Validazione locale dello schema JSON degli strumenti

Puoi eseguire una validazione locale per verificare che lo schema JSON derivato dalla tua classe di strumento rispetti le restrizioni di Anthropic. La validazione locale è abilitata per impostazione predefinita, ma può essere disabilitata:

```java
MessageCreateParams.Builder createParamsBuilder = MessageCreateParams.builder()
  .model(Model.CLAUDE_OPUS_5_5)
  .maxTokens(2048)
  .addTool(GetWeather.class, JsonSchemaLocalValidation.NO)
  .addUserMessage("What's the temperature in New York?");
```

### Annotazione delle classi degli strumenti

Puoi usare le annotazioni per aggiungere ulteriori informazioni sugli strumenti agli schemi JSON:

* `@JsonClassDescription` - Aggiunge una descrizione a una classe di strumento che specifica quando e come usare quello strumento.
* `@JsonTypeName` - Imposta il nome dello strumento su un valore diverso dal nome semplice della classe convertito in snake case.
* `@JsonPropertyDescription` - Aggiunge una descrizione dettagliata a un parametro dello strumento.
* `@JsonIgnore` - Esclude un campo `public` o un metodo getter dallo schema JSON generato per i parametri di uno strumento.
* `@JsonProperty` - Include un campo o un metodo getter non `public` nello schema JSON generato per i parametri di uno strumento.

## Batch di messaggi

L'SDK fornisce supporto per l'[elaborazione batch](https://platform.claude.com/docs/it/build-with-claude/batch-processing) sotto il namespace `client.messages().batches()`. Consulta [Paginazione](https://platform.claude.com/docs/it/cli-sdks-libraries/sdks/java#pagination) per sapere come elencare e paginare i batch.

## Caricamento di file

L'SDK definisce metodi che accettano file tramite la classe `MultipartField`:

```java
import com.anthropic.core.MultipartField;
import com.anthropic.models.files.FileMetadata;
import com.anthropic.models.files.FileUploadParams;

FileUploadParams params = FileUploadParams.builder()
  .file(
    MultipartField.<InputStream>builder()
      .value(Files.newInputStream(Paths.get("/path/to/file.pdf")))
      .contentType("application/pdf")
      .build()
  )
  .build();

FileMetadata fileMetadata = client.files().upload(params);
```

Oppure da un `InputStream`:

```java
import com.anthropic.core.MultipartField;
import com.anthropic.models.files.FileMetadata;
import com.anthropic.models.files.FileUploadParams;

FileUploadParams params = FileUploadParams.builder()
  .file(
    MultipartField.<InputStream>builder()
      .value(URI.create("https://example.com/path/to/file").toURL().openStream())
      .filename("document.pdf")
      .contentType("application/pdf")
      .build()
  )
  .build();

FileMetadata fileMetadata = client.files().upload(params);
```

Oppure da byte in memoria:

```java
import com.anthropic.core.MultipartField;
import com.anthropic.models.files.FileMetadata;
import com.anthropic.models.files.FileUploadParams;

FileUploadParams params = FileUploadParams.builder()
  .file(
    MultipartField.<InputStream>builder()
      .value(new ByteArrayInputStream("content".getBytes()))
      .filename("document.txt")
      .contentType("text/plain")
      .build()
  )
  .build();

FileMetadata fileMetadata = client.files().upload(params);
```

### Risposte binarie

L'SDK definisce metodi che restituiscono risposte binarie per le risposte API che non vengono necessariamente interpretate come JSON:

```java
import com.anthropic.core.http.HttpResponse;

HttpResponse response = client.files().download("file_abc123");
```

Per salvare il contenuto della risposta in un file:

```java
import com.anthropic.core.http.HttpResponse;

try (HttpResponse response = client.files().download(params)) {
    Files.copy(
        response.body(),
        Paths.get(path),
        StandardCopyOption.REPLACE_EXISTING
    );
} catch (Exception e) {
    IO.println("Something went wrong!");
    throw new RuntimeException(e);
}
```

Oppure trasferisci il contenuto della risposta a qualsiasi `OutputStream`:

```java
import com.anthropic.core.http.HttpResponse;

try (HttpResponse response = client.files().download(params)) {
    response.body().transferTo(Files.newOutputStream(Paths.get(path)));
} catch (Exception e) {
    IO.println("Something went wrong!");
    throw new RuntimeException(e);
}
```

## Gestione degli errori

L'SDK lancia tipi di eccezioni unchecked personalizzate:

* `AnthropicServiceException` - Classe base per gli errori HTTP.
* `AnthropicIoException` - Errori di rete I/O.
* `AnthropicRetryableException` - Errore generico che indica un fallimento che potrebbe essere ritentato.
* `AnthropicInvalidDataException` - Impossibilità di interpretare dati analizzati con successo (ad esempio, quando si accede a una proprietà che dovrebbe essere obbligatoria, ma che l'API ha inaspettatamente omesso).
* `AnthropicException` - Classe base per tutte le eccezioni.

### Mappatura dei codici di stato

| Stato | Eccezione                       |
| ----- | ------------------------------- |
| 400   | `BadRequestException`           |
| 401   | `UnauthorizedException`         |
| 403   | `PermissionDeniedException`     |
| 404   | `NotFoundException`             |
| 422   | `UnprocessableEntityException`  |
| 429   | `RateLimitException`            |
| 5xx   | `InternalServerException`       |
| altri | `UnexpectedStatusCodeException` |

`SseException` viene lanciata per gli errori riscontrati durante lo streaming SSE dopo una risposta HTTP iniziale riuscita.

```java
import com.anthropic.errors.*;

try {
    Message message = client.messages().create(params);
} catch (RateLimitException e) {
    IO.println("Rate limited, retry after: " + e.headers());
} catch (UnauthorizedException e) {
    IO.println("Invalid API key");
} catch (AnthropicServiceException e) {
    IO.println("API error: " + e.statusCode());
} catch (AnthropicIoException e) {
    IO.println("Network error: " + e.getMessage());
}
```

## ID delle richieste

Quando utilizzi le [risposte raw](https://platform.claude.com/docs/it/cli-sdks-libraries/sdks/java#raw-response-access), puoi accedere all'header di risposta `request-id` utilizzando il metodo `requestId()`:

```java
import com.anthropic.core.http.HttpResponseFor;
import com.anthropic.models.messages.Message;

HttpResponseFor<Message> message = client.messages().withRawResponse().create(params);

Optional<String> requestId = message.requestId();
```

Questo può essere utilizzato per registrare rapidamente le richieste non riuscite e segnalarle ad Anthropic. Per ulteriori informazioni sul debug delle richieste, consulta [ID della richiesta](https://platform.claude.com/docs/it/api/errors#request-id).

## Tentativi ripetuti

L'SDK ritenta automaticamente 2 volte per impostazione predefinita, con un breve backoff esponenziale tra le richieste.

Vengono ritentati solo i seguenti tipi di errore:

* Errori di connessione (ad esempio, a causa di un problema di connettività di rete)
* 408 Request Timeout
* 409 Conflict
* 429 Rate Limit (limite di velocità)
* 5xx Internal

L'API può anche istruire esplicitamente l'SDK a ritentare o non ritentare una richiesta.

Per impostare un numero personalizzato di tentativi, configura il client utilizzando il metodo `maxRetries`:

```java
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

AnthropicClient client = AnthropicOkHttpClient.builder().fromEnv().maxRetries(4).build();
```

## Timeout

Le richieste vanno in timeout dopo 10 minuti per impostazione predefinita.

Tuttavia, per i metodi che accettano `maxTokens`, se specifichi un valore `maxTokens` elevato e stai usando lo streaming, il timeout predefinito verrà calcolato dinamicamente utilizzando questa formula:

```java
Duration.ofSeconds(
    Math.min(
        60 * 60, // 1 hour max
        Math.max(
            10 * 60, // 10 minute minimum
            60 * 60 * maxTokens / 128_000
        )
    )
)
```

Questo si traduce in un timeout fino a 60 minuti, scalato in base al parametro `maxTokens`, a meno che non venga sovrascritto.

Per le richieste non in streaming, il timeout dinamico varia da un minimo di 30 secondi fino a un massimo di 10 minuti in base a `maxTokens`.

Per impostare un timeout personalizzato per singola richiesta:

```java
import com.anthropic.models.messages.Message;

Message message = client
  .messages()
  .create(params, RequestOptions.builder().timeout(Duration.ofSeconds(30)).build());
```

Oppure configura il valore predefinito per tutte le chiamate ai metodi a livello di client:

```java
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

AnthropicClient client = AnthropicOkHttpClient.builder()
  .fromEnv()
  .timeout(Duration.ofSeconds(30))
  .build();
```

## Richieste lunghe

<Warning>
  Valuta l'uso dello [streaming](https://platform.claude.com/docs/it/cli-sdks-libraries/sdks/java#streaming) per le richieste di lunga durata.
</Warning>

Evita di impostare un valore `maxTokens` elevato senza usare lo streaming. Alcune reti potrebbero interrompere le connessioni inattive dopo un certo periodo di tempo, il che può causare il fallimento della richiesta o un [timeout](https://platform.claude.com/docs/it/cli-sdks-libraries/sdks/java#timeouts) senza ricevere una risposta da Anthropic. L'SDK invia periodicamente ping all'API per mantenere attiva la connessione e ridurre l'impatto di queste reti.

L'SDK lancia un errore se si prevede che una richiesta non in streaming richieda più di 10 minuti. L'uso di un [metodo di streaming](https://platform.claude.com/docs/it/cli-sdks-libraries/sdks/java#streaming) o la [sovrascrittura del timeout](https://platform.claude.com/docs/it/cli-sdks-libraries/sdks/java#timeouts) a livello di client o di richiesta disabilita l'errore.

## Paginazione

L'SDK fornisce modi comodi per accedere ai risultati paginati, una pagina alla volta oppure elemento per elemento attraverso tutte le pagine.

### Paginazione automatica

Per iterare su tutti i risultati di tutte le pagine, usa il metodo `autoPager()`, che recupera automaticamente altre pagine secondo necessità.

```java
import com.anthropic.models.messages.batches.BatchListPage;
import com.anthropic.models.messages.batches.MessageBatch;

BatchListPage page = client.messages().batches().list();

// Elabora come Iterable
for (MessageBatch batch : page.autoPager()) {
    IO.println(batch);
}

// Elabora come Stream
page.autoPager()
    .stream()
    .limit(50)
    .forEach(batch -> IO.println(batch));
```

Quando si utilizza il client asincrono, il metodo restituisce un `AsyncStreamResponse`:

```java
import com.anthropic.core.http.AsyncStreamResponse;
import com.anthropic.models.messages.batches.BatchListPageAsync;
import com.anthropic.models.messages.batches.MessageBatch;

CompletableFuture<BatchListPageAsync> pageFuture = client.async().messages().batches().list();

pageFuture.thenAccept(page -> page.autoPager().subscribe(batch -> {
    IO.println(batch);
}));

// Se devi gestire errori o il completamento dello stream
pageFuture.thenAccept(page -> page.autoPager().subscribe(new AsyncStreamResponse.Handler<>() {
    @Override
    public void onNext(MessageBatch batch) {
        IO.println(batch);
    }

    @Override
    public void onComplete(Optional<Throwable> error) {
        if (error.isPresent()) {
            IO.println("Something went wrong!");
            throw new RuntimeException(error.get());
        } else {
            IO.println("No more!");
        }
    }
}));

// Oppure usa i future
pageFuture.thenAccept(page -> page.autoPager()
    .subscribe(batch -> {
        IO.println(batch);
    })
    .onCompleteFuture()
    .whenComplete((unused, error) -> {
        if (error != null) {
            IO.println("Something went wrong!");
            throw new RuntimeException(error);
        } else {
            IO.println("No more!");
        }
    }));
```

### Paginazione manuale

Per accedere ai singoli elementi della pagina e richiedere manualmente la pagina successiva:

```java
import com.anthropic.models.messages.batches.BatchListPage;
import com.anthropic.models.messages.batches.MessageBatch;

BatchListPage page = client.messages().batches().list();
while (true) {
    for (MessageBatch batch : page.items()) {
        IO.println(batch);
    }

    if (!page.hasNextPage()) {
        break;
    }

    page = page.nextPage();
}
```

## Sistema dei tipi

### Immutabilità e builder

Ogni classe nell'SDK ha un builder associato per costruirla. Ogni classe è immutabile una volta costruita. Se la classe ha un builder associato, allora dispone di un metodo `toBuilder()`, che può essere utilizzato per riconvertirla in un builder per creare una copia modificata.

```java
MessageCreateParams params = MessageCreateParams.builder()
  .maxTokens(1024L)
  .addUserMessage("Hello, Claude")
  .model(Model.CLAUDE_OPUS_5_5)
  .build();

// Crea una copia modificata usando toBuilder()
MessageCreateParams modified = params.toBuilder().maxTokens(2048L).build();
```

Poiché ogni classe è immutabile, la modifica del builder non influisce mai sulle istanze di classe già costruite.

### Richieste e risposte

Per inviare una richiesta alla Claude API, costruisci un'istanza di una classe `Params` e passala al metodo del client corrispondente. Quando la risposta viene ricevuta, viene deserializzata in un'istanza di una classe Java.

Ad esempio, `client.messages().create(...)` deve essere chiamato con un'istanza di `MessageCreateParams` e restituisce un'istanza di `Message`.

### Parametri non documentati

Per impostare parametri non documentati, chiama i metodi `putAdditionalHeader`, `putAdditionalQueryParam` o `putAdditionalBodyProperty` su qualsiasi classe `Params`:

```java
import com.anthropic.core.JsonValue;
import com.anthropic.models.messages.MessageCreateParams;

MessageCreateParams params = MessageCreateParams.builder()
  .putAdditionalHeader("Secret-Header", "42")
  .putAdditionalQueryParam("secret_query_param", "42")
  .putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))
  .build();
```

È possibile accedervi successivamente sull'oggetto costruito utilizzando i metodi `_additionalHeaders()`, `_additionalQueryParams()` e `_additionalBodyProperties()`.

<Warning>
  I valori passati a questi metodi sovrascrivono i valori passati ai metodi precedenti. Per motivi di sicurezza, assicurati che questi metodi vengano utilizzati solo con dati di input attendibili.
</Warning>

Per impostare parametri non documentati su header, parametri di query o classi del body annidati:

```java
import com.anthropic.core.JsonValue;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Metadata;

MessageCreateParams params = MessageCreateParams.builder()
  .metadata(
    Metadata.builder().putAdditionalProperty("secretProperty", JsonValue.from("42")).build()
  )
  .build();
```

È possibile accedere a queste proprietà successivamente sull'oggetto annidato costruito utilizzando il metodo `_additionalProperties()`.

Per impostare un parametro o una proprietà documentata su un valore non documentato o non ancora supportato, passa un oggetto `JsonValue` al suo setter:

```java
import com.anthropic.core.JsonValue;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;

MessageCreateParams params = MessageCreateParams.builder()
  .maxTokens(JsonValue.from(3.14))
  .addUserMessage("Hello, Claude")
  .model(Model.CLAUDE_OPUS_5_5)
  .build();
```

### Creazione di JsonValue

Il modo più diretto per creare un `JsonValue` è utilizzare il suo metodo `from(...)`:

```java
import com.anthropic.core.JsonValue;

// Crea valori JSON primitivi
JsonValue nullValue = JsonValue.from(null);

JsonValue booleanValue = JsonValue.from(true);

JsonValue numberValue = JsonValue.from(42);

JsonValue stringValue = JsonValue.from("Hello World!");

// Crea un valore array JSON equivalente a `["Hello", "World"]`
JsonValue arrayValue = JsonValue.from(List.of("Hello", "World"));

// Crea un valore oggetto JSON equivalente a `{ "a": 1, "b": 2 }`
JsonValue objectValue = JsonValue.from(Map.of("a", 1, "b", 2));

// Crea un JSON annidato arbitrariamente equivalente a:
// { "a": [1, 2], "b": [3, 4] }
JsonValue complexValue = JsonValue.from(Map.of("a", List.of(1, 2), "b", List.of(3, 4)));
```

### Omissione forzata dei parametri obbligatori

Normalmente il metodo `build` di una classe `Builder` lancia `IllegalStateException` se un parametro o una proprietà obbligatoria non è impostata. Per omettere forzatamente un parametro o una proprietà obbligatoria, passa `JsonMissing`:

```java
import com.anthropic.core.JsonMissing;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;

MessageCreateParams params = MessageCreateParams.builder()
  .addUserMessage("Hello, world")
  .model(Model.CLAUDE_OPUS_5_5)
  .maxTokens(JsonMissing.of())
  .build();
```

### Proprietà della risposta

Per accedere alle proprietà non documentate della risposta, chiama il metodo `_additionalProperties()`:

```java
import com.anthropic.core.JsonValue;

Map<String, JsonValue> additionalProperties = client
  .messages()
  .create(params)
  ._additionalProperties();

JsonValue secretPropertyValue = additionalProperties.get("secretProperty");

String result = secretPropertyValue.accept(new JsonValue.Visitor<>() {
    @Override
    public String visitNull() {
        return "It's null!";
    }

    @Override
    public String visitBoolean(boolean value) {
        return "It's a boolean!";
    }

    @Override
    public String visitNumber(Number value) {
        return "It's a number!";
    }

    // Altri metodi includono `visitMissing`, `visitString`, `visitArray` e `visitObject`
    // L'implementazione predefinita di ogni metodo non implementato delega a `visitDefault`,
    // che per impostazione predefinita lancia un'eccezione, ma può anche essere sovrascritto
});
```

Per accedere al valore JSON raw di una proprietà, chiama il suo metodo con prefisso `_`:

```java
import com.anthropic.core.JsonField;
import com.anthropic.models.messages.StopReason;

JsonField<StopReason> stopReason = client.messages().create(params)._stopReason();

if (stopReason.isMissing()) {
  // La proprietà è assente dalla risposta JSON
} else if (stopReason.isNull()) {
  // La proprietà è stata impostata al valore letterale null
} else {
  // Verifica se il valore è stato fornito come stringa
  // Altri metodi includono `asNumber()`, `asBoolean()`, ecc.
  Optional<String> jsonString = stopReason.asString();

  // Prova a deserializzare in un tipo personalizzato
  MyClass myObject = stopReason.asUnknown().orElseThrow().convert(MyClass.class);
}
```

### Validazione della risposta

Per impostazione predefinita, l'SDK non lancia un'eccezione quando l'API restituisce una risposta che non corrisponde al tipo previsto. Lancia `AnthropicInvalidDataException` solo se accedi direttamente alla proprietà.

Per verificare in anticipo che la risposta sia completamente ben tipizzata, chiama `validate()`:

```java
import com.anthropic.models.messages.Message;

Message message = client.messages().create(params).validate();
```

Oppure configura per singola richiesta:

```java
import com.anthropic.models.messages.Message;

Message message = client
  .messages()
  .create(params, RequestOptions.builder().responseValidation(true).build());
```

Oppure configura il valore predefinito per tutte le chiamate ai metodi a livello di client:

```java
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

AnthropicClient client = AnthropicOkHttpClient.builder()
  .fromEnv()
  .responseValidation(true)
  .build();
```

## Personalizzazione del client HTTP

### Configurazione del proxy

```java
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import java.net.Proxy;

AnthropicClient client = AnthropicOkHttpClient.builder()
  .fromEnv()
  .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("https://example.com", 8080)))
  .build();
```

### Configurazione HTTPS / SSL

<Note>
  La maggior parte delle applicazioni non dovrebbe chiamare questi metodi, ma utilizzare invece le impostazioni predefinite di sistema. Le impostazioni predefinite includono ottimizzazioni speciali che possono andare perse se le implementazioni vengono modificate.
</Note>

```java
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

AnthropicClient client = AnthropicOkHttpClient.builder()
  .fromEnv()
  .sslSocketFactory(yourSSLSocketFactory)
  .trustManager(yourTrustManager)
  .hostnameVerifier(yourHostnameVerifier)
  .build();
```

### Client HTTP personalizzato

L'SDK è composto da tre artefatti:

* `anthropic-java-core` - Contiene la logica principale dell'SDK, non dipende da OkHttp. Espone `AnthropicClient`, `AnthropicClientAsync` e le relative classi di implementazione, tutte in grado di funzionare con qualsiasi client HTTP.
* `anthropic-java-client-okhttp` - Dipende da OkHttp. Espone `AnthropicOkHttpClient` e `AnthropicOkHttpClientAsync`.
* `anthropic-java` - Dipende da ed espone le API sia di `anthropic-java-core` che di `anthropic-java-client-okhttp`. Non ha una logica propria.

Questa struttura consente di sostituire il client HTTP predefinito dell'SDK senza includere dipendenze non necessarie.

#### OkHttpClient personalizzato

<Tip>
  Prova le [opzioni di rete](https://platform.claude.com/docs/it/cli-sdks-libraries/sdks/java#retries) disponibili prima di sostituire il client predefinito.
</Tip>

Per usare un `OkHttpClient` personalizzato:

1. Sostituisci la dipendenza `anthropic-java` con `anthropic-java-core`.
2. Copia la classe `OkHttpClient` di `anthropic-java-client-okhttp` nel tuo codice e personalizzala.
3. Costruisci `AnthropicClientImpl` o `AnthropicClientAsyncImpl` utilizzando il tuo client personalizzato.

#### Client HTTP completamente personalizzato

Per usare un client HTTP completamente personalizzato:

1. Sostituisci la dipendenza `anthropic-java` con `anthropic-java-core`.
2. Scrivi una classe che implementi l'interfaccia `HttpClient`.
3. Costruisci `AnthropicClientImpl` o `AnthropicClientAsyncImpl` utilizzando la tua nuova classe client.

## Integrazioni con le piattaforme

<Note>
  Per guide dettagliate alla configurazione delle piattaforme con esempi di codice, consulta:

  * [Amazon Bedrock](https://platform.claude.com/docs/it/build-with-claude/claude-in-amazon-bedrock)
  * [Amazon Bedrock (Opus 4.6 e precedenti)](https://platform.claude.com/docs/it/build-with-claude/claude-on-amazon-bedrock-legacy)
  * [Claude Platform on AWS](https://platform.claude.com/docs/it/build-with-claude/claude-platform-on-aws)
  * [Google Cloud](https://platform.claude.com/docs/it/build-with-claude/claude-on-vertex-ai)
  * [Microsoft Foundry](https://platform.claude.com/docs/it/build-with-claude/claude-in-microsoft-foundry)
</Note>

L'SDK Java supporta le seguenti piattaforme tramite dipendenze separate che forniscono implementazioni `Backend` specifiche per piattaforma:

* **Agent Platform:** `com.anthropic:anthropic-java-vertex`: Usa `VertexBackend.builder()` o `VertexBackend.fromEnv()`. `fromEnv()` legge `CLOUD_ML_REGION` e `ANTHROPIC_VERTEX_PROJECT_ID` e utilizza le Application Default Credentials.
* **Bedrock:** `com.anthropic:anthropic-java-bedrock`: Usa `BedrockMantleBackend.fromEnv()` o `BedrockMantleBackend.builder()` per l'endpoint Bedrock della Messages API, oppure `BedrockBackend.fromEnv()` / `BedrockBackend.builder()` (percorso `bedrock-runtime`).
* **Claude Platform on AWS:** `com.anthropic:anthropic-java-aws`: Usa `AwsBackend.fromEnv()` (legge `ANTHROPIC_AWS_WORKSPACE_ID` e la catena predefinita di regione/credenziali AWS) o `AwsBackend.builder()`. Disponibile in beta.
* **Foundry:** `com.anthropic:anthropic-java-foundry`: Usa `FoundryBackend.fromEnv()` o `FoundryBackend.builder()`.

Usa `BedrockMantleBackend` per i nuovi progetti; `BedrockBackend` rimane disponibile per le applicazioni esistenti che utilizzano l'API `InvokeModel` di Bedrock.

Gli artefatti delle piattaforme sono componenti aggiuntivi della dipendenza di base `com.anthropic:anthropic-java`, che fornisce `AnthropicOkHttpClient`, quindi installali entrambi. Ogni implementazione `Backend` viene passata al client con `.backend()` su `AnthropicOkHttpClient.builder()`. Ogni backend cloud include le classi dell'SDK della rispettiva piattaforma cloud come dipendenze transitive.

## Utilizzo avanzato

### Accesso alla risposta raw

Per accedere agli header HTTP, ai codici di stato e al body raw della risposta, anteponi `withRawResponse()` a qualsiasi chiamata di metodo HTTP:

```java
import com.anthropic.core.http.Headers;
import com.anthropic.core.http.HttpResponseFor;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;

MessageCreateParams params = MessageCreateParams.builder()
  .maxTokens(1024L)
  .addUserMessage("Hello, Claude")
  .model(Model.CLAUDE_OPUS_5_5)
  .build();

HttpResponseFor<Message> message = client.messages().withRawResponse().create(params);

int statusCode = message.statusCode();

Headers headers = message.headers();
```

Puoi comunque deserializzare la risposta in un'istanza di una classe Java se necessario:

```java
import com.anthropic.models.messages.Message;

Message parsedMessage = message.parse();
```

### Logging

L'SDK utilizza l'interceptor di logging standard di OkHttp.

Abilita il logging impostando la variabile d'ambiente `ANTHROPIC_LOG` su `info`:

```bash
export ANTHROPIC_LOG=info
```

Oppure su `debug` per un logging più dettagliato:

```bash
export ANTHROPIC_LOG=debug
```

<Accordion title="Compatibilità con Jackson">
  L'SDK dipende da Jackson per la serializzazione/deserializzazione JSON. È compatibile con la versione 2.13.4 o superiore, ma dipende dalla versione 2.19.4 per impostazione predefinita.

  L'SDK lancia un'eccezione se rileva una versione di Jackson incompatibile a runtime (ad esempio, se la versione predefinita è stata sovrascritta nella tua configurazione Maven o Gradle).

  Se l'SDK ha lanciato un'eccezione, ma sei certo che la versione sia compatibile, disabilita il controllo della versione utilizzando `checkJacksonVersionCompatibility` su `AnthropicOkHttpClient` o `AnthropicOkHttpClientAsync`.

  <Warning>
    Non vi è alcuna garanzia che l'SDK funzioni correttamente quando il controllo della versione di Jackson è disabilitato.
  </Warning>

  Esistono inoltre bug nelle versioni precedenti di Jackson che possono influire sull'SDK. L'SDK non aggira tutti i bug di Jackson e si aspetta invece che gli utenti aggiornino Jackson per risolverli.
</Accordion>

<Accordion title="Configurazione ProGuard/R8">
  Sebbene l'SDK utilizzi la reflection, è comunque utilizzabile con ProGuard e R8 perché `anthropic-java-core` è pubblicato con un file di configurazione contenente regole keep.

  ProGuard e R8 dovrebbero rilevare e utilizzare automaticamente le regole pubblicate, ma puoi anche copiare manualmente le regole keep se necessario.
</Accordion>

### Funzionalità API non documentate

L'SDK è tipizzato per un utilizzo comodo dell'API documentata. Tuttavia, supporta anche l'utilizzo di parti dell'API non documentate o non ancora supportate.

#### Parametri di richiesta non documentati

Per impostare parametri di richiesta non documentati, usa i metodi `putAdditionalHeader`, `putAdditionalQueryParam` o `putAdditionalBodyProperty` come descritto in [Parametri non documentati](https://platform.claude.com/docs/it/cli-sdks-libraries/sdks/java#undocumented-parameters).

#### Proprietà di risposta non documentate

Per accedere alle proprietà di risposta non documentate, usa il metodo `_additionalProperties()` come descritto in [Proprietà della risposta](https://platform.claude.com/docs/it/cli-sdks-libraries/sdks/java#response-properties).

#### Valori enum nuovi o non ancora rilasciati

Le classi simili a enum nell'SDK, come `Model` e `AnthropicBeta`, non sono tipi `enum` Java chiusi. Ognuna fornisce un metodo factory `of(String)` che accetta qualsiasi stringa, così puoi usare valori che non sono ancora stati aggiunti all'SDK, come un modello o un header beta rilasciato dopo la tua versione dell'SDK:

```java
import com.anthropic.models.beta.AnthropicBeta;
import com.anthropic.models.messages.Model;

Model model = Model.of("some-new-model");
AnthropicBeta beta = AnthropicBeta.of("some-new-beta-2026-01-01");
```

I metodi builder che accettano questi tipi spesso forniscono anche un overload `String` che chiama `of(...)` per te:

```java
import com.anthropic.models.messages.MessageCreateParams;

MessageCreateParams params = MessageCreateParams.builder()
  .model("some-new-model") // same as .model(Model.of("some-new-model"))
  .maxTokens(1024L)
  .addUserMessage("Hello, Claude")
  .build();
```

Preferisci le costanti ben tipizzate (ad esempio, `Model.CLAUDE_OPUS_5`) in modo da ottenere il completamento automatico e gli avvisi di deprecazione. Gli overload `String` e `of(...)` servono principalmente per impostare il campo su un valore non documentato o non ancora supportato in attesa di una versione dell'SDK che lo includa.

## Funzionalità beta

Le funzionalità beta sono disponibili prima del rilascio generale per raccogliere feedback anticipati e testare nuove funzionalità. Puoi verificare la disponibilità di tutte le capacità e gli strumenti di Claude nella [Panoramica delle funzionalità](https://platform.claude.com/docs/it/build-with-claude/overview).

Puoi accedere alla maggior parte delle funzionalità API beta tramite il metodo `beta()` sul client. Per abilitare una particolare funzionalità beta, aggiungi l'[header beta](https://platform.claude.com/docs/it/api/beta-headers) appropriato con `.addBeta()` durante la costruzione dei parametri del messaggio.

Ad esempio, per abilitare la [modifica del contesto](https://platform.claude.com/docs/it/build-with-claude/context-editing):

```java
import com.anthropic.models.beta.AnthropicBeta;
import com.anthropic.models.beta.messages.BetaMessage;
import com.anthropic.models.beta.messages.MessageCreateParams;
// ...
void main() {
    AnthropicClient client = AnthropicOkHttpClient.fromEnv();

    BetaMessage message = client.beta().messages().create(
        MessageCreateParams.builder()
            .model(Model.CLAUDE_OPUS_5_5)
            .maxTokens(1024L)
            .addBeta(AnthropicBeta.CONTEXT_MANAGEMENT_2025_06_27)
            .addUserMessage("Hello, Claude")
            .build());
}
```

## Domande frequenti

<AccordionGroup>
  <Accordion title="Perché l'SDK non usa semplici classi enum?">
    Le classi `enum` Java non sono banalmente compatibili in avanti. Il loro utilizzo nell'SDK potrebbe causare eccezioni a runtime se l'API venisse aggiornata per rispondere con un nuovo valore enum.

    Poiché queste classi sono aperte, puoi anche costruirle con qualsiasi valore stringa tramite il loro metodo factory `of(String)`. Consulta [Valori enum nuovi o non ancora rilasciati](https://platform.claude.com/docs/it/cli-sdks-libraries/sdks/java#new-or-unreleased-enum-values) se hai bisogno di usare un valore che non è ancora presente nella tua versione dell'SDK.
  </Accordion>

  <Accordion title="Perché i campi sono rappresentati usando JsonField<T> invece del semplice T?">
    L'uso di `JsonField<T>` abilita alcune funzionalità:

    * Consentire l'utilizzo di funzionalità API non documentate
    * Validare in modo lazy la risposta dell'API rispetto alla forma prevista
    * Rappresentare valori assenti rispetto a valori esplicitamente null
  </Accordion>

  <Accordion title="Perché l'SDK non usa data class?">
    Aggiungere nuovi campi a una data class non è retrocompatibile, e l'SDK evita di introdurre una modifica incompatibile ogni volta che viene aggiunto un campo a una classe.
  </Accordion>

  <Accordion title="Perché l'SDK non usa eccezioni checked?">
    Le eccezioni checked sono ampiamente considerate un errore nel linguaggio di programmazione Java. Infatti, sono state omesse da Kotlin per questo motivo.

    Le eccezioni checked:

    * Sono verbose da gestire
    * Incoraggiano la gestione degli errori al livello di astrazione sbagliato, dove non si può fare nulla riguardo all'errore
    * Sono tediose da propagare a causa del problema del function coloring
    * Non funzionano bene con le lambda (sempre a causa del problema del function coloring)
  </Accordion>
</AccordionGroup>

## Versionamento semantico

Questo pacchetto segue generalmente le convenzioni [SemVer](https://semver.org/spec/v2.0.0.html), anche se alcune modifiche non retrocompatibili potrebbero essere rilasciate come versioni minori:

1. Modifiche agli elementi interni della libreria che sono tecnicamente pubblici ma non destinati o documentati per l'uso esterno.
2. Modifiche che non si prevede abbiano un impatto sulla grande maggioranza degli utenti nella pratica.

## Risorse aggiuntive

* [Repository GitHub](https://github.com/anthropics/anthropic-sdk-java)
* [Javadocs](https://javadoc.io/doc/com.anthropic/anthropic-java)
* [Riferimento API](https://platform.claude.com/docs/it/api/overview)
* [Streaming dei messaggi](https://platform.claude.com/docs/it/build-with-claude/streaming)
* [Uso degli strumenti con Claude](https://platform.claude.com/docs/it/agents-and-tools/tool-use/overview)
