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
| Setter | System property | Variabel lingkungan | Wajib | Nilai default |
|---|---|---|---|---|
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" |
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 fieldpublicatau metode getter dari skema JSON yang dihasilkan untuk parameter alat.@JsonProperty- Menyertakan field non-publicatau 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
| Status | Exception |
|---|---|
| 400 | BadRequestException |
| 401 | UnauthorizedException |
| 403 | PermissionDeniedException |
| 404 | NotFoundException |
| 422 | UnprocessableEntityException |
| 429 | RateLimitException |
| 5xx | InternalServerException |
| lainnya | UnexpectedStatusCodeException |
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. MengeksposAnthropicClient,AnthropicClientAsync, dan kelas implementasinya, yang semuanya dapat bekerja dengan klien HTTP apa pun.anthropic-java-client-okhttp- Bergantung pada OkHttp. MengeksposAnthropicOkHttpClientdanAnthropicOkHttpClientAsync.anthropic-java- Bergantung pada dan mengekspos API darianthropic-java-coredananthropic-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:
- Ganti dependensi
anthropic-javaAnda dengananthropic-java-core. - Salin kelas
OkHttpClientmilikanthropic-java-client-okhttpke dalam kode Anda dan kustomisasi. - Bangun
AnthropicClientImplatauAnthropicClientAsyncImplmenggunakan klien yang telah Anda kustomisasi.
Klien HTTP yang sepenuhnya kustom
Untuk menggunakan klien HTTP yang sepenuhnya kustom:
- Ganti dependensi
anthropic-javaAnda dengananthropic-java-core. - Tulis kelas yang mengimplementasikan interface
HttpClient. - Bangun
AnthropicClientImplatauAnthropicClientAsyncImplmenggunakan 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: GunakanVertexBackend.fromEnv()atauVertexBackend.builder(). - Bedrock:
com.anthropic:anthropic-java-bedrock: GunakanBedrockMantleBackend.fromEnv()atauBedrockMantleBackend.builder()untuk endpoint Bedrock Messages-API, atauBedrockBackend.fromEnv()/BedrockBackend.builder()(jalurbedrock-runtime). - Claude Platform on AWS:
com.anthropic:anthropic-java-aws: GunakanAwsBackend.fromEnv()(membacaANTHROPIC_AWS_WORKSPACE_IDdan rantai region/kredensial default AWS) atauAwsBackend.builder(). Tersedia dalam beta. - Foundry:
com.anthropic:anthropic-java-foundry: GunakanFoundryBackend.fromEnv()atauFoundryBackend.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=infoAtau ke debug untuk logging yang lebih rinci:
export ANTHROPIC_LOG=debugSDK bergantung pada Jackson untuk serialisasi/deserialisasi JSON. SDK kompatibel dengan versi 2.13.4 atau lebih tinggi, tetapi secara default bergantung pada versi 2.19.4.
SDK melempar exception jika mendeteksi versi Jackson yang tidak kompatibel saat runtime (misalnya, jika versi default ditimpa dalam konfigurasi Maven atau Gradle Anda).
Jika SDK melempar exception, tetapi Anda yakin versinya kompatibel, nonaktifkan pemeriksaan versi menggunakan checkJacksonVersionCompatibility pada AnthropicOkHttpClient atau AnthropicOkHttpClientAsync.
Ada juga bug pada versi Jackson lama yang dapat memengaruhi SDK. SDK tidak mengatasi semua bug Jackson dan mengharapkan pengguna untuk memutakhirkan Jackson untuk kasus-kasus tersebut.
Meskipun SDK menggunakan reflection, SDK tetap dapat digunakan dengan ProGuard dan R8 karena anthropic-java-core dipublikasikan dengan file konfigurasi yang berisi keep rules.
ProGuard dan R8 seharusnya secara otomatis mendeteksi dan menggunakan aturan yang dipublikasikan, tetapi Anda juga dapat menyalin keep rules secara manual jika diperlukan.
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
Kelas enum Java tidak mudah kompatibel ke depan. Menggunakannya dalam SDK dapat menyebabkan runtime exception jika API diperbarui untuk merespons dengan nilai enum baru.
Karena kelas-kelas ini terbuka, Anda juga dapat membangunnya dengan nilai string apa pun melalui metode factory of(String)-nya. Lihat Nilai enum baru atau belum dirilis jika Anda perlu menggunakan nilai yang belum ada di versi SDK Anda.
Menggunakan JsonField<T> memungkinkan beberapa fitur:
- Memungkinkan penggunaan fungsionalitas API yang tidak terdokumentasi
- Memvalidasi respons API secara lazy terhadap bentuk yang diharapkan
- Merepresentasikan nilai yang tidak ada vs nilai null eksplisit
Menambahkan field baru ke data class tidak kompatibel ke belakang, dan SDK menghindari memperkenalkan breaking change setiap kali sebuah field ditambahkan ke kelas.
Checked exception secara luas dianggap sebagai kesalahan dalam bahasa pemrograman Java. Bahkan, checked exception dihilangkan dari Kotlin karena alasan ini.
Checked exception:
- Bertele-tele untuk ditangani
- Mendorong penanganan error pada tingkat abstraksi yang salah, di mana tidak ada yang bisa dilakukan terhadap error tersebut
- Merepotkan untuk dipropagasi karena masalah function coloring
- Tidak bekerja dengan baik bersama lambda (juga karena masalah function coloring)
Semantic versioning
Paket ini umumnya mengikuti konvensi SemVer, meskipun perubahan tertentu yang tidak kompatibel ke belakang mungkin dirilis sebagai versi minor:
- Perubahan pada internal library yang secara teknis publik tetapi tidak dimaksudkan atau didokumentasikan untuk penggunaan eksternal.
- Perubahan yang dalam praktiknya tidak diperkirakan berdampak pada sebagian besar pengguna.
Sumber daya tambahan
Was this page helpful?