11 KiB
Claude API — Java
Note: The Java SDK supports the Claude API and beta tool use with annotated classes. Agent SDK is not yet available for Java.
Package Reference
Types are organized by package. If a class you need isn't shown in an example below, locate it via this table first — don't block on fetching SDK source over the network.
import prefix |
Contains |
|---|---|
com.anthropic.client / com.anthropic.client.okhttp |
AnthropicClient, AnthropicOkHttpClient |
com.anthropic.models.messages |
non-beta request/response types — MessageCreateParams, Model, Message, TextBlockParam, ContentBlockParam, ToolUseBlockParam, ToolResultBlockParam, CacheControlEphemeral, Tool* (e.g. ToolBash20250124, ToolTextEditor20250728), StopReason, StructuredMessage* |
com.anthropic.models.messages.batches |
Batch API — BatchResultsParams, MessageBatchIndividualResponse |
com.anthropic.models.beta |
AnthropicBeta (beta-flag constants) |
com.anthropic.models.beta.messages |
beta-endpoint types — MessageCreateParams, BetaMessage, BetaStopReason, BetaContextManagementConfig, BetaMcpToolset, BetaRequestMcpServerUrlDefinition, BetaTool* |
com.anthropic.core |
JsonValue, JsonField, JsonSchemaLocalValidation, com.anthropic.core.http.StreamResponse |
com.anthropic.errors |
typed exceptions — AnthropicServiceException, RateLimitException, NotFoundException, etc. (see shared/error-codes.md) |
client.messages() uses com.anthropic.models.messages.*; client.beta().messages() uses com.anthropic.models.beta.messages.*. Both packages define a MessageCreateParams — import the one matching the client path you call.
Key types per feature
Write from this table instead of javap/jar inspection. Endpoint column tells you whether to use client.messages() or client.beta().messages().
| Feature | Endpoint | Key Java types / builder calls |
|---|---|---|
| User profiles | beta | client.beta().userProfiles().create(...) / .retrieve(id) / .list(). Pass the returned profile id on the beta MessageCreateParams. Requires a beta header — check the SDK's beta-headers reference for the current flag. |
| Agent Skills | beta | BetaContainerParams, BetaSkillParams, BetaCodeExecutionTool20250825. .addBeta("code-execution-2025-08-25").addBeta("skills-2025-10-02"). Download the output via client.beta().files().download(fileId). |
| Cache diagnostics | beta | BetaDiagnosticsParam, BetaCacheControlEphemeral |
| Context editing | beta | .contextManagement(BetaContextManagementConfig.builder()…). The edit strategy is a BetaClearToolUses20250919Edit (or BetaClearThinking20251015Edit); its trigger is a BetaInputTokensTrigger built separately and passed to the edit's builder — there is no direct .inputTokensTrigger(N) shortcut on the edit builder. javap the edit and trigger classes for the exact setter names. |
| Memory tool | non-beta | .addTool(MemoryTool20250818.builder().build()) from com.anthropic.models.messages |
| Programmatic tool calling | non-beta | CodeExecutionTool20260120, Tool, ContentBlockParam |
| Strict tool use | non-beta | Tool, Tool.InputSchema |
| Task budgets | beta | .outputConfig(BetaOutputConfig.builder().taskBudget(BetaTokenTaskBudget.builder()...)) |
| Tool search | non-beta | .addTool(ToolSearchToolRegex20251119.builder()...) from com.anthropic.models.messages |
| Web search | non-beta | WebSearchTool20260209 from com.anthropic.models.messages — the latest variant with dynamic filtering (Opus 4.8/4.7/4.6 + Sonnet 4.6). For older models or Vertex, use WebSearchTool20250305 |
Discovering type and member names
If a class or builder method you need isn't in the tables above, jar tf <anthropic-java-core jar> | grep -i <term> or javap -classpath <jar> com.anthropic.models.… is fast enough to locate names. Do not compile and run a separate reflection program to enumerate members — the first build is slow enough to be backgrounded in many environments, trapping you in a polling loop. Write the script with the names you found and let the compiler error (cannot find symbol) point at any wrong member.
Installation
Maven:
<dependency>
<groupId>com.anthropic</groupId>
<artifactId>anthropic-java</artifactId>
<version>2.34.0</version>
</dependency>
Gradle:
implementation("com.anthropic:anthropic-java:2.34.0")
Client Initialization
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
// Default (reads ANTHROPIC_API_KEY from environment)
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
// Explicit API key
AnthropicClient client = AnthropicOkHttpClient.builder()
.apiKey("your-api-key")
.build();
Basic Message Request
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.Model;
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.CLAUDE_OPUS_4_8)
.maxTokens(16000L)
.addUserMessage("What is the capital of France?")
.build();
Message response = client.messages().create(params);
response.content().stream()
.flatMap(block -> block.text().stream())
.forEach(textBlock -> System.out.println(textBlock.text()));
Thinking
Adaptive thinking is the recommended mode for Claude 4.6+ models. Claude decides dynamically when and how much to think. The builder has a direct .thinking(ThinkingConfigAdaptive) overload — no manual union wrapping.
Fable 5, Opus 4.8, Opus 4.7, Opus 4.6, and Sonnet 4.6: Use adaptive thinking (below).
ThinkingConfigEnabled.builder().budgetTokens(N)is removed on Fable 5, Opus 4.8, and 4.7 (400 if sent); deprecated on Opus 4.6 and Sonnet 4.6. Older models: Use.thinking(ThinkingConfigEnabled.builder().budgetTokens(N).build())(budget must be <maxTokens, min 1024).
import com.anthropic.models.messages.ContentBlock;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;
import com.anthropic.models.messages.ThinkingConfigAdaptive;
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.CLAUDE_SONNET_4_6)
.maxTokens(16000L)
.thinking(ThinkingConfigAdaptive.builder().build())
.addUserMessage("Solve this step by step: 27 * 453")
.build();
for (ContentBlock block : client.messages().create(params).content()) {
block.thinking().ifPresent(t -> System.out.println("[thinking] " + t.thinking()));
block.text().ifPresent(t -> System.out.println(t.text()));
}
ContentBlock narrowing: .thinking() / .text() return Optional<T> — use .ifPresent(...) or .stream().flatMap(...). Alternative: isThinking() / asThinking() boolean+unwrap pairs (throws on wrong variant).
Effort Parameter
Effort is nested inside OutputConfig — there is NO .effort() directly on MessageCreateParams.Builder.
import com.anthropic.models.messages.OutputConfig;
.outputConfig(OutputConfig.builder()
.effort(OutputConfig.Effort.HIGH) // or LOW, MEDIUM, MAX
.build())
Combine with Thinking = ThinkingConfigAdaptive for cost-quality control.
Prompt Caching
System message as a list of TextBlockParam with CacheControlEphemeral. Use .systemOfTextBlockParams(...) — the plain .system(String) overload can't carry cache control. For placement patterns and the silent-invalidator audit checklist, see shared/prompt-caching.md.
import com.anthropic.models.messages.TextBlockParam;
import com.anthropic.models.messages.CacheControlEphemeral;
.systemOfTextBlockParams(List.of(
TextBlockParam.builder()
.text(longSystemPrompt)
.cacheControl(CacheControlEphemeral.builder()
.ttl(CacheControlEphemeral.Ttl.TTL_1H) // optional; also TTL_5M
.build())
.build()))
There's also a top-level .cacheControl(CacheControlEphemeral) on MessageCreateParams.Builder and on Tool.builder().
Verify hits via response.usage().cacheCreationInputTokens() / response.usage().cacheReadInputTokens().
Token Counting
import com.anthropic.models.messages.MessageCountTokensParams;
long tokens = client.messages().countTokens(
MessageCountTokensParams.builder()
.model(Model.CLAUDE_SONNET_4_6)
.addUserMessage("Hello")
.build()
).inputTokens();
PDF / Document Input
DocumentBlockParam builder has source shortcuts. Wrap in ContentBlockParam.ofDocument() and pass via .addUserMessageOfBlockParams().
import com.anthropic.models.messages.DocumentBlockParam;
import com.anthropic.models.messages.ContentBlockParam;
import com.anthropic.models.messages.TextBlockParam;
DocumentBlockParam doc = DocumentBlockParam.builder()
.source(Base64PdfSource.builder().data(base64String).build())
// or .source(UrlPdfSource.builder().url("https://...").build())
.title("My Document") // optional
.build();
For Files API document references, use the beta path and beta types — see files-api.md: BetaRequestDocumentBlock.builder().source(BetaFileDocumentSource.builder().fileId(id).build()).
.addUserMessageOfBlockParams(List.of(
ContentBlockParam.ofDocument(doc),
ContentBlockParam.ofText(TextBlockParam.builder().text("Summarize this").build())))
Stop Details
When stopReason() is "refusal", the response includes structured stopDetails():
response.stopDetails().ifPresent(details -> {
System.out.println("Category: " + details.category());
System.out.println("Explanation: " + details.explanation());
});
Refusal fallbacks ({{FABLE_NAME}}) — opt in by default. Fallbacks are opt-in: without them a refused request simply stops. New {{FABLE_ID}} code should include the server-side fallbacks parameter (beta header server-side-fallback-2026-06-01, fallback model {{OPUS_ID}}, on the beta messages call) by default. The exact Java builder methods (and the client-side middleware for providers without server-side support) are not documented here — WebFetch the Java SDK repo's examples/ from shared/live-sources.md; full semantics in shared/model-migration.md → Migrating to {{FABLE_NAME}} → refusal stop reason.
Error Type
AnthropicServiceException exposes .errorType() returning Optional<ErrorType> for programmatic error classification:
try {
client.messages().create(params);
} catch (AnthropicServiceException e) {
e.errorType().ifPresent(type ->
System.out.println("Error type: " + type) // RATE_LIMIT_ERROR, OVERLOADED_ERROR, etc.
);
}