AWS Bedrock integration for LangChain4j enabling Java applications to interact with various LLM providers through a unified interface
Fine-grained cache control for mixed static and dynamic content.
BedrockSystemMessage allows marking specific content blocks for caching. Use this when you need to mix static (cacheable) and dynamic (non-cacheable) content.
public class BedrockSystemMessage implements ChatMessage {
public static final int MAX_CONTENT_BLOCKS = 10;
public static final int MAX_CACHE_POINTS = 4;
public List<BedrockSystemContent> contents();
public boolean hasCachePoints();
public int cachePointCount();
public static Builder builder();
public static BedrockSystemMessage from(String text);
public static BedrockSystemMessage from(List<BedrockSystemContent> contents);
public static BedrockSystemMessage from(SystemMessage systemMessage);
}Important: BedrockSystemMessage is NOT a SystemMessage subclass. It implements ChatMessage directly.
public static class Builder {
public Builder contents(List<BedrockSystemContent> contents);
public Builder addContent(BedrockSystemContent content);
public Builder addText(String text); // No cache point
public Builder addTextWithCachePoint(String text); // With cache point
public BedrockSystemMessage build();
}import dev.langchain4j.model.bedrock.BedrockSystemMessage;
// Mix static and dynamic content
BedrockSystemMessage message = BedrockSystemMessage.builder()
.addTextWithCachePoint(loadStaticKnowledgeBase()) // Static: cached
.addText("Current date: " + LocalDate.now()) // Dynamic: not cached
.addTextWithCachePoint(loadStaticInstructions()) // Static: cached
.build();
ChatResponse response = model.chat(ChatRequest.builder()
.messages(message, UserMessage.from("Question"))
.build());public final class BedrockSystemTextContent implements BedrockSystemContent {
public static final int MAX_TEXT_LENGTH = 1_000_000;
public BedrockSystemTextContent(String text, boolean cachePoint);
public BedrockSystemTextContent(String text);
public String text();
public boolean hasCachePoint();
public BedrockSystemContentType type();
public static BedrockSystemTextContent from(String text);
public static BedrockSystemTextContent withCachePoint(String text);
}String knowledgeBase = loadLargeKnowledgeBase(); // >1024 tokens, static
String instructions = loadStaticInstructions(); // >1024 tokens, static
String currentDate = "Today is " + LocalDate.now(); // Dynamic
BedrockSystemMessage systemMessage = BedrockSystemMessage.builder()
.addTextWithCachePoint(knowledgeBase) // Cache point 1
.addText(currentDate) // No cache point
.addTextWithCachePoint(instructions) // Cache point 2
.build();
// Next day: date changes, but knowledge base and instructions still cached
String newDate = "Today is " + LocalDate.now();
BedrockSystemMessage updatedMessage = BedrockSystemMessage.builder()
.addTextWithCachePoint(knowledgeBase) // Same: cache hit
.addText(newDate) // Different: not cached anyway
.addTextWithCachePoint(instructions) // Same: cache hit
.build();// Use all 4 cache points
BedrockSystemMessage message = BedrockSystemMessage.builder()
.addTextWithCachePoint("Section 1: " + loadSection1()) // Cache point 1
.addTextWithCachePoint("Section 2: " + loadSection2()) // Cache point 2
.addTextWithCachePoint("Section 3: " + loadSection3()) // Cache point 3
.addTextWithCachePoint("Section 4: " + loadSection4()) // Cache point 4
.build();
// This would fail - exceeds 4 cache points
try {
BedrockSystemMessage tooMany = BedrockSystemMessage.builder()
.addTextWithCachePoint("Section 1")
.addTextWithCachePoint("Section 2")
.addTextWithCachePoint("Section 3")
.addTextWithCachePoint("Section 4")
.addTextWithCachePoint("Section 5") // 5th cache point - error!
.build();
} catch (IllegalStateException e) {
// Exceeded MAX_CACHE_POINTS
}BedrockSystemMessage is NOT a SystemMessage:
BedrockSystemMessage bedrockMsg = BedrockSystemMessage.from("Test");
SystemMessage standardMsg = SystemMessage.from("Test");
// Type checking
boolean isSystemMessage = bedrockMsg instanceof SystemMessage; // false!
// Finding in message list
List<ChatMessage> messages = List.of(bedrockMsg, UserMessage.from("Hi"));
Optional<SystemMessage> found = SystemMessage.findFirst(messages); // empty!
// Must convert for ChatMemory or serialization
SystemMessage forPersistence = bedrockMsg.toSystemMessage(); // Loses cache points// Standard SystemMessage → BedrockSystemMessage
SystemMessage standard = SystemMessage.from("Instructions");
BedrockSystemMessage bedrock = BedrockSystemMessage.from(standard);
// BedrockSystemMessage → Standard SystemMessage (loses cache points)
BedrockSystemMessage bedrockMsg = BedrockSystemMessage.builder()
.addTextWithCachePoint("Cached content")
.build();
SystemMessage standard = bedrockMsg.toSystemMessage(); // Cache points lost// Valid
BedrockSystemTextContent valid = BedrockSystemTextContent.from("Good text");
// Invalid: blank text
try {
BedrockSystemTextContent blank = BedrockSystemTextContent.from("");
} catch (IllegalArgumentException e) {
// "Text must not be blank"
}
// Invalid: exceeds max length
String tooLong = "x".repeat(1_000_001);
try {
BedrockSystemTextContent oversized = BedrockSystemTextContent.from(tooLong);
} catch (IllegalArgumentException e) {
// "Text exceeds maximum length of 1,000,000 characters"
}Next: Best Practices for optimization tips