---
title: Java SDK
url: https://platform.claude.com/docs/ru/cli-sdks-libraries/sdks/java
description: Установка и настройка Anthropic Java SDK с шаблонами builder и поддержкой асинхронных операций
---

Anthropic Java SDK предоставляет удобный доступ к Claude API из приложений, написанных на Java. Он использует шаблон builder для создания запросов и поддерживает как синхронные, так и асинхронные операции.

<Info>
  Документацию по функциям API с примерами кода см. в [справочнике API](https://platform.claude.com/docs/ru/api/overview). На этой странице описаны функции и настройка SDK, специфичные для Java.
</Info>

## Установка

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

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

## Требования

Для этой библиотеки требуется Java 8 или более поздняя версия.

<Note>
  SDK поддерживает Java 8 и более поздние версии. Примеры кода в этой документации написаны как [компактные исходные файлы JDK 25](https://openjdk.org/jeps/512) с использованием простой точки входа `void main()` и `IO.println()` для вывода. Сами вызовы API идентичны во всех поддерживаемых JDK; чтобы скомпилировать пример в более ранней версии, замените `IO.println(...)` на `System.out.println(...)` и поместите тело внутрь `public static void main(String[] args)` в классе.
</Note>

## Быстрый старт

```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;

// Настраивает клиент с помощью системных свойств `anthropic.apiKey`, `anthropic.authToken` и `anthropic.baseUrl`
// Или настраивает клиент с помощью переменных окружения `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN` и `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);
```

## Настройка клиента

### Настройка ключа API

Настройте клиент с помощью системных свойств или переменных окружения:

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

// Настраивает клиент с помощью системных свойств `anthropic.apiKey`, `anthropic.authToken` и `anthropic.baseUrl`
// Или настраивает клиент с помощью переменных окружения `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN` и `ANTHROPIC_BASE_URL`
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
```

Или настройте вручную:

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

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

Или используйте комбинацию обоих подходов:

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

AnthropicClient client = AnthropicOkHttpClient.builder()
  // Настраивает с помощью системных свойств или переменных окружения
  .fromEnv()
  .apiKey("my-anthropic-api-key")
  .build();
```

Сведения о вариантах аутентификации, включая Workload Identity Federation, см. в разделе [Аутентификация](https://platform.claude.com/docs/ru/manage-claude/authentication). Если ваш ключ API является [ключом персональной или сервисной учётной записи](https://platform.claude.com/docs/ru/manage-claude/authentication#key-types), который не привязан к рабочему пространству, укажите идентификатор рабочего пространства в заголовке запроса `anthropic-workspace-id`; в разделе [Выбор рабочего пространства](https://platform.claude.com/docs/ru/manage-claude/authentication#select-a-workspace) показан вариант указания для каждого запроса в этом SDK.

### Параметры конфигурации

| Сеттер      | Системное свойство    | Переменная окружения   | Обязательный | Значение по умолчанию         |
| ----------- | --------------------- | ---------------------- | ------------ | ----------------------------- |
| `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"` |

Системные свойства имеют приоритет над переменными окружения.

<Tip>
  Не создавайте более одного клиента в одном приложении. Каждый клиент имеет пул соединений и пулы потоков, которые эффективнее использовать совместно между запросами.
</Tip>

### Изменение конфигурации

Чтобы временно использовать изменённую конфигурацию клиента, повторно используя те же пулы соединений и потоков, вызовите `withOptions()` для любого клиента или сервиса:

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

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

Метод `withOptions()` не влияет на исходный клиент или сервис.

## Асинхронное использование

Клиент по умолчанию является синхронным. Чтобы переключиться на асинхронное выполнение, вызовите метод `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);
```

Или создайте асинхронный клиент с самого начала:

```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);
```

Асинхронный клиент поддерживает те же параметры, что и синхронный, за исключением того, что большинство методов возвращают `CompletableFuture`.

## Потоковая передача

«Streaming» (потоковая передача): SDK определяет методы, которые возвращают потоки «фрагментов» ответа, где каждый фрагмент может быть обработан отдельно сразу по мере поступления, без ожидания полного ответа.

### Синхронная потоковая передача

Для синхронных клиентов эти методы потоковой передачи возвращают `StreamResponse`:

```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!");
}
```

### Асинхронная потоковая передача

Для асинхронных клиентов метод возвращает `AsyncStreamResponse`:

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

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

// Если нужно обработать ошибки или завершение потока
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!");
        }
    }
});

// Или используйте futures
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!");
        }
    });
```

Асинхронная потоковая передача использует выделенный для каждого клиента кэшированный пул потоков `Executor`, чтобы выполнять потоковую передачу без блокировки текущего потока. Чтобы использовать другой `Executor`:

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

Или настройте клиент глобально с помощью метода `streamHandlerExecutor`:

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

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

### Потоковая передача с аккумулятором сообщений

`MessageAccumulator` может записывать поток событий в ответе по мере их обработки и накапливать объект `Message`, аналогичный тому, который был бы возвращён API без потоковой передачи.

Для синхронного ответа добавьте вызов `Stream.peek()` в конвейер потока, чтобы накапливать каждое событие:

```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();
```

Для асинхронного ответа добавьте `MessageAccumulator` в вызов `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();
```

Также доступен `BetaMessageAccumulator` для накопления объекта `BetaMessage`. Он используется так же, как `MessageAccumulator`.

## Структурированные выходные данные

Полную документацию по структурированным выходным данным, включая примеры на Java, см. в разделе [Структурированные выходные данные](https://platform.claude.com/docs/ru/build-with-claude/structured-outputs).

## Использование инструментов

[Использование инструментов с Claude](https://platform.claude.com/docs/ru/agents-and-tools/tool-use/overview) («tool use», использование инструментов) позволяет интегрировать внешние инструменты и функции непосредственно в ответы модели ИИ. Вместо создания простого текста модель может при необходимости выводить инструкции (с параметрами) для вызова инструмента или функции. Вы определяете JSON-схемы для инструментов, а модель использует эти схемы, чтобы определить, когда и как использовать эти инструменты.

Функция использования инструментов поддерживает «строгий» режим, который гарантирует, что JSON-вывод модели ИИ будет соответствовать JSON-схеме, которую вы предоставляете во входных параметрах.

SDK может автоматически выводить инструмент и его параметры из структуры произвольного класса Java: имя класса (преобразованное в snake case) задаёт имя инструмента, а поля класса определяют параметры инструмента.

<Note>
  Объявляйте классы инструментов как классы верхнего уровня или как `static` вложенные классы. Это требование исходит от библиотеки Jackson Databind (`com.fasterxml.jackson.databind`), которую SDK использует для десериализации входных данных инструментов в экземпляры ваших классов и которая не может создавать экземпляры нестатических внутренних классов.
</Note>

### Определение инструментов с помощью аннотаций

```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;
  }
}
```

### Вызов инструментов

Когда классы инструментов определены, добавьте их в параметры сообщения с помощью `MessageCreateParams.Builder.addTool(Class<T>)`, а затем вызывайте их, если это запрошено в ответе модели ИИ. `BetaToolUseBlock.input(Class<T>)` можно использовать для разбора параметров инструмента в формате JSON в экземпляр вашего класса, определяющего инструмент.

После вызова инструмента используйте `BetaToolResultBlockParam.Builder.contentAsJson(Object)`, чтобы передать результат инструмента обратно модели ИИ:

```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
              // Добавляем сообщение о том, что было запрошено использование инструментов.
              .addAssistantMessageOfContentBlockParams(
                      List.of(BetaContentBlockParam.ofToolUse(BetaToolUseBlockParam.builder()
                              .name(toolUseBlock.name())
                              .id(toolUseBlock.id())
                              .input(toolUseBlock._input())
                              .build())))
              // Добавляем сообщение с результатом запрошенного использования инструментов.
              .addUserMessageOfContentBlockParams(
                      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");
}
```

### Преобразование имён инструментов

Имена инструментов выводятся из имён классов инструментов в camel case (например, `GetWeather`) и преобразуются в snake case (например, `get_weather`). Границы слов начинаются там, где текущий символ не является первым, находится в верхнем регистре и либо предыдущий символ находится в нижнем регистре, либо следующий символ находится в нижнем регистре. Например, `MyJSONParser` становится `my_json_parser`, а `ParseJSON` становится `parse_json`. Это преобразование можно переопределить с помощью аннотации `@JsonTypeName`.

### Локальная проверка JSON-схемы инструмента

Вы можете выполнить локальную проверку, чтобы убедиться, что JSON-схема, выведенная из вашего класса инструмента, соответствует ограничениям Anthropic. Локальная проверка включена по умолчанию, но её можно отключить:

```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?");
```

### Аннотирование классов инструментов

Вы можете использовать аннотации, чтобы добавить в JSON-схемы дополнительную информацию об инструментах:

* `@JsonClassDescription` — добавляет к классу инструмента описание, поясняющее, когда и как использовать этот инструмент.
* `@JsonTypeName` — задаёт имя инструмента, отличное от простого имени класса, преобразованного в snake case.
* `@JsonPropertyDescription` — добавляет подробное описание к параметру инструмента.
* `@JsonIgnore` — исключает `public` поле или метод-геттер из сгенерированной JSON-схемы параметров инструмента.
* `@JsonProperty` — включает не-`public` поле или метод-геттер в сгенерированную JSON-схему параметров инструмента.

## Пакеты сообщений

SDK поддерживает [пакетную обработку](https://platform.claude.com/docs/ru/build-with-claude/batch-processing) в пространстве имён `client.messages().batches()`. О том, как получать список пакетов и выполнять по ним пагинацию, см. в разделе [Пагинация](https://platform.claude.com/docs/ru/cli-sdks-libraries/sdks/java#pagination).

## Загрузка файлов

SDK определяет методы, которые принимают файлы через класс `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);
```

Или из `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);
```

Или из байтов в памяти:

```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);
```

### Двоичные ответы

SDK определяет методы, которые возвращают двоичные ответы для ответов API, которые не обязательно разбираются как JSON:

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

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

Чтобы сохранить содержимое ответа в файл:

```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);
}
```

Или передать содержимое ответа в любой `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);
}
```

## Обработка ошибок

SDK выбрасывает пользовательские непроверяемые типы исключений:

* `AnthropicServiceException` — базовый класс для ошибок HTTP.
* `AnthropicIoException` — сетевые ошибки ввода-вывода.
* `AnthropicRetryableException` — общая ошибка, указывающая на сбой, который можно повторить.
* `AnthropicInvalidDataException` — невозможность интерпретировать успешно разобранные данные (например, при обращении к свойству, которое должно быть обязательным, но API неожиданно его опустил).
* `AnthropicException` — базовый класс для всех исключений.

### Соответствие кодов состояния

| Статус | Исключение                      |
| ------ | ------------------------------- |
| 400    | `BadRequestException`           |
| 401    | `UnauthorizedException`         |
| 403    | `PermissionDeniedException`     |
| 404    | `NotFoundException`             |
| 422    | `UnprocessableEntityException`  |
| 429    | `RateLimitException`            |
| 5xx    | `InternalServerException`       |
| другие | `UnexpectedStatusCodeException` |

`SseException` выбрасывается при ошибках, возникших во время потоковой передачи SSE после успешного начального HTTP-ответа.

```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());
}
```

## Идентификаторы запросов

При использовании [необработанных ответов](https://platform.claude.com/docs/ru/cli-sdks-libraries/sdks/java#raw-response-access) вы можете получить доступ к заголовку ответа `request-id` с помощью метода `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();
```

Это можно использовать для быстрого логирования неудачных запросов и сообщения о них в Anthropic. Дополнительную информацию об отладке запросов см. в разделе [Request ID](https://platform.claude.com/docs/ru/api/errors#request-id).

## Повторные попытки

По умолчанию SDK автоматически выполняет 2 повторные попытки с коротким экспоненциальным откатом между запросами.

Повторяются только следующие типы ошибок:

* Ошибки соединения (например, из-за проблемы с сетевым подключением)
* 408 Request Timeout
* 409 Conflict
* 429 Rate Limit
* 5xx Internal

API также может явно указать SDK повторить или не повторять запрос.

Чтобы задать собственное количество повторных попыток, настройте клиент с помощью метода `maxRetries`:

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

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

## Тайм-ауты

По умолчанию время ожидания запросов истекает через 10 минут.

Однако для методов, принимающих `maxTokens`, если вы указываете большое значение `maxTokens` и используете потоковую передачу, тайм-аут по умолчанию будет вычисляться динамически по следующей формуле:

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

Это даёт тайм-аут до 60 минут, масштабируемый параметром `maxTokens`, если он не переопределён.

Для запросов без потоковой передачи динамический тайм-аут масштабируется от минимума в 30 секунд до максимума в 10 минут в зависимости от `maxTokens`.

Чтобы задать собственный тайм-аут для отдельного запроса:

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

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

Или настройте значение по умолчанию для всех вызовов методов на уровне клиента:

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

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

## Длительные запросы

<Warning>
  Рассмотрите возможность использования [потоковой передачи](https://platform.claude.com/docs/ru/cli-sdks-libraries/sdks/java#streaming) для длительных запросов.
</Warning>

Избегайте установки большого значения `maxTokens` без использования потоковой передачи. Некоторые сети могут разрывать неактивные соединения через определённый период времени, что может привести к сбою запроса или [истечению тайм-аута](https://platform.claude.com/docs/ru/cli-sdks-libraries/sdks/java#timeouts) без получения ответа от Anthropic. SDK периодически отправляет ping-запросы к API, чтобы поддерживать соединение активным и уменьшить влияние таких сетей.

SDK выбрасывает ошибку, если ожидается, что запрос без потоковой передачи займёт более 10 минут. Использование [метода потоковой передачи](https://platform.claude.com/docs/ru/cli-sdks-libraries/sdks/java#streaming) или [переопределение тайм-аута](https://platform.claude.com/docs/ru/cli-sdks-libraries/sdks/java#timeouts) на уровне клиента или запроса отключает эту ошибку.

## Пагинация

SDK предоставляет удобные способы доступа к результатам с пагинацией — либо по одной странице за раз, либо поэлементно по всем страницам.

### Автоматическая пагинация

Чтобы перебрать все результаты на всех страницах, используйте метод `autoPager()`, который автоматически загружает дополнительные страницы по мере необходимости.

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

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

// Обработка как Iterable
for (MessageBatch batch : page.autoPager()) {
    IO.println(batch);
}

// Обработка как Stream
page.autoPager()
    .stream()
    .limit(50)
    .forEach(batch -> IO.println(batch));
```

При использовании асинхронного клиента метод возвращает `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);
}));

// Если нужно обработать ошибки или завершение потока
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!");
        }
    }
}));

// Или используйте futures
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!");
        }
    }));
```

### Ручная пагинация

Чтобы получить доступ к элементам отдельной страницы и вручную запросить следующую страницу:

```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();
}
```

## Система типов

### Неизменяемость и builder-классы

Каждый класс в SDK имеет связанный builder для его создания. Каждый класс неизменяем после создания. Если у класса есть связанный builder, то у него есть метод `toBuilder()`, который можно использовать для преобразования обратно в builder, чтобы создать изменённую копию.

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

// Создаём изменённую копию с помощью toBuilder()
MessageCreateParams modified = params.toBuilder().maxTokens(2048L).build();
```

Поскольку каждый класс неизменяем, изменение builder никогда не влияет на уже созданные экземпляры класса.

### Запросы и ответы

Чтобы отправить запрос к Claude API, создайте экземпляр некоторого класса `Params` и передайте его соответствующему методу клиента. Когда ответ получен, он десериализуется в экземпляр класса Java.

Например, `client.messages().create(...)` следует вызывать с экземпляром `MessageCreateParams`, и он возвращает экземпляр `Message`.

### Недокументированные параметры

Чтобы задать недокументированные параметры, вызовите методы `putAdditionalHeader`, `putAdditionalQueryParam` или `putAdditionalBodyProperty` для любого класса `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();
```

Позже к ним можно получить доступ в созданном объекте с помощью методов `_additionalHeaders()`, `_additionalQueryParams()` и `_additionalBodyProperties()`.

<Warning>
  Значения, переданные этим методам, перезаписывают значения, переданные более ранним методам. По соображениям безопасности убедитесь, что эти методы используются только с доверенными входными данными.
</Warning>

Чтобы задать недокументированные параметры во вложенных классах заголовков, параметров запроса или тела:

```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();
```

Позже к этим свойствам можно получить доступ во вложенном созданном объекте с помощью метода `_additionalProperties()`.

Чтобы задать документированному параметру или свойству недокументированное или ещё не поддерживаемое значение, передайте объект `JsonValue` в его сеттер:

```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();
```

### Создание JsonValue

Самый простой способ создать `JsonValue` — использовать его метод `from(...)`:

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

// Создание примитивных значений JSON
JsonValue nullValue = JsonValue.from(null);

JsonValue booleanValue = JsonValue.from(true);

JsonValue numberValue = JsonValue.from(42);

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

// Создание значения-массива JSON, эквивалентного `["Hello", "World"]`
JsonValue arrayValue = JsonValue.from(List.of("Hello", "World"));

// Создание значения-объекта JSON, эквивалентного `{ "a": 1, "b": 2 }`
JsonValue objectValue = JsonValue.from(Map.of("a", 1, "b", 2));

// Создание JSON произвольной вложенности, эквивалентного:
// { "a": [1, 2], "b": [3, 4] }
JsonValue complexValue = JsonValue.from(Map.of("a", List.of(1, 2), "b", List.of(3, 4)));
```

### Принудительное опускание обязательных параметров

Обычно метод `build` класса `Builder` выбрасывает `IllegalStateException`, если какой-либо обязательный параметр или свойство не задан. Чтобы принудительно опустить обязательный параметр или свойство, передайте `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();
```

### Свойства ответа

Чтобы получить доступ к недокументированным свойствам ответа, вызовите метод `_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!";
    }

    // Другие методы: `visitMissing`, `visitString`, `visitArray` и `visitObject`
    // Реализация по умолчанию каждого нереализованного метода делегирует вызов `visitDefault`,
    // который по умолчанию выбрасывает исключение, но его также можно переопределить
});
```

Чтобы получить доступ к необработанному JSON-значению свойства, вызовите его метод с префиксом `_`:

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

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

if (stopReason.isMissing()) {
  // Свойство отсутствует в JSON-ответе
} else if (stopReason.isNull()) {
  // Свойству было присвоено литеральное значение null
} else {
  // Проверить, было ли значение передано в виде строки
  // Другие методы включают `asNumber()`, `asBoolean()` и т. д.
  Optional<String> jsonString = stopReason.asString();

  // Попытаться десериализовать в пользовательский тип
  MyClass myObject = stopReason.asUnknown().orElseThrow().convert(MyClass.class);
}
```

### Проверка ответа

По умолчанию SDK не выбрасывает исключение, когда API возвращает ответ, не соответствующий ожидаемому типу. Он выбрасывает `AnthropicInvalidDataException` только при непосредственном обращении к свойству.

Чтобы заранее проверить, что ответ полностью корректно типизирован, вызовите `validate()`:

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

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

Или настройте для отдельного запроса:

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

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

Или настройте значение по умолчанию для всех вызовов методов на уровне клиента:

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

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

## Настройка HTTP-клиента

### Настройка прокси

```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();
```

### Настройка HTTPS / SSL

<Note>
  Большинству приложений не следует вызывать эти методы; вместо этого используйте системные значения по умолчанию. Значения по умолчанию включают специальные оптимизации, которые могут быть потеряны при изменении реализаций.
</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();
```

### Пользовательский HTTP-клиент

SDK состоит из трёх артефактов:

* `anthropic-java-core` — содержит основную логику SDK, не зависит от OkHttp. Предоставляет `AnthropicClient`, `AnthropicClientAsync` и их классы реализации, которые могут работать с любым HTTP-клиентом.
* `anthropic-java-client-okhttp` — зависит от OkHttp. Предоставляет `AnthropicOkHttpClient` и `AnthropicOkHttpClientAsync`.
* `anthropic-java` — зависит от `anthropic-java-core` и `anthropic-java-client-okhttp` и предоставляет API обоих. Не имеет собственной логики.

Такая структура позволяет заменить HTTP-клиент SDK по умолчанию, не подключая ненужные зависимости.

#### Настроенный OkHttpClient

<Tip>
  Прежде чем заменять клиент по умолчанию, попробуйте доступные [сетевые параметры](https://platform.claude.com/docs/ru/cli-sdks-libraries/sdks/java#retries).
</Tip>

Чтобы использовать настроенный `OkHttpClient`:

1. Замените зависимость `anthropic-java` на `anthropic-java-core`.
2. Скопируйте класс `OkHttpClient` из `anthropic-java-client-okhttp` в свой код и настройте его.
3. Создайте `AnthropicClientImpl` или `AnthropicClientAsyncImpl`, используя ваш настроенный клиент.

#### Полностью пользовательский HTTP-клиент

Чтобы использовать полностью пользовательский HTTP-клиент:

1. Замените зависимость `anthropic-java` на `anthropic-java-core`.
2. Напишите класс, реализующий интерфейс `HttpClient`.
3. Создайте `AnthropicClientImpl` или `AnthropicClientAsyncImpl`, используя ваш новый класс клиента.

## Интеграции с платформами

<Note>
  Подробные руководства по настройке платформ с примерами кода см.:

  * [Amazon Bedrock](https://platform.claude.com/docs/ru/build-with-claude/claude-in-amazon-bedrock)
  * [Amazon Bedrock (Opus 4.6 и более ранние)](https://platform.claude.com/docs/ru/build-with-claude/claude-on-amazon-bedrock-legacy)
  * [Claude Platform on AWS](https://platform.claude.com/docs/ru/build-with-claude/claude-platform-on-aws)
  * [Claude Models on Google Cloud (Google managed)](https://platform.claude.com/docs/ru/build-with-claude/claude-models-on-google-cloud/google-managed)
  * [Microsoft Foundry](https://platform.claude.com/docs/ru/build-with-claude/claude-in-microsoft-foundry)

  См. также [Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/ru/build-with-claude/claude-models-on-google-cloud/anthropic-managed).
</Note>

Java SDK поддерживает следующие платформы через отдельные зависимости, предоставляющие специфичные для платформ реализации `Backend`:

* **Agent Platform:** `com.anthropic:anthropic-java-vertex`: используйте `VertexBackend.builder()` или `VertexBackend.fromEnv()`. `fromEnv()` считывает `CLOUD_ML_REGION` и `ANTHROPIC_VERTEX_PROJECT_ID` и использует Application Default Credentials.
* **Bedrock:** `com.anthropic:anthropic-java-bedrock`: используйте `BedrockMantleBackend.fromEnv()` или `BedrockMantleBackend.builder()` для конечной точки Bedrock с Messages API либо `BedrockBackend.fromEnv()` / `BedrockBackend.builder()` (путь `bedrock-runtime`).
* **Claude Platform on AWS:** `com.anthropic:anthropic-java-aws`: используйте `AwsBackend.fromEnv()` (считывает `ANTHROPIC_AWS_WORKSPACE_ID` и регион/цепочку учётных данных AWS по умолчанию) или `AwsBackend.builder()`. Доступно в бета-версии.
* **Foundry:** `com.anthropic:anthropic-java-foundry`: используйте `FoundryBackend.fromEnv()` или `FoundryBackend.builder()`.

Используйте `BedrockMantleBackend` для новых проектов; `BedrockBackend` сохраняется для существующих приложений, использующих API Bedrock `InvokeModel`.

Java SDK также поддерживает Claude Models on Google Cloud (Anthropic managed) через `GoogleCloudBackend` из зависимости `com.anthropic:anthropic-java-google-cloud`. Этот бэкенд находится в стадии бета-тестирования. Создайте его с помощью `GoogleCloudBackend.builder()` или `GoogleCloudBackend.fromEnv()`. `fromEnv()` считывает `ANTHROPIC_GOOGLE_CLOUD_WORKSPACE_ID`, `ANTHROPIC_GOOGLE_CLOUD_PROJECT` и учётные данные Google Application Default Credentials. См. [Определение проекта, расположения и рабочего пространства](https://platform.claude.com/docs/ru/build-with-claude/claude-models-on-google-cloud/anthropic-managed#project-location-and-workspace-resolution).

Артефакты платформ являются дополнениями к базовой зависимости `com.anthropic:anthropic-java`, которая предоставляет `AnthropicOkHttpClient`, поэтому установите обе. Каждая реализация `Backend` передаётся клиенту с помощью `.backend()` в `AnthropicOkHttpClient.builder()`. Каждый облачный бэкенд подключает классы SDK соответствующей облачной платформы в качестве транзитивных зависимостей.

## Расширенное использование

### Доступ к необработанному ответу

Чтобы получить доступ к HTTP-заголовкам, кодам состояния и необработанному телу ответа, добавьте `withRawResponse()` перед вызовом любого 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();
```

При необходимости вы по-прежнему можете десериализовать ответ в экземпляр класса Java:

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

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

### Логирование

SDK использует стандартный перехватчик логирования OkHttp.

Включите логирование, установив переменную окружения `ANTHROPIC_LOG` в значение `info`:

```bash
export ANTHROPIC_LOG=info
```

Или в значение `debug` для более подробного логирования:

```bash
export ANTHROPIC_LOG=debug
```

<Accordion title="Совместимость с Jackson">
  SDK зависит от Jackson для сериализации/десериализации JSON. Он совместим с версией 2.13.4 или выше, но по умолчанию зависит от версии 2.19.4.

  SDK выбрасывает исключение, если во время выполнения обнаруживает несовместимую версию Jackson (например, если версия по умолчанию была переопределена в вашей конфигурации Maven или Gradle).

  Если SDK выбросил исключение, но вы уверены, что версия совместима, отключите проверку версии с помощью `checkJacksonVersionCompatibility` в `AnthropicOkHttpClient` или `AnthropicOkHttpClientAsync`.

  <Warning>
    Нет гарантии, что SDK будет работать корректно при отключённой проверке версии Jackson.
  </Warning>

  В старых версиях Jackson также есть ошибки, которые могут влиять на SDK. SDK не обходит все ошибки Jackson и ожидает, что пользователи обновят Jackson для их устранения.
</Accordion>

<Accordion title="Настройка ProGuard/R8">
  Хотя SDK использует рефлексию, его всё равно можно использовать с ProGuard и R8, поскольку `anthropic-java-core` публикуется с файлом конфигурации, содержащим правила keep.

  ProGuard и R8 должны автоматически обнаруживать и использовать опубликованные правила, но при необходимости вы также можете скопировать правила keep вручную.
</Accordion>

### Трассировка OpenTelemetry

Когда ваше приложение регистрирует провайдер трассировщика OpenTelemetry, SDK создаёт спан для каждого отправляемого запроса. Чтобы отправлять спаны на вашу платформу наблюдаемости, см. [Настройка OpenTelemetry с Claude SDK](https://platform.claude.com/docs/ru/manage-claude/opentelemetry/sdk).

### Недокументированная функциональность API

SDK типизирован для удобного использования документированного API. Однако он также поддерживает работу с недокументированными или ещё не поддерживаемыми частями API.

#### Недокументированные параметры запроса

Чтобы задать недокументированные параметры запроса, используйте методы `putAdditionalHeader`, `putAdditionalQueryParam` или `putAdditionalBodyProperty`, как описано в разделе [Недокументированные параметры](https://platform.claude.com/docs/ru/cli-sdks-libraries/sdks/java#undocumented-parameters).

#### Недокументированные свойства ответа

Чтобы получить доступ к недокументированным свойствам ответа, используйте метод `_additionalProperties()`, как описано в разделе [Свойства ответа](https://platform.claude.com/docs/ru/cli-sdks-libraries/sdks/java#response-properties).

#### Новые или ещё не выпущенные значения перечислений

Классы SDK, подобные перечислениям, такие как `Model` и `AnthropicBeta`, не являются закрытыми типами Java `enum`. Каждый из них предоставляет фабричный метод `of(String)`, принимающий любую строку, поэтому вы можете использовать значения, которые ещё не добавлены в SDK, например модель или бета-заголовок, выпущенные после вашей версии 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");
```

Методы builder, принимающие эти типы, часто также предоставляют перегрузку для `String`, которая вызывает `of(...)` за вас:

```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();
```

Предпочитайте строго типизированные константы (например, `Model.CLAUDE_OPUS_5`), чтобы получать автодополнение и предупреждения об устаревании. Перегрузки для `String` и `of(...)` предназначены в первую очередь для установки поля в недокументированное или ещё не поддерживаемое значение в ожидании выпуска SDK, который его включает.

## Бета-функции

Бета-функции становятся доступны до общего выпуска, чтобы получить ранние отзывы и протестировать новую функциональность. Доступность всех возможностей и инструментов Claude можно проверить в [обзоре функций](https://platform.claude.com/docs/ru/build-with-claude/overview).

Доступ к большинству бета-функций API можно получить через метод `beta()` клиента. Чтобы включить определённую бета-функцию, добавьте соответствующий [бета-заголовок](https://platform.claude.com/docs/ru/api/beta-headers) с помощью `.addBeta()` при создании параметров сообщения.

Например, чтобы включить [редактирование контекста](https://platform.claude.com/docs/ru/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());
}
```

## Часто задаваемые вопросы

<AccordionGroup>
  <Accordion title="Почему SDK не использует обычные классы enum?">
    Классы Java `enum` не обладают простой прямой совместимостью. Их использование в SDK могло бы вызывать исключения во время выполнения, если API будет обновлён и начнёт возвращать новое значение перечисления.

    Поскольку эти классы открыты, вы также можете создавать их с любым строковым значением через их фабричный метод `of(String)`. См. раздел [Новые или ещё не выпущенные значения перечислений](https://platform.claude.com/docs/ru/cli-sdks-libraries/sdks/java#new-or-unreleased-enum-values), если вам нужно использовать значение, которого ещё нет в вашей версии SDK.
  </Accordion>

  <Accordion title="Почему поля представлены с помощью JsonField<T>, а не просто T?">
    Использование `JsonField<T>` обеспечивает несколько возможностей:

    * Возможность использования недокументированной функциональности API
    * Ленивая проверка ответа API на соответствие ожидаемой структуре
    * Различение отсутствующих и явно заданных как null значений
  </Accordion>

  <Accordion title="Почему SDK не использует data-классы?">
    Добавление новых полей в data-класс нарушает обратную совместимость, а SDK избегает внесения критических изменений каждый раз, когда в класс добавляется поле.
  </Accordion>

  <Accordion title="Почему SDK не использует проверяемые исключения?">
    Проверяемые исключения широко считаются ошибкой в языке программирования Java. Фактически по этой причине они были исключены из Kotlin.

    Проверяемые исключения:

    * Требуют многословной обработки
    * Поощряют обработку ошибок на неправильном уровне абстракции, где с ошибкой ничего нельзя сделать
    * Утомительны в распространении из-за проблемы «окрашивания функций»
    * Плохо сочетаются с лямбдами (также из-за проблемы «окрашивания функций»)
  </Accordion>
</AccordionGroup>

## Семантическое версионирование

Каждая мажорная версия этого SDK по умолчанию отправляет одну версию API в заголовке `anthropic-version`, и с каждой новой версией API выходит новая мажорная версия. Первая мажорная версия, отправляющая `2026-10-21`, — 3.0.0; см. [Переход на версию API 2026-10-21](https://platform.claude.com/docs/ru/api/migration-2026-10-21#upgrade).

Этот пакет в целом следует соглашениям [SemVer](https://semver.org/spec/v2.0.0.html), хотя некоторые обратно несовместимые изменения могут выпускаться в минорных версиях:

1. Изменения во внутренних компонентах библиотеки, которые технически являются публичными, но не предназначены или не задокументированы для внешнего использования.
2. Изменения, которые, как ожидается, на практике не затронут подавляющее большинство пользователей.

## Дополнительные ресурсы

* [Репозиторий GitHub](https://github.com/anthropics/anthropic-sdk-java)
* [Javadocs](https://javadoc.io/doc/com.anthropic/anthropic-java)
* [Справочник API](https://platform.claude.com/docs/ru/api/overview)
* [Потоковая передача сообщений](https://platform.claude.com/docs/ru/build-with-claude/streaming)
* [Использование инструментов с Claude](https://platform.claude.com/docs/ru/agents-and-tools/tool-use/overview)
