Das Anthropic Java SDK bietet bequemen Zugriff auf die Anthropic REST API aus Anwendungen, die in Java geschrieben sind. Es verwendet das Builder-Pattern zum Erstellen von Anfragen und unterstützt sowohl synchrone als auch asynchrone Operationen.
Für die Dokumentation der API-Funktionen mit Codebeispielen siehe die API-Referenz. Diese Seite behandelt Java-spezifische SDK-Funktionen und -Konfiguration.
Diese Bibliothek erfordert Java 8 oder höher.
Das SDK unterstützt Java 8 und höher. Die Codebeispiele in dieser Dokumentation sind als JDK 25 Compact Source Files geschrieben und verwenden einen einfachen void main()-Einstiegspunkt sowie IO.println() für die Ausgabe. Die API-Aufrufe selbst sind auf jedem unterstützten JDK identisch; um ein Beispiel auf einer früheren Version zu kompilieren, ersetze IO.println(...) durch System.out.println(...) und platziere den Body innerhalb von public static void main(String[] args) in einer Klasse.
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;
// Konfiguriert über die System-Properties `anthropic.apiKey`, `anthropic.authToken` und `anthropic.baseUrl`
// Oder konfiguriert über die Umgebungsvariablen `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN` und `ANTHROPIC_BASE_URL`
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
MessageCreateParams params = MessageCreateParams.builder()
.maxTokens(1024L)
.addUserMessage("Hello, Claude")
.model(Model.CLAUDE_OPUS_4_8)
.build();
Message message = client.messages().create(params);Konfiguriere den Client mithilfe von System-Properties oder Umgebungsvariablen:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
// Konfiguriert über die System-Properties `anthropic.apiKey`, `anthropic.authToken` und `anthropic.baseUrl`
// Oder konfiguriert über die Umgebungsvariablen `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN` und `ANTHROPIC_BASE_URL`
AnthropicClient client = AnthropicOkHttpClient.fromEnv();Oder konfiguriere manuell:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
AnthropicClient client = AnthropicOkHttpClient.builder()
.apiKey("my-anthropic-api-key")
.build();Oder verwende eine Kombination aus beiden Ansätzen:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
AnthropicClient client = AnthropicOkHttpClient.builder()
// Konfiguriert über Systemeigenschaften oder Umgebungsvariablen
.fromEnv()
.apiKey("my-anthropic-api-key")
.build();Für Authentifizierungsoptionen einschließlich Workload Identity Federation siehe Authentifizierung.
| Setter | System-Property | Umgebungsvariable | Erforderlich | Standardwert |
|---|---|---|---|---|
apiKey | anthropic.apiKey | ANTHROPIC_API_KEY | false | - |
authToken | anthropic.authToken | ANTHROPIC_AUTH_TOKEN | false | - |
baseUrl | anthropic.baseUrl | ANTHROPIC_BASE_URL | true |
System-Properties haben Vorrang vor Umgebungsvariablen.
Erstelle nicht mehr als einen Client in derselben Anwendung. Jeder Client hat einen Connection-Pool und Thread-Pools, die effizienter zwischen Anfragen geteilt werden.
Um vorübergehend eine geänderte Client-Konfiguration zu verwenden und dabei dieselben Connection- und Thread-Pools wiederzuverwenden, rufe withOptions() auf einem beliebigen Client oder Service auf:
import com.anthropic.client.AnthropicClient;
AnthropicClient clientWithOptions = client.withOptions(optionsBuilder -> {
optionsBuilder.baseUrl("https://example.com");
optionsBuilder.maxRetries(42);
});Die Methode withOptions() hat keine Auswirkungen auf den ursprünglichen Client oder Service.
Der Standard-Client ist synchron. Um zur asynchronen Ausführung zu wechseln, rufe die Methode async() auf:
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_4_8)
.build();
CompletableFuture<Message> message = client.async().messages().create(params);Oder erstelle von Anfang an einen asynchronen Client:
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_4_8)
.build();
CompletableFuture<Message> message = client.messages().create(params);Der asynchrone Client unterstützt dieselben Optionen wie der synchrone, außer dass die meisten Methoden CompletableFutures zurückgeben.
Das SDK definiert Methoden, die Response-„Chunk"-Streams zurückgeben, bei denen jeder Chunk einzeln verarbeitet werden kann, sobald er ankommt, anstatt auf die vollständige Antwort zu warten.
Diese Streaming-Methoden geben StreamResponse für synchrone Clients zurück:
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!");
}Für asynchrone Clients gibt die Methode AsyncStreamResponse zurück:
import com.anthropic.core.http.AsyncStreamResponse;
import com.anthropic.models.messages.RawMessageStreamEvent;
client.async().messages().createStreaming(params).subscribe(chunk -> {
IO.println(chunk);
});
// Falls du Fehler oder den Abschluss des Streams behandeln musst
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!");
}
}
});
// Oder verwende 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!");
}
});Asynchrones Streaming verwendet einen dedizierten, pro Client gecachten Thread-Pool-Executor, um zu streamen, ohne den aktuellen Thread zu blockieren. Um einen anderen Executor zu verwenden:
Executor executor = Executors.newFixedThreadPool(4);
client.async().messages().createStreaming(params).subscribe(
chunk -> IO.println(chunk), executor
);Oder konfiguriere den Client global mit der Methode streamHandlerExecutor:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
AnthropicClient client = AnthropicOkHttpClient.builder()
.fromEnv()
.streamHandlerExecutor(Executors.newFixedThreadPool(4))
.build();Ein MessageAccumulator kann den Stream von Events in der Antwort aufzeichnen, während sie verarbeitet werden, und ein Message-Objekt akkumulieren, das dem ähnelt, was von der Nicht-Streaming-API zurückgegeben worden wäre.
Für eine synchrone Antwort füge einen Stream.peek()-Aufruf zur Stream-Pipeline hinzu, um jedes Event zu akkumulieren:
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();Für eine asynchrone Antwort füge den MessageAccumulator zum subscribe()-Aufruf hinzu:
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();Ein BetaMessageAccumulator ist ebenfalls verfügbar für die Akkumulation eines BetaMessage-Objekts. Er wird auf die gleiche Weise wie der MessageAccumulator verwendet.
Für die vollständige Dokumentation zu strukturierten Ausgaben einschließlich Java-Beispielen siehe Strukturierte Ausgaben.
Tool-Nutzung mit Claude ermöglicht es dir, externe Tools und Funktionen direkt in die Antworten des KI-Modells zu integrieren. Anstatt reinen Text zu erzeugen, kann das Modell Anweisungen (mit Parametern) zum Aufrufen eines Tools oder einer Funktion ausgeben, wenn dies angebracht ist. Du definierst JSON-Schemas für Tools, und das Modell verwendet die Schemas, um zu bestimmen, wann und wie diese Tools verwendet werden sollen.
Die Tool-Nutzung unterstützt einen „strict"-Modus, der garantiert, dass die JSON-Ausgabe des KI-Modells dem JSON-Schema entspricht, das du in den Eingabeparametern angibst.
Das SDK kann ein Tool und seine Parameter automatisch aus der Struktur einer beliebigen Java-Klasse ableiten: Der Name der Klasse (in Snake Case konvertiert) liefert den Tool-Namen, und die Felder der Klasse definieren die Parameter des Tools.
Deklariere deine Tool-Klassen als Top-Level-Klassen oder static verschachtelte Klassen. Diese Anforderung stammt von der Jackson-Databind-Bibliothek (com.fasterxml.jackson.databind), die das SDK verwendet, um Tool-Eingaben in deine Klasseninstanzen zu deserialisieren, und die keine nicht-statischen inneren Klassen instanziieren kann.
import com.fasterxml.jackson.annotation.JsonClassDescription;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
enum Unit {
CELSIUS,
FAHRENHEIT;
public String toString() {
switch (this) {
case CELSIUS:
return "C";
case FAHRENHEIT:
default:
return "F";
}
}
public double fromKelvin(double temperatureK) {
switch (this) {
case CELSIUS:
return temperatureK - 273.15;
case FAHRENHEIT:
default:
return (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":
temperatureK = 300.0;
break;
case "New York, NY":
temperatureK = 310.0;
break;
case "Dallas, TX":
temperatureK = 305.0;
break;
default:
temperatureK = 295;
break;
}
return new Weather(String.format("%.0f%s", unit.fromKelvin(temperatureK), unit));
}
}
static class Weather {
public String temperature;
public Weather(String temperature) {
this.temperature = temperature;
}
}Wenn deine Tool-Klassen definiert sind, füge sie mit MessageCreateParams.Builder.addTool(Class<T>) zu den Message-Parametern hinzu und rufe sie dann auf, wenn dies in der Antwort des KI-Modells angefordert wird. BetaToolUseBlock.input(Class<T>) kann verwendet werden, um die Parameter eines Tools in JSON-Form in eine Instanz deiner Tool-definierenden Klasse zu parsen.
Nach dem Aufruf des Tools verwende BetaToolResultBlockParam.Builder.contentAsJson(Object), um das Ergebnis des Tools an das KI-Modell zurückzugeben:
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_4_8)
.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
// Füge eine Nachricht hinzu, die angibt, dass die Tool-Nutzung angefordert wurde.
.addAssistantMessageOfBetaContentBlockParams(
List.of(BetaContentBlockParam.ofToolUse(BetaToolUseBlockParam.builder()
.name(toolUseBlock.name())
.id(toolUseBlock.id())
.input(toolUseBlock._input())
.build())))
// Füge eine Nachricht mit dem Ergebnis der angeforderten Tool-Nutzung hinzu.
.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");
}Tool-Namen werden von den Camel-Case-Tool-Klassennamen (z. B. GetWeather) abgeleitet und in Snake Case konvertiert (z. B. get_weather). Wortgrenzen beginnen dort, wo das aktuelle Zeichen nicht das erste Zeichen ist, großgeschrieben ist und entweder das vorhergehende Zeichen kleingeschrieben ist oder das folgende Zeichen kleingeschrieben ist. Zum Beispiel wird MyJSONParser zu my_json_parser und ParseJSON zu parse_json. Diese Konvertierung kann mit der Annotation @JsonTypeName überschrieben werden.
Du kannst eine lokale Validierung durchführen, um zu überprüfen, ob das aus deiner Tool-Klasse abgeleitete JSON-Schema die Einschränkungen von Anthropic einhält. Die lokale Validierung ist standardmäßig aktiviert, kann aber deaktiviert werden:
MessageCreateParams.Builder createParamsBuilder = MessageCreateParams.builder()
.model(Model.CLAUDE_OPUS_4_8)
.maxTokens(2048)
.addTool(GetWeather.class, JsonSchemaLocalValidation.NO)
.addUserMessage("What's the temperature in New York?");Du kannst Annotationen verwenden, um den JSON-Schemas weitere Informationen über Tools hinzuzufügen:
@JsonClassDescription – Füge einer Tool-Klasse eine Beschreibung hinzu, die erläutert, wann und wie dieses Tool verwendet werden soll.@JsonTypeName – Setze den Tool-Namen auf etwas anderes als den einfachen Namen der Klasse, konvertiert in Snake Case.@JsonPropertyDescription – Füge einem Tool-Parameter eine detaillierte Beschreibung hinzu.@JsonIgnore – Schließe ein public-Feld oder eine Getter-Methode aus dem generierten JSON-Schema für die Parameter eines Tools aus.@JsonProperty – Schließe ein nicht-public-Feld oder eine Getter-Methode in das generierte JSON-Schema für die Parameter eines Tools ein.Das SDK bietet Unterstützung für Batch-Verarbeitung unter dem Namespace client.messages().batches(). Siehe Paginierung für Informationen zum Auflisten und Paginieren durch Batches.
Das SDK definiert Methoden, die Dateien über die Klasse MultipartField akzeptieren:
import com.anthropic.core.MultipartField;
import com.anthropic.models.beta.files.FileMetadata;
import com.anthropic.models.beta.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.beta().files().upload(params);Oder von einem InputStream:
import com.anthropic.core.MultipartField;
import com.anthropic.models.beta.files.FileMetadata;
import com.anthropic.models.beta.files.FileUploadParams;
FileUploadParams params = FileUploadParams.builder()
.file(
MultipartField.<InputStream>builder()
.value(new URL("https://example.com/path/to/file").openStream())
.filename("document.pdf")
.contentType("application/pdf")
.build()
)
.build();
FileMetadata fileMetadata = client.beta().files().upload(params);Oder von In-Memory-Bytes:
import com.anthropic.core.MultipartField;
import com.anthropic.models.beta.files.FileMetadata;
import com.anthropic.models.beta.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.beta().files().upload(params);Das SDK definiert Methoden, die binäre Antworten für API-Antworten zurückgeben, die nicht unbedingt als JSON geparst werden:
import com.anthropic.core.http.HttpResponse;
HttpResponse response = client.beta().files().download("file_id");Um den Antwortinhalt in einer Datei zu speichern:
import com.anthropic.core.http.HttpResponse;
try (HttpResponse response = client.beta().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);
}Oder übertrage den Antwortinhalt an einen beliebigen OutputStream:
import com.anthropic.core.http.HttpResponse;
try (HttpResponse response = client.beta().files().download(params)) {
response.body().transferTo(Files.newOutputStream(Paths.get(path)));
} catch (Exception e) {
IO.println("Something went wrong!");
throw new RuntimeException(e);
}Das SDK wirft benutzerdefinierte Unchecked-Exception-Typen:
AnthropicServiceException – Basisklasse für HTTP-Fehler.AnthropicIoException – I/O-Netzwerkfehler.AnthropicRetryableException – Generischer Fehler, der einen Fehlschlag anzeigt, der wiederholt werden könnte.AnthropicInvalidDataException – Fehler beim Interpretieren erfolgreich geparster Daten (z. B. beim Zugriff auf eine Property, die eigentlich erforderlich sein sollte, aber von der API unerwartet weggelassen wurde).AnthropicException – Basisklasse für alle Exceptions.| Status | Exception |
|---|---|
| 400 | BadRequestException |
| 401 | UnauthorizedException |
| 403 | PermissionDeniedException |
| 404 | NotFoundException |
| 422 | UnprocessableEntityException |
| 429 | RateLimitException |
| 5xx | InternalServerException |
| andere | UnexpectedStatusCodeException |
SseException wird für Fehler geworfen, die während des SSE-Streamings nach einer erfolgreichen initialen HTTP-Antwort auftreten.
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());
}Bei Verwendung von Raw-Responses kannst du auf den request-id-Response-Header mit der Methode requestId() zugreifen:
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();Dies kann verwendet werden, um fehlgeschlagene Anfragen schnell zu protokollieren und an Anthropic zu melden. Weitere Informationen zum Debuggen von Anfragen findest du unter Request-ID.
Das SDK wiederholt standardmäßig automatisch 2 Mal, mit einem kurzen exponentiellen Backoff zwischen den Anfragen.
Nur die folgenden Fehlertypen werden wiederholt:
Die API kann das SDK auch explizit anweisen, eine Anfrage zu wiederholen oder nicht zu wiederholen.
Um eine benutzerdefinierte Anzahl von Wiederholungsversuchen festzulegen, konfiguriere den Client mit der Methode maxRetries:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
AnthropicClient client = AnthropicOkHttpClient.builder().fromEnv().maxRetries(4).build();Anfragen laufen standardmäßig nach 10 Minuten ab.
Für Methoden, die maxTokens akzeptieren, wird jedoch, wenn du einen großen maxTokens-Wert angibst und Streaming verwendest, das Standard-Timeout dynamisch mit dieser Formel berechnet:
Duration.ofSeconds(
Math.min(
60 * 60, // 1 hour max
Math.max(
10 * 60, // 10 minute minimum
60 * 60 * maxTokens / 128_000
)
)
)Dies führt zu einem Timeout von bis zu 60 Minuten, skaliert durch den maxTokens-Parameter, sofern nicht überschrieben.
Für Nicht-Streaming-Anfragen skaliert das dynamische Timeout von einem Minimum von 30 Sekunden bis zu einem Maximum von 10 Minuten basierend auf maxTokens.
Um ein benutzerdefiniertes Timeout pro Anfrage festzulegen:
import com.anthropic.models.messages.Message;
Message message = client
.messages()
.create(params, RequestOptions.builder().timeout(Duration.ofSeconds(30)).build());Oder konfiguriere den Standard für alle Methodenaufrufe auf Client-Ebene:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
AnthropicClient client = AnthropicOkHttpClient.builder()
.fromEnv()
.timeout(Duration.ofSeconds(30))
.build();Erwäge die Verwendung von Streaming für länger laufende Anfragen.
Vermeide es, einen großen maxTokens-Wert ohne Streaming zu setzen. Einige Netzwerke können inaktive Verbindungen nach einer bestimmten Zeit trennen, was dazu führen kann, dass die Anfrage fehlschlägt oder ein Timeout auftritt, ohne eine Antwort von Anthropic zu erhalten. Das SDK pingt die API regelmäßig an, um die Verbindung aufrechtzuerhalten und die Auswirkungen dieser Netzwerke zu reduzieren.
Das SDK wirft einen Fehler, wenn erwartet wird, dass eine Nicht-Streaming-Anfrage länger als 10 Minuten dauert. Die Verwendung einer Streaming-Methode oder das Überschreiben des Timeouts auf Client- oder Anfrageebene deaktiviert den Fehler.
Das SDK bietet bequeme Möglichkeiten, auf paginierte Ergebnisse entweder seitenweise oder elementweise über alle Seiten hinweg zuzugreifen.
Um durch alle Ergebnisse über alle Seiten hinweg zu iterieren, verwende die Methode autoPager(), die bei Bedarf automatisch weitere Seiten abruft.
import com.anthropic.models.messages.batches.BatchListPage;
import com.anthropic.models.messages.batches.MessageBatch;
BatchListPage page = client.messages().batches().list();
// Als Iterable verarbeiten
for (MessageBatch batch : page.autoPager()) {
IO.println(batch);
}
// Als Stream verarbeiten
page.autoPager()
.stream()
.limit(50)
.forEach(batch -> IO.println(batch));Bei Verwendung des asynchronen Clients gibt die Methode eine AsyncStreamResponse zurück:
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);
}));
// Falls du Fehler oder den Abschluss des Streams behandeln musst
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!");
}
}
}));
// Oder verwende 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!");
}
}));Um auf einzelne Seitenelemente zuzugreifen und die nächste Seite manuell anzufordern:
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();
}Jede Klasse im SDK hat einen zugehörigen Builder zum Erstellen. Jede Klasse ist nach der Erstellung unveränderlich. Wenn die Klasse einen zugehörigen Builder hat, dann hat sie eine toBuilder()-Methode, die verwendet werden kann, um sie zurück in einen Builder zu konvertieren, um eine modifizierte Kopie zu erstellen.
MessageCreateParams params = MessageCreateParams.builder()
.maxTokens(1024L)
.addUserMessage("Hello, Claude")
.model(Model.CLAUDE_OPUS_4_8)
.build();
// Erstelle eine modifizierte Kopie mit toBuilder()
MessageCreateParams modified = params.toBuilder().maxTokens(2048L).build();Da jede Klasse unveränderlich ist, wirkt sich eine Builder-Modifikation niemals auf bereits erstellte Klasseninstanzen aus.
Um eine Anfrage an die Claude API zu senden, erstelle eine Instanz einer Params-Klasse und übergib sie an die entsprechende Client-Methode. Wenn die Antwort empfangen wird, wird sie in eine Instanz einer Java-Klasse deserialisiert.
Zum Beispiel sollte client.messages().create(...) mit einer Instanz von MessageCreateParams aufgerufen werden, und es wird eine Instanz von Message zurückgeben.
Um undokumentierte Parameter zu setzen, rufe die Methoden putAdditionalHeader, putAdditionalQueryParam oder putAdditionalBodyProperty auf einer beliebigen Params-Klasse auf:
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();Auf diese kann später am erstellten Objekt mit den Methoden _additionalHeaders(), _additionalQueryParams() und _additionalBodyProperties() zugegriffen werden.
Die an diese Methoden übergebenen Werte überschreiben Werte, die an frühere Methoden übergeben wurden. Stelle aus Sicherheitsgründen sicher, dass diese Methoden nur mit vertrauenswürdigen Eingabedaten verwendet werden.
Um undokumentierte Parameter auf verschachtelten Headern, Query-Params oder Body-Klassen zu setzen:
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();Auf diese Properties kann später am verschachtelten erstellten Objekt mit der Methode _additionalProperties() zugegriffen werden.
Um einen dokumentierten Parameter oder eine Property auf einen undokumentierten oder noch nicht unterstützten Wert zu setzen, übergib ein JsonValue-Objekt an seinen Setter:
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_4_8)
.build();Der einfachste Weg, ein JsonValue zu erstellen, ist die Verwendung seiner from(...)-Methode:
import com.anthropic.core.JsonValue;
// Erstelle primitive JSON-Werte
JsonValue nullValue = JsonValue.from(null);
JsonValue booleanValue = JsonValue.from(true);
JsonValue numberValue = JsonValue.from(42);
JsonValue stringValue = JsonValue.from("Hello World!");
// Erstelle einen JSON-Array-Wert äquivalent zu `["Hello", "World"]`
JsonValue arrayValue = JsonValue.from(List.of("Hello", "World"));
// Erstelle einen JSON-Objekt-Wert äquivalent zu `{ "a": 1, "b": 2 }`
JsonValue objectValue = JsonValue.from(Map.of("a", 1, "b", 2));
// Erstelle ein beliebig verschachteltes JSON äquivalent zu:
// { "a": [1, 2], "b": [3, 4] }
JsonValue complexValue = JsonValue.from(Map.of("a", List.of(1, 2), "b", List.of(3, 4)));Normalerweise wirft die build-Methode einer Builder-Klasse eine IllegalStateException, wenn ein erforderlicher Parameter oder eine Property nicht gesetzt ist. Um einen erforderlichen Parameter oder eine Property erzwungen wegzulassen, übergib 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_4_8)
.maxTokens(JsonMissing.of())
.build();Um auf undokumentierte Response-Properties zuzugreifen, rufe die Methode _additionalProperties() auf:
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!";
}
// Weitere Methoden sind `visitMissing`, `visitString`, `visitArray` und `visitObject`
// Die Standardimplementierung jeder nicht implementierten Methode delegiert an `visitDefault`,
// die standardmäßig eine Exception wirft, aber auch überschrieben werden kann
});Um auf den rohen JSON-Wert einer Property zuzugreifen, rufe ihre mit _ präfixierte Methode auf:
import com.anthropic.core.JsonField;
import com.anthropic.models.messages.StopReason;
JsonField<StopReason> stopReason = client.messages().create(params)._stopReason();
if (stopReason.isMissing()) {
// Die Eigenschaft fehlt in der JSON-Antwort
} else if (stopReason.isNull()) {
// Die Eigenschaft wurde auf literales null gesetzt
} else {
// Prüfe, ob der Wert als String übergeben wurde
// Weitere Methoden sind `asNumber()`, `asBoolean()` usw.
Optional<String> jsonString = stopReason.asString();
// Versuche, in einen benutzerdefinierten Typ zu deserialisieren
MyClass myObject = stopReason.asUnknown().orElseThrow().convert(MyClass.class);
}Standardmäßig wirft das SDK keine Exception, wenn die API eine Antwort zurückgibt, die nicht dem erwarteten Typ entspricht. Es wirft AnthropicInvalidDataException nur, wenn du direkt auf die Property zugreifst.
Um vorab zu überprüfen, ob die Antwort vollständig korrekt typisiert ist, rufe validate() auf:
import com.anthropic.models.messages.Message;
Message message = client.messages().create(params).validate();Oder konfiguriere pro Anfrage:
import com.anthropic.models.messages.Message;
Message message = client
.messages()
.create(params, RequestOptions.builder().responseValidation(true).build());Oder konfiguriere den Standard für alle Methodenaufrufe auf Client-Ebene:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
AnthropicClient client = AnthropicOkHttpClient.builder()
.fromEnv()
.responseValidation(true)
.build();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();Die meisten Anwendungen sollten diese Methoden nicht aufrufen und stattdessen die Systemstandards verwenden. Die Standards enthalten spezielle Optimierungen, die verloren gehen können, wenn die Implementierungen geändert werden.
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
AnthropicClient client = AnthropicOkHttpClient.builder()
.fromEnv()
.sslSocketFactory(yourSSLSocketFactory)
.trustManager(yourTrustManager)
.hostnameVerifier(yourHostnameVerifier)
.build();Das SDK besteht aus drei Artefakten:
anthropic-java-core – Enthält die Kern-SDK-Logik, hängt nicht von OkHttp ab. Stellt AnthropicClient, AnthropicClientAsync und deren Implementierungsklassen bereit, die alle mit jedem HTTP-Client funktionieren können.anthropic-java-client-okhttp – Hängt von OkHttp ab. Stellt AnthropicOkHttpClient und AnthropicOkHttpClientAsync bereit.anthropic-java – Hängt von den APIs von anthropic-java-core und anthropic-java-client-okhttp ab und stellt diese bereit. Hat keine eigene Logik.Diese Struktur ermöglicht es, den Standard-HTTP-Client des SDK zu ersetzen, ohne unnötige Abhängigkeiten einzubinden.
Probiere die verfügbaren Netzwerkoptionen aus, bevor du den Standard-Client ersetzt.
Um einen angepassten OkHttpClient zu verwenden:
anthropic-java-Abhängigkeit durch anthropic-java-core.OkHttpClient-Klasse von anthropic-java-client-okhttp in deinen Code und passe sie an.AnthropicClientImpl oder AnthropicClientAsyncImpl mit deinem angepassten Client.Um einen vollständig benutzerdefinierten HTTP-Client zu verwenden:
anthropic-java-Abhängigkeit durch anthropic-java-core.HttpClient-Interface implementiert.AnthropicClientImpl oder AnthropicClientAsyncImpl mit deiner neuen Client-Klasse.Für detaillierte Plattform-Einrichtungsanleitungen mit Codebeispielen siehe:
Das Java SDK unterstützt die folgenden Plattformen über separate Abhängigkeiten, die plattformspezifische Backend-Implementierungen bereitstellen:
com.anthropic:anthropic-java-bedrock: Verwende BedrockMantleBackend.fromEnv() oder BedrockMantleBackend.builder() für den Messages-API-Bedrock-Endpunkt, oder BedrockBackend.fromEnv() / BedrockBackend.builder() (bedrock-runtime-Pfad).com.anthropic:anthropic-java-vertex: Verwende VertexBackend.fromEnv() oder VertexBackend.builder().com.anthropic:anthropic-java-foundry: Verwende FoundryBackend.fromEnv() oder FoundryBackend.builder().com.anthropic:anthropic-java-aws: Verwende (liest und die AWS-Standard-Region/Credential-Chain) oder . Verfügbar in Beta.Verwende BedrockMantleBackend für neue Projekte; BedrockBackend bleibt für bestehende Anwendungen, die die Bedrock-InvokeModel-API verwenden.
Jede Backend-Implementierung wird mit .backend() auf AnthropicOkHttpClient.builder() an den Client übergeben. Jedes Cloud-Backend zieht seine jeweiligen Cloud-Plattform-SDK-Klassen als transitive Abhängigkeiten ein.
Um auf HTTP-Header, Statuscodes und den rohen Response-Body zuzugreifen, stelle jedem HTTP-Methodenaufruf withRawResponse() voran:
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_4_8)
.build();
HttpResponseFor<Message> message = client.messages().withRawResponse().create(params);
int statusCode = message.statusCode();
Headers headers = message.headers();Du kannst die Antwort bei Bedarf weiterhin in eine Instanz einer Java-Klasse deserialisieren:
import com.anthropic.models.messages.Message;
Message parsedMessage = message.parse();Das SDK verwendet den Standard-OkHttp-Logging-Interceptor.
Aktiviere das Logging, indem du die Umgebungsvariable ANTHROPIC_LOG auf info setzt:
export ANTHROPIC_LOG=infoOder auf debug für ausführlicheres Logging:
export ANTHROPIC_LOG=debugDas SDK ist für die bequeme Verwendung der dokumentierten API typisiert. Es unterstützt jedoch auch die Arbeit mit undokumentierten oder noch nicht unterstützten Teilen der API.
Um undokumentierte Request-Parameter zu setzen, verwende die Methoden putAdditionalHeader, putAdditionalQueryParam oder putAdditionalBodyProperty wie in Undokumentierte Parameter beschrieben.
Um auf undokumentierte Response-Properties zuzugreifen, verwende die Methode _additionalProperties() wie in Response-Properties beschrieben.
Enum-ähnliche Klassen im SDK, wie Model und AnthropicBeta, sind keine geschlossenen Java-enum-Typen. Jede bietet eine of(String)-Factory-Methode, die jeden String akzeptiert, sodass du Werte verwenden kannst, die noch nicht zum SDK hinzugefügt wurden, wie z. B. ein Modell oder einen Beta-Header, der nach deiner SDK-Version veröffentlicht wurde:
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-Methoden, die diese Typen akzeptieren, bieten oft auch eine String-Überladung, die of(...) für dich aufruft:
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();Bevorzuge die gut typisierten Konstanten (zum Beispiel Model.CLAUDE_OPUS_4_7), damit du Autovervollständigung und Deprecation-Warnungen erhältst. Die String-Überladungen und of(...) sind hauptsächlich dafür gedacht, das Feld auf einen undokumentierten oder noch nicht unterstützten Wert zu setzen, während du auf ein SDK-Release wartest, das ihn enthält.
Beta-Funktionen sind vor der allgemeinen Veröffentlichung verfügbar, um frühes Feedback zu erhalten und neue Funktionalität zu testen. Du kannst die Verfügbarkeit aller Fähigkeiten und Tools von Claude in der Übersicht zum Entwickeln mit Claude überprüfen.
Du kannst auf die meisten Beta-API-Funktionen über die Methode beta() auf dem Client zugreifen. Um eine bestimmte Beta-Funktion zu aktivieren, füge den entsprechenden Beta-Header mit .addBeta() beim Erstellen der Message-Params hinzu.
Zum Beispiel, um die Files API zu verwenden:
import com.anthropic.models.beta.AnthropicBeta;
import com.anthropic.models.beta.messages.BetaContentBlockParam;
import com.anthropic.models.beta.messages.BetaMessage;
import com.anthropic.models.beta.messages.BetaRequestDocumentBlock;
import com.anthropic.models.beta.messages.BetaTextBlockParam;
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_4_8)
.maxTokens(1024L)
.addBeta(AnthropicBeta.FILES_API_2025_04_14)
.addUserMessageOfBetaContentBlockParams(List.of(
BetaContentBlockParam.ofText(
BetaTextBlockParam.builder()
.text("Please summarize this document for me.")
.build()),
BetaContentBlockParam.ofDocument(
BetaRequestDocumentBlock.builder()
.fileSource("file_abc123")
.build())))
.build());
}Dieses Paket folgt im Allgemeinen den SemVer-Konventionen, obwohl bestimmte abwärtsinkompatible Änderungen als Minor-Versionen veröffentlicht werden können:
Was this page helpful?
"https://api.anthropic.com" |
AwsBackend.fromEnv()ANTHROPIC_AWS_WORKSPACE_IDAwsBackend.builder()