Claude Platform Docs

Java SDK

Instal dan konfigurasikan Anthropic Java SDK dengan pola builder dan dukungan async

Anthropic Java SDK menyediakan akses yang mudah ke Claude API dari aplikasi yang ditulis dalam Java. SDK ini menggunakan "builder pattern" (pola builder) untuk membuat permintaan dan mendukung operasi sinkron maupun asinkron.

Instalasi

implementation("com.anthropic:anthropic-java:2.58.0")

Persyaratan

Library ini memerlukan Java 8 atau yang lebih baru.

Mulai cepat

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;

// Mengonfigurasi menggunakan properti sistem `anthropic.apiKey`, `anthropic.authToken`, dan `anthropic.baseUrl`
// Atau mengonfigurasi menggunakan variabel lingkungan `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, dan `ANTHROPIC_BASE_URL`
AnthropicClient client = AnthropicOkHttpClient.fromEnv();

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

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

Konfigurasi klien

Penyiapan kunci API

Konfigurasikan klien menggunakan system property atau variabel lingkungan:

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

// Mengonfigurasi menggunakan properti sistem `anthropic.apiKey`, `anthropic.authToken`, dan `anthropic.baseUrl`
// Atau mengonfigurasi menggunakan variabel lingkungan `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, dan `ANTHROPIC_BASE_URL`
AnthropicClient client = AnthropicOkHttpClient.fromEnv();

Atau konfigurasikan secara manual:

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

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

Atau gunakan kombinasi kedua pendekatan:

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

AnthropicClient client = AnthropicOkHttpClient.builder()
  // Mengonfigurasi menggunakan properti sistem atau variabel lingkungan
  .fromEnv()
  .apiKey("my-anthropic-api-key")
  .build();

Untuk opsi autentikasi termasuk Workload Identity Federation, lihat Autentikasi. Jika kunci API Anda adalah kunci personal atau kunci akun layanan dengan akses ke beberapa workspace, tetapkan ID workspace di header permintaan anthropic-workspace-id; Pilih workspace menunjukkan opsi per permintaan untuk SDK ini.

Opsi konfigurasi

SetterSystem propertyVariabel lingkunganWajibNilai default
apiKeyanthropic.apiKeyANTHROPIC_API_KEYfalse-
authTokenanthropic.authTokenANTHROPIC_AUTH_TOKENfalse-
baseUrlanthropic.baseUrlANTHROPIC_BASE_URLtrue"https://api.anthropic.com"

System property lebih diutamakan daripada variabel lingkungan.

Memodifikasi konfigurasi

Untuk sementara menggunakan konfigurasi klien yang dimodifikasi sambil tetap menggunakan connection pool dan thread pool yang sama, panggil withOptions() pada klien atau service mana pun:

import com.anthropic.client.AnthropicClient;

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

Metode withOptions() tidak memengaruhi klien atau service asli.

Penggunaan async

Klien default bersifat sinkron. Untuk beralih ke eksekusi asinkron, panggil metode async():

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)
  .build();

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

Atau buat klien asinkron sejak awal:

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)
  .build();

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

Klien asinkron mendukung opsi yang sama dengan klien sinkron, kecuali sebagian besar metodenya mengembalikan CompletableFuture.

Streaming

SDK mendefinisikan metode yang mengembalikan stream "chunk" respons, di mana setiap chunk dapat diproses secara individual segera setelah tiba alih-alih menunggu respons lengkap.

Streaming sinkron

Metode streaming ini mengembalikan StreamResponse untuk klien sinkron:

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 asinkron

Untuk klien asinkron, metode ini mengembalikan AsyncStreamResponse:

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

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

// Jika Anda perlu menangani error atau penyelesaian 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!");
        }
    }
});

// Atau gunakan 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!");
        }
    });

Streaming async menggunakan Executor cached thread pool khusus per klien untuk melakukan streaming tanpa memblokir thread saat ini. Untuk menggunakan Executor yang berbeda:

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

Atau konfigurasikan klien secara global menggunakan metode streamHandlerExecutor:

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

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

Streaming dengan message accumulator

MessageAccumulator dapat merekam stream event dalam respons saat diproses dan mengakumulasi objek Message yang serupa dengan apa yang akan dikembalikan oleh API non-streaming.

Untuk respons sinkron, tambahkan pemanggilan Stream.peek() ke pipeline stream untuk mengakumulasi setiap event:

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

Untuk respons asinkron, tambahkan MessageAccumulator ke pemanggilan subscribe():

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 juga tersedia untuk akumulasi objek BetaMessage. Penggunaannya sama dengan MessageAccumulator.

Output terstruktur

Untuk dokumentasi lengkap output terstruktur termasuk contoh Java, lihat Output terstruktur.

Penggunaan alat

Penggunaan alat dengan Claude ("tool use") memungkinkan Anda mengintegrasikan alat dan fungsi eksternal langsung ke dalam respons model AI. Alih-alih menghasilkan teks biasa, model dapat mengeluarkan instruksi (dengan parameter) untuk memanggil alat atau fungsi bila sesuai. Anda mendefinisikan skema JSON untuk alat, dan model menggunakan skema tersebut untuk menentukan kapan dan bagaimana menggunakan alat-alat ini.

Fitur penggunaan alat mendukung mode "strict" yang menjamin bahwa output JSON dari model AI akan sesuai dengan skema JSON yang Anda berikan dalam parameter input.

SDK dapat menurunkan alat dan parameternya secara otomatis dari struktur kelas Java apa pun: nama kelas (dikonversi ke snake case) menjadi nama alat, dan field kelas mendefinisikan parameter alat.

Mendefinisikan alat dengan anotasi

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

Memanggil alat

Setelah kelas alat Anda didefinisikan, tambahkan ke parameter pesan menggunakan MessageCreateParams.Builder.addTool(Class<T>) lalu panggil alat tersebut jika diminta dalam respons model AI. BetaToolUseBlock.input(Class<T>) dapat digunakan untuk mem-parsing parameter alat dalam bentuk JSON menjadi instance kelas pendefinisi alat Anda.

Setelah memanggil alat, gunakan BetaToolResultBlockParam.Builder.contentAsJson(Object) untuk mengirimkan hasil alat kembali ke model AI:

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)
        .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
              // Tambahkan pesan yang menunjukkan bahwa penggunaan alat telah diminta.
              .addAssistantMessageOfBetaContentBlockParams(
                      List.of(BetaContentBlockParam.ofToolUse(BetaToolUseBlockParam.builder()
                              .name(toolUseBlock.name())
                              .id(toolUseBlock.id())
                              .input(toolUseBlock._input())
                              .build())))
              // Tambahkan pesan berisi hasil dari penggunaan alat yang diminta.
              .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");
}

Konversi nama alat

Nama alat diturunkan dari nama kelas alat dalam camel case (misalnya, GetWeather) dan dikonversi ke snake case (misalnya, get_weather). Batas kata dimulai ketika karakter saat ini bukan karakter pertama, berupa huruf besar, dan karakter sebelumnya berupa huruf kecil atau karakter berikutnya berupa huruf kecil. Misalnya, MyJSONParser menjadi my_json_parser dan ParseJSON menjadi parse_json. Konversi ini dapat ditimpa menggunakan anotasi @JsonTypeName.

Validasi skema JSON alat secara lokal

Anda dapat melakukan validasi lokal untuk memeriksa bahwa skema JSON yang diturunkan dari kelas alat Anda mematuhi batasan Anthropic. Validasi lokal diaktifkan secara default, tetapi dapat dinonaktifkan:

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

Menganotasi kelas alat

Anda dapat menggunakan anotasi untuk menambahkan informasi lebih lanjut tentang alat ke skema JSON:

  • @JsonClassDescription - Menambahkan deskripsi ke kelas alat yang merinci kapan dan bagaimana menggunakan alat tersebut.
  • @JsonTypeName - Menetapkan nama alat menjadi sesuatu selain nama sederhana kelas yang dikonversi ke snake case.
  • @JsonPropertyDescription - Menambahkan deskripsi terperinci ke parameter alat.
  • @JsonIgnore - Mengecualikan field public atau metode getter dari skema JSON yang dihasilkan untuk parameter alat.
  • @JsonProperty - Menyertakan field non-public atau metode getter dalam skema JSON yang dihasilkan untuk parameter alat.

Batch pesan

SDK menyediakan dukungan untuk Pemrosesan batch di bawah namespace client.messages().batches(). Lihat Paginasi untuk cara mendaftar dan melakukan paginasi melalui batch.

Unggahan file

SDK mendefinisikan metode yang menerima file melalui kelas MultipartField:

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

Atau dari InputStream:

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

Atau dari byte dalam memori:

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

Respons biner

SDK mendefinisikan metode yang mengembalikan respons biner untuk respons API yang tidak selalu di-parsing sebagai JSON:

import com.anthropic.core.http.HttpResponse;

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

Untuk menyimpan konten respons ke file:

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

Atau transfer konten respons ke OutputStream mana pun:

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

Penanganan error

SDK melempar tipe unchecked exception kustom:

  • AnthropicServiceException - Kelas dasar untuk error HTTP.
  • AnthropicIoException - Error jaringan I/O.
  • AnthropicRetryableException - Error umum yang menunjukkan kegagalan yang dapat dicoba ulang.
  • AnthropicInvalidDataException - Kegagalan menafsirkan data yang berhasil di-parsing (misalnya, saat mengakses properti yang seharusnya wajib, tetapi API secara tak terduga menghilangkannya).
  • AnthropicException - Kelas dasar untuk semua exception.

Pemetaan kode status

StatusException
400BadRequestException
401UnauthorizedException
403PermissionDeniedException
404NotFoundException
422UnprocessableEntityException
429RateLimitException
5xxInternalServerException
lainnyaUnexpectedStatusCodeException

SseException dilempar untuk error yang ditemui selama streaming SSE setelah respons HTTP awal yang berhasil.

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 permintaan

Saat menggunakan respons mentah, Anda dapat mengakses header respons request-id menggunakan metode requestId():

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

Ini dapat digunakan untuk mencatat permintaan yang gagal dengan cepat dan melaporkannya kembali ke Anthropic. Untuk informasi lebih lanjut tentang debugging permintaan, lihat ID Permintaan.

Percobaan ulang

SDK secara otomatis mencoba ulang 2 kali secara default, dengan exponential backoff singkat di antara permintaan.

Hanya tipe error berikut yang dicoba ulang:

  • Error koneksi (misalnya, karena masalah konektivitas jaringan)
  • 408 Request Timeout
  • 409 Conflict
  • 429 Rate Limit
  • 5xx Internal

API juga dapat secara eksplisit menginstruksikan SDK untuk mencoba ulang atau tidak mencoba ulang suatu permintaan.

Untuk menetapkan jumlah percobaan ulang kustom, konfigurasikan klien menggunakan metode maxRetries:

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

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

Timeout

Permintaan mengalami timeout setelah 10 menit secara default.

Namun, untuk metode yang menerima maxTokens, jika Anda menentukan nilai maxTokens yang besar dan menggunakan streaming, maka timeout default akan dihitung secara dinamis menggunakan rumus ini:

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

Ini menghasilkan timeout hingga 60 menit, diskalakan berdasarkan parameter maxTokens, kecuali ditimpa.

Untuk permintaan non-streaming, timeout dinamis diskalakan dari minimum 30 detik hingga maksimum 10 menit berdasarkan maxTokens.

Untuk menetapkan timeout kustom per permintaan:

import com.anthropic.models.messages.Message;

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

Atau konfigurasikan default untuk semua pemanggilan metode di tingkat klien:

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

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

Permintaan panjang

Hindari menetapkan nilai maxTokens yang besar tanpa menggunakan streaming. Beberapa jaringan mungkin memutus koneksi yang menganggur setelah jangka waktu tertentu, yang dapat menyebabkan permintaan gagal atau timeout tanpa menerima respons dari Anthropic. SDK secara berkala melakukan ping ke API untuk menjaga koneksi tetap hidup dan mengurangi dampak jaringan semacam ini.

SDK melempar error jika permintaan non-streaming diperkirakan memakan waktu lebih dari 10 menit. Menggunakan metode streaming atau menimpa timeout di tingkat klien atau permintaan akan menonaktifkan error tersebut.

Paginasi

SDK menyediakan cara yang mudah untuk mengakses hasil berpaginasi, baik satu halaman sekaligus maupun item per item di seluruh halaman.

Paginasi otomatis

Untuk mengiterasi semua hasil di seluruh halaman, gunakan metode autoPager(), yang secara otomatis mengambil halaman tambahan sesuai kebutuhan.

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

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

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

// Proses sebagai Stream
page.autoPager()
    .stream()
    .limit(50)
    .forEach(batch -> IO.println(batch));

Saat menggunakan klien asinkron, metode ini mengembalikan AsyncStreamResponse:

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

// Jika Anda perlu menangani error atau penyelesaian 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!");
        }
    }
}));

// Atau gunakan 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!");
        }
    }));

Paginasi manual

Untuk mengakses item halaman individual dan meminta halaman berikutnya secara manual:

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

Sistem tipe

Imutabilitas dan builder

Setiap kelas dalam SDK memiliki builder terkait untuk membangunnya. Setiap kelas bersifat immutable setelah dibangun. Jika kelas memiliki builder terkait, maka kelas tersebut memiliki metode toBuilder(), yang dapat digunakan untuk mengonversinya kembali menjadi builder guna membuat salinan yang dimodifikasi.

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

// Buat salinan yang dimodifikasi menggunakan toBuilder()
MessageCreateParams modified = params.toBuilder().maxTokens(2048L).build();

Karena setiap kelas bersifat immutable, modifikasi builder tidak pernah memengaruhi instance kelas yang sudah dibangun.

Permintaan dan respons

Untuk mengirim permintaan ke Claude API, bangun instance dari suatu kelas Params dan teruskan ke metode klien yang sesuai. Ketika respons diterima, respons tersebut dideserialisasi menjadi instance kelas Java.

Misalnya, client.messages().create(...) harus dipanggil dengan instance MessageCreateParams, dan mengembalikan instance Message.

Parameter tidak terdokumentasi

Untuk menetapkan parameter yang tidak terdokumentasi, panggil metode putAdditionalHeader, putAdditionalQueryParam, atau putAdditionalBodyProperty pada kelas Params mana pun:

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

Ini dapat diakses pada objek yang telah dibangun nantinya menggunakan metode _additionalHeaders(), _additionalQueryParams(), dan _additionalBodyProperties().

Untuk menetapkan parameter tidak terdokumentasi pada header, query param, atau kelas body bersarang:

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

Properti ini dapat diakses pada objek bersarang yang telah dibangun nantinya menggunakan metode _additionalProperties().

Untuk menetapkan parameter atau properti terdokumentasi ke nilai yang tidak terdokumentasi atau belum didukung, teruskan objek JsonValue ke setter-nya:

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)
  .build();

Pembuatan JsonValue

Cara paling mudah untuk membuat JsonValue adalah menggunakan metode from(...)-nya:

import com.anthropic.core.JsonValue;

// Buat nilai JSON primitif
JsonValue nullValue = JsonValue.from(null);

JsonValue booleanValue = JsonValue.from(true);

JsonValue numberValue = JsonValue.from(42);

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

// Buat nilai array JSON yang setara dengan `["Hello", "World"]`
JsonValue arrayValue = JsonValue.from(List.of("Hello", "World"));

// Buat nilai objek JSON yang setara dengan `{ "a": 1, "b": 2 }`
JsonValue objectValue = JsonValue.from(Map.of("a", 1, "b", 2));

// Buat JSON bertingkat sembarang yang setara dengan:
// { "a": [1, 2], "b": [3, 4] }
JsonValue complexValue = JsonValue.from(Map.of("a", List.of(1, 2), "b", List.of(3, 4)));

Menghilangkan parameter wajib secara paksa

Biasanya metode build dari kelas Builder akan melempar IllegalStateException jika ada parameter atau properti wajib yang belum ditetapkan. Untuk menghilangkan parameter atau properti wajib secara paksa, teruskan JsonMissing:

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)
  .maxTokens(JsonMissing.of())
  .build();

Properti respons

Untuk mengakses properti respons yang tidak terdokumentasi, panggil metode _additionalProperties():

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

    // Metode lain mencakup `visitMissing`, `visitString`, `visitArray`, dan `visitObject`
    // Implementasi default setiap metode yang tidak diimplementasikan didelegasikan ke `visitDefault`,
    // yang secara default melempar exception, tetapi juga dapat di-override
});

Untuk mengakses nilai JSON mentah suatu properti, panggil metodenya yang berawalan _:

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

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

if (stopReason.isMissing()) {
  // Properti tidak ada dalam respons JSON
} else if (stopReason.isNull()) {
  // Properti diatur ke null literal
} else {
  // Periksa apakah nilai diberikan sebagai string
  // Metode lain termasuk `asNumber()`, `asBoolean()`, dll.
  Optional<String> jsonString = stopReason.asString();

  // Coba deserialisasi ke tipe kustom
  MyClass myObject = stopReason.asUnknown().orElseThrow().convert(MyClass.class);
}

Validasi respons

Secara default, SDK tidak melempar exception ketika API mengembalikan respons yang tidak cocok dengan tipe yang diharapkan. SDK melempar AnthropicInvalidDataException hanya jika Anda mengakses properti tersebut secara langsung.

Untuk memeriksa di awal bahwa respons sepenuhnya bertipe dengan benar, panggil validate():

import com.anthropic.models.messages.Message;

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

Atau konfigurasikan per permintaan:

import com.anthropic.models.messages.Message;

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

Atau konfigurasikan default untuk semua pemanggilan metode di tingkat klien:

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

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

Kustomisasi klien HTTP

Konfigurasi proxy

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

Konfigurasi HTTPS / SSL

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

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

Klien HTTP kustom

SDK terdiri dari tiga artefak:

  • anthropic-java-core - Berisi logika inti SDK, tidak bergantung pada OkHttp. Mengekspos AnthropicClient, AnthropicClientAsync, dan kelas implementasinya, yang semuanya dapat bekerja dengan klien HTTP apa pun.
  • anthropic-java-client-okhttp - Bergantung pada OkHttp. Mengekspos AnthropicOkHttpClient dan AnthropicOkHttpClientAsync.
  • anthropic-java - Bergantung pada dan mengekspos API dari anthropic-java-core dan anthropic-java-client-okhttp. Tidak memiliki logika sendiri.

Struktur ini memungkinkan penggantian klien HTTP default SDK tanpa menarik dependensi yang tidak perlu.

OkHttpClient yang dikustomisasi

Untuk menggunakan OkHttpClient yang dikustomisasi:

  1. Ganti dependensi anthropic-java Anda dengan anthropic-java-core.
  2. Salin kelas OkHttpClient milik anthropic-java-client-okhttp ke dalam kode Anda dan kustomisasi.
  3. Bangun AnthropicClientImpl atau AnthropicClientAsyncImpl menggunakan klien yang telah Anda kustomisasi.

Klien HTTP yang sepenuhnya kustom

Untuk menggunakan klien HTTP yang sepenuhnya kustom:

  1. Ganti dependensi anthropic-java Anda dengan anthropic-java-core.
  2. Tulis kelas yang mengimplementasikan interface HttpClient.
  3. Bangun AnthropicClientImpl atau AnthropicClientAsyncImpl menggunakan kelas klien baru Anda.

Integrasi platform

Java SDK mendukung platform berikut melalui dependensi terpisah yang menyediakan implementasi Backend khusus platform:

  • Agent Platform: com.anthropic:anthropic-java-vertex: Gunakan VertexBackend.fromEnv() atau VertexBackend.builder().
  • Bedrock: com.anthropic:anthropic-java-bedrock: Gunakan BedrockMantleBackend.fromEnv() atau BedrockMantleBackend.builder() untuk endpoint Bedrock Messages-API, atau BedrockBackend.fromEnv() / BedrockBackend.builder() (jalur bedrock-runtime).
  • Claude Platform on AWS: com.anthropic:anthropic-java-aws: Gunakan AwsBackend.fromEnv() (membaca ANTHROPIC_AWS_WORKSPACE_ID dan rantai region/kredensial default AWS) atau AwsBackend.builder(). Tersedia dalam beta.
  • Foundry: com.anthropic:anthropic-java-foundry: Gunakan FoundryBackend.fromEnv() atau FoundryBackend.builder().

Gunakan BedrockMantleBackend untuk proyek baru; BedrockBackend tetap tersedia untuk aplikasi yang sudah ada yang menggunakan API InvokeModel Bedrock.

Setiap implementasi Backend diteruskan ke klien dengan .backend() pada AnthropicOkHttpClient.builder(). Setiap backend cloud menarik kelas SDK platform cloud masing-masing sebagai dependensi transitif.

Penggunaan lanjutan

Akses respons mentah

Untuk mengakses header HTTP, kode status, dan body respons mentah, awali pemanggilan metode HTTP apa pun dengan withRawResponse():

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)
  .build();

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

int statusCode = message.statusCode();

Headers headers = message.headers();

Anda masih dapat mendeserialisasi respons menjadi instance kelas Java jika diperlukan:

import com.anthropic.models.messages.Message;

Message parsedMessage = message.parse();

Logging

SDK menggunakan logging interceptor OkHttp standar.

Aktifkan logging dengan menetapkan variabel lingkungan ANTHROPIC_LOG ke info:

export ANTHROPIC_LOG=info

Atau ke debug untuk logging yang lebih rinci:

export ANTHROPIC_LOG=debug

Fungsionalitas API tidak terdokumentasi

SDK memiliki tipe untuk penggunaan API terdokumentasi yang mudah. Namun, SDK juga mendukung bekerja dengan bagian API yang tidak terdokumentasi atau belum didukung.

Parameter permintaan tidak terdokumentasi

Untuk menetapkan parameter permintaan yang tidak terdokumentasi, gunakan metode putAdditionalHeader, putAdditionalQueryParam, atau putAdditionalBodyProperty seperti dijelaskan di Parameter tidak terdokumentasi.

Properti respons tidak terdokumentasi

Untuk mengakses properti respons yang tidak terdokumentasi, gunakan metode _additionalProperties() seperti dijelaskan di Properti respons.

Nilai enum baru atau belum dirilis

Kelas mirip enum dalam SDK, seperti Model dan AnthropicBeta, bukan tipe enum Java tertutup. Masing-masing menyediakan metode factory of(String) yang menerima string apa pun, sehingga Anda dapat menggunakan nilai yang belum ditambahkan ke SDK, seperti model atau header beta yang dirilis setelah versi SDK Anda:

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

Metode builder yang menerima tipe-tipe ini sering kali juga menyediakan overload String yang memanggil of(...) untuk Anda:

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

Utamakan konstanta bertipe baik (misalnya, Model.CLAUDE_OPUS_5) agar Anda mendapatkan autocomplete dan peringatan deprecation. Overload String dan of(...) terutama ditujukan untuk menetapkan field ke nilai yang tidak terdokumentasi atau belum didukung sambil menunggu rilis SDK yang menyertakannya.

Fitur beta

Fitur beta tersedia sebelum rilis umum untuk mendapatkan umpan balik awal dan menguji fungsionalitas baru. Anda dapat memeriksa ketersediaan semua kemampuan dan alat Claude di ikhtisar membangun dengan Claude.

Anda dapat mengakses sebagian besar fitur API beta melalui metode beta() pada klien. Untuk mengaktifkan fitur beta tertentu, tambahkan header beta yang sesuai dengan .addBeta() saat membangun params pesan.

Misalnya, untuk mengaktifkan pengeditan konteks:

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)
            .maxTokens(1024L)
            .addBeta(AnthropicBeta.CONTEXT_MANAGEMENT_2025_06_27)
            .addUserMessage("Hello, Claude")
            .build());
}

Pertanyaan yang sering diajukan

Semantic versioning

Paket ini umumnya mengikuti konvensi SemVer, meskipun perubahan tertentu yang tidak kompatibel ke belakang mungkin dirilis sebagai versi minor:

  1. Perubahan pada internal library yang secara teknis publik tetapi tidak dimaksudkan atau didokumentasikan untuk penggunaan eksternal.
  2. Perubahan yang dalam praktiknya tidak diperkirakan berdampak pada sebagian besar pengguna.

Sumber daya tambahan

Was this page helpful?