This package provides an integration layer between the LangChain4j framework and Anthropic's Claude language models, enabling Java developers to seamlessly incorporate Anthropic's AI capabilities into their applications.
The langchain4j-anthropic integration supports various content types for rich multimodal interactions. Content types define how information is structured in messages exchanged with Claude models.
Claude models can process and generate multiple content types:
Standard text messages are the most common content type.
package dev.langchain4j.data.message;
/**
* Text content for messages.
* Thread-safe (immutable).
*/
public class TextContent implements Content {
/**
* Creates text content from string.
*
* @param text text content, must not be null
* @return text content instance, never null
* @throws IllegalArgumentException if text is null
*/
public static TextContent from(String text);
/**
* Returns text content.
*
* @return text string, never null
*/
public String text();
}Usage Example:
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.data.message.TextContent;
// Simple text message
UserMessage message = UserMessage.from("What is the capital of France?");
// Explicit text content
TextContent textContent = TextContent.from("Explain quantum computing");
UserMessage message2 = UserMessage.from(textContent);Error Handling:
IllegalArgumentException: text is nullNull Safety:
Usage:
Visual content for vision-enabled models. Images must be Base64-encoded with a MIME type.
package dev.langchain4j.data.message;
import dev.langchain4j.data.image.Image;
/**
* Image content for vision models.
* Thread-safe (immutable).
*/
public class ImageContent implements Content {
/**
* Creates image content from Image.
*
* @param image the image with Base64 data and MIME type, must not be null
* @return image content instance, never null
* @throws IllegalArgumentException if image is null
*/
public static ImageContent from(Image image);
/**
* Returns the image.
*
* @return image instance, never null
*/
public Image image();
}package dev.langchain4j.data.image;
/**
* Image with Base64-encoded data.
* Thread-safe (immutable).
*/
public class Image {
/**
* Creates new image builder.
*
* @return new builder, never null
*/
public static Builder builder();
/**
* Returns Base64-encoded image data.
*
* @return Base64 string without data URI prefix, never null
*/
public String base64Data();
/**
* Returns MIME type.
*
* @return MIME type (e.g., "image/jpeg"), never null
*/
public String mimeType();
public static class Builder {
/**
* Sets Base64-encoded image data.
*
* @param base64Data Base64 string without prefix, must not be null
* @return this builder, never null
* @throws IllegalArgumentException if base64Data is null
* @default no default - REQUIRED
*/
public Builder base64Data(String base64Data);
/**
* Sets image MIME type.
*
* @param mimeType MIME type string, must not be null, must be supported
* @return this builder, never null
* @throws IllegalArgumentException if mimeType is null or unsupported
* @default no default - REQUIRED
*/
public Builder mimeType(String mimeType);
/**
* Builds the image.
*
* @return image instance, never null
* @throws IllegalStateException if base64Data or mimeType missing
*/
public Image build();
}
}Usage Example:
import dev.langchain4j.data.message.ImageContent;
import dev.langchain4j.data.message.TextContent;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.data.image.Image;
// Create image from Base64 data
String base64Data = /* Base64-encoded image */;
Image image = Image.builder()
.base64Data(base64Data)
.mimeType("image/jpeg")
.build();
ImageContent imageContent = ImageContent.from(image);
// Combine image with text
UserMessage message = UserMessage.from(
imageContent,
TextContent.from("What's in this image?")
);Supported MIME Types:
image/jpeg - JPEG images (.jpg, .jpeg)image/png - PNG images (.png)image/gif - GIF images (.gif)image/webp - WebP images (.webp)Error Handling:
IllegalArgumentException: Unsupported MIME typeRuntimeException: Image too large (>5MB recommended max)RuntimeException: Invalid Base64 encodingIllegalStateException: Missing required fields in builderSize Constraints:
Common Pitfalls:
❌ DON'T include data URI prefix
.base64Data("data:image/jpeg;base64,/9j/...") // Wrong!✅ DO use raw Base64
.base64Data("/9j/4AAQSkZJRg...") // Correct❌ DON'T send image URLs
Image.builder().url("https://...").build() // Not supported✅ DO convert to Base64
String base64 = Base64.getEncoder().encodeToString(imageBytes);
Image.builder().base64Data(base64).mimeType("image/jpeg").build();Usage:
Process PDF documents directly. PDFs can be provided via Base64 encoding or URL.
package dev.langchain4j.data.message;
/**
* PDF document content.
* Thread-safe (immutable).
*/
public class PdfFileContent implements Content {
/**
* Creates PDF content from Base64 data.
*
* @param base64Data Base64-encoded PDF, must not be null
* @param mimeType MIME type (must be "application/pdf"), must not be null
* @return PDF content instance, never null
* @throws IllegalArgumentException if parameters are null or mimeType invalid
*/
public static PdfFileContent from(String base64Data, String mimeType);
/**
* Creates PDF content from URL.
* URL must be publicly accessible or support authentication headers.
*
* @param url PDF document URL, must not be null
* @return PDF content instance, never null
* @throws IllegalArgumentException if url is null
*/
public static PdfFileContent from(String url);
}Usage Example:
import dev.langchain4j.data.message.PdfFileContent;
import dev.langchain4j.data.message.TextContent;
import dev.langchain4j.data.message.UserMessage;
// PDF from Base64
String base64Pdf = /* Base64-encoded PDF data */;
PdfFileContent pdfContent = PdfFileContent.from(base64Pdf, "application/pdf");
// Combine PDF with question
UserMessage message = UserMessage.from(
pdfContent,
TextContent.from("Summarize this document")
);
// PDF from URL (if supported)
PdfFileContent pdfFromUrl = PdfFileContent.from("https://example.com/doc.pdf");
UserMessage message2 = UserMessage.from(
pdfFromUrl,
TextContent.from("What are the key findings?")
);Error Handling:
RuntimeException: PDF too large (>32MB recommended max)RuntimeException: Invalid PDF format or corrupted fileRuntimeException: URL not accessible (if using URL method)IllegalArgumentException: Invalid mimeType (must be "application/pdf")Size Constraints:
Common Pitfalls:
❌ DON'T use wrong MIME type
PdfFileContent.from(base64, "application/octet-stream") // Wrong!✅ DO use correct MIME type
PdfFileContent.from(base64, "application/pdf") // CorrectUsage:
Represents function/tool calls made by the model. These are generated by Claude when it decides to use a tool.
package dev.langchain4j.data.message;
/**
* Tool execution request from model.
* Immutable after creation.
*/
public class ToolExecutionRequest {
/**
* Returns unique execution request ID.
* Use this ID when sending tool results back.
*
* @return request ID, never null
*/
public String id();
/**
* Returns tool name to execute.
* Matches a tool name from ToolSpecification.
*
* @return tool name, never null
*/
public String name();
/**
* Returns JSON-encoded tool arguments.
* Parse as JSON object to extract parameters.
*
* @return arguments JSON string, never null (may be empty object "{}")
*/
public String arguments();
}Usage Example:
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ToolExecutionRequest;
import java.util.List;
// Tool calls are returned in AI messages
ChatResponse response = model.chat(request);
AiMessage aiMessage = response.aiMessage();
if (aiMessage.hasToolExecutionRequests()) {
List<ToolExecutionRequest> toolCalls = aiMessage.toolExecutionRequests();
for (ToolExecutionRequest toolCall : toolCalls) {
String id = toolCall.id(); // Unique call ID
String name = toolCall.name(); // Tool name
String arguments = toolCall.arguments(); // JSON arguments
System.out.println("Tool: " + name);
System.out.println("Arguments: " + arguments);
}
}Fields:
id: Unique identifier for the tool call, used when sending results backname: Name of the tool to execute, matches ToolSpecification namearguments: JSON string containing tool parametersError Handling:
Null Safety:
Usage:
Represents the results of tool/function executions sent back to the model.
package dev.langchain4j.data.message;
/**
* Tool execution result to send back to model.
* Immutable after creation.
*/
public class ToolExecutionResultMessage implements ChatMessage {
/**
* Creates tool result from execution request and result string.
* Links result to original request via ID.
*
* @param request the original tool execution request, must not be null
* @param result the tool execution result (any format), must not be null
* @return result message, never null
* @throws IllegalArgumentException if parameters are null
*/
public static ToolExecutionResultMessage from(ToolExecutionRequest request, String result);
/**
* Creates tool result from explicit ID, name, and result.
*
* @param id tool execution ID, must not be null
* @param toolName tool name, must not be null
* @param result execution result, must not be null
* @return result message, never null
* @throws IllegalArgumentException if parameters are null
*/
public static ToolExecutionResultMessage from(String id, String toolName, String result);
/**
* Returns tool execution ID.
*
* @return ID linking to tool use request, never null
*/
public String id();
/**
* Returns tool name.
*
* @return tool name, never null
*/
public String toolName();
/**
* Returns result text.
*
* @return result string, never null
*/
public String text();
}Usage Example:
import dev.langchain4j.data.message.ToolExecutionResultMessage;
import dev.langchain4j.data.message.ToolExecutionRequest;
// Execute tool and return result
ToolExecutionRequest request = /* from AI message */;
String toolResult = executeMyTool(request.name(), request.arguments());
// Create tool result message
ToolExecutionResultMessage resultMessage =
ToolExecutionResultMessage.from(request, toolResult);
// Send back to model
ChatResponse nextResponse = model.chat(ChatRequest.builder()
.messages(
previousUserMessage,
aiMessageWithToolCall,
resultMessage
)
.build());Fields:
toolUseId: ID linking back to the tool use requestcontent: String result of the tool executionisError: Boolean indicating if execution failedError Handling:
Common Pitfalls:
❌ DON'T forget to link result to request
ToolExecutionResultMessage.from("wrong-id", toolName, result) // ID mismatch!✅ DO use request object
ToolExecutionResultMessage.from(request, result) // Correct linkingUsage:
Extended reasoning text from models with thinking capabilities (e.g., Claude Opus 4.5+).
package dev.langchain4j.data.message;
/**
* AI message with thinking support.
* Immutable after creation.
*/
public class AiMessage implements ChatMessage {
/**
* Returns thinking/reasoning text if enabled.
* Only present when returnThinking(true) configured on model.
* Null if thinking disabled or not supported by model.
*
* @return thinking text or null if not available
*/
public String thinking();
}Usage Example:
import dev.langchain4j.data.message.AiMessage;
// Configure model with thinking
AnthropicChatModel model = AnthropicChatModel.builder()
.apiKey(apiKey)
.modelName(AnthropicChatModelName.CLAUDE_OPUS_4_5_20251101)
.thinkingType("enabled")
.thinkingBudgetTokens(10000)
.returnThinking(true) // Required to receive thinking
.build();
// Get thinking from response
ChatResponse response = model.chat(request);
AiMessage aiMessage = response.aiMessage();
String thinking = aiMessage.thinking();
if (thinking != null) {
System.out.println("Claude's reasoning:");
System.out.println(thinking);
}
String answer = aiMessage.text();
System.out.println("\nAnswer:");
System.out.println(answer);Properties:
thinking: The reasoning text, may be nullsignature: Optional cryptographic signature (model-specific, in metadata)Error Handling:
Null Safety:
Usage:
In streaming mode, thinking can be received incrementally.
package dev.langchain4j.model.chat.response;
/**
* Partial thinking content during streaming.
* Immutable snapshot.
*/
public class PartialThinking {
/**
* Returns partial thinking text fragment.
*
* @return thinking text fragment, never null
*/
public String text();
}Usage Example:
import dev.langchain4j.model.chat.response.PartialThinking;
model.doChat(request, new StreamingChatResponseHandler() {
@Override
public void onPartialThinking(PartialThinking thinking) {
// Thinking text as it's generated
System.out.print(thinking.text());
}
@Override
public void onPartialResponse(String token) {
// Answer text after thinking
System.out.print(token);
}
@Override
public void onCompleteResponse(ChatResponse completeResponse) {
System.out.println("\nComplete");
}
@Override
public void onError(Throwable error) {
error.printStackTrace();
}
});Combine multiple content types in a single message for rich interactions.
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.data.message.ImageContent;
import dev.langchain4j.data.message.TextContent;
UserMessage message = UserMessage.from(
TextContent.from("Analyze this chart and explain the trends:"),
ImageContent.from(chartImage)
);UserMessage message = UserMessage.from(
PdfFileContent.from(pdfData, "application/pdf"),
TextContent.from("Extract all dates and names mentioned in this document")
);UserMessage message = UserMessage.from(
TextContent.from("Compare these two images:"),
ImageContent.from(image1),
ImageContent.from(image2)
);Error Handling:
Common Pitfalls:
❌ DON'T exceed total size limits
// 10 large images = request too large
UserMessage.from(images.toArray(new Content[0]))✅ DO limit content per request
// Max 4-5 images per request recommended
UserMessage.from(images.subList(0, 4).toArray(new Content[0]))Images:
Documents:
| Content Type | All Models | Vision Models | Thinking Models |
|---|---|---|---|
| Text | ✓ | ✓ | ✓ |
| Images | ✓ | ✓ | |
| PDFs | ✓ | ✓ | |
| Tool Use | ✓ | ✓ | ✓ |
| Tool Results | ✓ | ✓ | ✓ |
| Thinking | ✓ (Opus 4.5+) |
Vision Models:
Thinking Models:
returnThinking(true)Thread Safety:
Resource Lifecycle:
Install with Tessl CLI
npx tessl i tessl/maven-dev-langchain4j--langchain4j-anthropic@1.11.0