Spring AI Chat Client provides a fluent API for building AI-powered applications with LLMs, supporting advisors, streaming, structured outputs, and conversation memory
The Spring AI Chat Client provides fluent interfaces for configuring requests before execution. Request configuration happens through several spec interfaces that build upon each other.
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.core.io.Resource;
import java.nio.charset.Charset;The main interface for building complete requests.
interface ChatClientRequestSpec {
// Message configuration
ChatClientRequestSpec user(String text);
ChatClientRequestSpec user(Resource resource);
ChatClientRequestSpec user(Consumer<PromptUserSpec> userSpecConsumer);
ChatClientRequestSpec system(String text);
ChatClientRequestSpec system(Resource resource);
ChatClientRequestSpec system(Consumer<PromptSystemSpec> systemSpecConsumer);
ChatClientRequestSpec messages(Message... messages);
ChatClientRequestSpec messages(List<Message> messages);
// Advisor configuration
ChatClientRequestSpec advisors(Advisor... advisors);
ChatClientRequestSpec advisors(Consumer<AdvisorSpec> advisorSpecConsumer);
// Tool configuration
ChatClientRequestSpec toolNames(String... toolNames);
ChatClientRequestSpec tools(Object... toolObjects);
ChatClientRequestSpec toolCallbacks(ToolCallback... toolCallbacks);
ChatClientRequestSpec toolCallbacks(List<ToolCallback> toolCallbacks);
ChatClientRequestSpec toolCallbacks(ToolCallbackProvider... toolCallbackProviders);
ChatClientRequestSpec toolContext(Map<String, Object> toolContext);
// Model options
ChatClientRequestSpec options(ChatOptions chatOptions);
// Execution
CallResponseSpec call();
StreamResponseSpec stream();
}Add or configure the user message (the prompt from the user).
Simple Text:
ChatClientRequestSpec user(String text);Example:
String response = chatClient
.prompt()
.user("What is Spring Framework?")
.call()
.content();From Resource:
ChatClientRequestSpec user(Resource resource);Load user message from a file or classpath resource.
Example:
import org.springframework.core.io.ClassPathResource;
String response = chatClient
.prompt()
.user(new ClassPathResource("prompts/query.txt"))
.call()
.content();With Consumer and Parameters:
ChatClientRequestSpec user(Consumer<PromptUserSpec> userSpecConsumer);Configure user message with parameters, media, and metadata.
Example:
String response = chatClient
.prompt()
.user(spec -> spec
.text("Tell me about {topic} in {language}")
.param("topic", "Spring Boot")
.param("language", "Java")
)
.call()
.content();Configure system messages that set the context or behavior for the AI model.
Simple Text:
ChatClientRequestSpec system(String text);Example:
String response = chatClient
.prompt()
.system("You are a helpful Java programming assistant")
.user("Explain interfaces")
.call()
.content();From Resource:
ChatClientRequestSpec system(Resource resource);With Consumer:
ChatClientRequestSpec system(Consumer<PromptSystemSpec> systemSpecConsumer);Example:
String response = chatClient
.prompt()
.system(spec -> spec
.text("You are an expert in {domain}")
.param("domain", "microservices")
)
.user("Explain service discovery")
.call()
.content();Add pre-constructed Message objects directly to the request.
ChatClientRequestSpec messages(Message... messages);
ChatClientRequestSpec messages(List<Message> messages);Example:
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
String response = chatClient
.prompt()
.messages(
new SystemMessage("You are a code reviewer"),
new UserMessage("Review this code: " + code)
)
.call()
.content();Detailed configuration for user messages including parameters, media, and metadata.
interface PromptUserSpec {
PromptUserSpec text(String text);
PromptUserSpec text(Resource resource);
PromptUserSpec text(Resource text, Charset charset);
PromptUserSpec params(Map<String, Object> params);
PromptUserSpec param(String key, Object value);
PromptUserSpec media(Media... media);
PromptUserSpec media(MimeType mimeType, URL url);
PromptUserSpec media(MimeType mimeType, Resource resource);
PromptUserSpec metadata(Map<String, Object> metadata);
PromptUserSpec metadata(String key, Object value);
}Use placeholders in text that are replaced with parameter values.
Example:
chatClient
.prompt()
.user(spec -> spec
.text("Compare {item1} and {item2}")
.param("item1", "ArrayList")
.param("item2", "LinkedList")
)
.call()
.content();With Map:
Map<String, Object> params = Map.of(
"item1", "HashMap",
"item2", "TreeMap"
);
chatClient
.prompt()
.user(spec -> spec
.text("Compare {item1} and {item2}")
.params(params)
)
.call()
.content();Add images, documents, or other media to the user message (for multimodal models).
PromptUserSpec media(Media... media);
PromptUserSpec media(MimeType mimeType, URL url);
PromptUserSpec media(MimeType mimeType, Resource resource);Example:
import org.springframework.ai.content.Media;
import org.springframework.util.MimeTypeUtils;
import org.springframework.core.io.ByteArrayResource;
Media image = new Media(
MimeTypeUtils.IMAGE_PNG,
new ByteArrayResource(imageBytes)
);
String description = chatClient
.prompt()
.user(spec -> spec
.text("Describe this image")
.media(image)
)
.call()
.content();Add metadata to the user message for tracking or context.
PromptUserSpec metadata(String key, Object value);Example:
chatClient
.prompt()
.user(spec -> spec
.text("Answer this question")
.metadata("user_id", "user-123")
.metadata("session_id", "session-456")
)
.call()
.content();Configuration for system messages with parameters and metadata.
interface PromptSystemSpec {
PromptSystemSpec text(String text);
PromptSystemSpec text(Resource resource);
PromptSystemSpec text(Resource text, Charset charset);
PromptSystemSpec params(Map<String, Object> params);
PromptSystemSpec param(String key, Object value);
PromptSystemSpec metadata(Map<String, Object> metadata);
PromptSystemSpec metadata(String key, Object value);
}Example:
chatClient
.prompt()
.system(spec -> spec
.text("You are a {role} expert. Be {tone}.")
.param("role", "DevOps")
.param("tone", "concise")
.metadata("persona_version", "1.0")
)
.user("Explain containers")
.call()
.content();Advisors are interceptors that modify requests and responses. They can be added at the request level.
ChatClientRequestSpec advisors(Advisor... advisors);
ChatClientRequestSpec advisors(Consumer<AdvisorSpec> advisorSpecConsumer);Simple Addition:
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
chatClient
.prompt("Hello")
.advisors(SimpleLoggerAdvisor.builder().build())
.call()
.content();With Advisor Spec:
interface AdvisorSpec {
AdvisorSpec advisors(Advisor... advisors);
AdvisorSpec advisors(List<Advisor> advisors);
AdvisorSpec param(String key, Object value);
AdvisorSpec params(Map<String, Object> p);
}Advisor parameters allow passing configuration to advisors at request time.
Example:
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
chatClient
.prompt("Continue our conversation")
.advisors(spec -> spec
.advisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
.param("conversationId", "user-123")
)
.call()
.content();Tools allow the AI model to call Java functions during processing.
ChatClientRequestSpec toolCallbacks(ToolCallback... toolCallbacks);
ChatClientRequestSpec toolCallbacks(List<ToolCallback> toolCallbacks);
ChatClientRequestSpec toolCallbacks(ToolCallbackProvider... toolCallbackProviders);Example:
import org.springframework.ai.tool.ToolCallback;
ToolCallback weatherTool = ToolCallback.builder()
.function("getCurrentWeather", this::getWeather)
.description("Get the current weather for a location")
.inputType(WeatherRequest.class)
.build();
String response = chatClient
.prompt("What's the weather in Paris?")
.toolCallbacks(weatherTool)
.call()
.content();ChatClientRequestSpec tools(Object... toolObjects);
ChatClientRequestSpec toolNames(String... toolNames);The tools() method accepts objects that will be converted to tool callbacks. The toolNames() method allows specifying which tools to use by name.
Example:
// Define a tool as an object with @Tool annotated methods
@Component
class WeatherTools {
@Tool(description = "Get the current weather for a location")
public String getCurrentWeather(String location) {
// Fetch and return weather data
return "Sunny, 22°C";
}
}
// Use the tool
String response = chatClient
.prompt("What's the weather in Paris?")
.tools(weatherTools)
.call()
.content();Share data between tools and requests.
ChatClientRequestSpec toolContext(Map<String, Object> toolContext);Example:
Map<String, Object> context = Map.of(
"userId", "user-123",
"sessionId", "session-456"
);
chatClient
.prompt("Process my data")
.toolContext(context)
.toolCallbacks(dataTool)
.call()
.content();Set model-specific parameters like temperature, maxTokens, etc.
ChatClientRequestSpec options(ChatOptions chatOptions);Example:
import org.springframework.ai.chat.options.ChatOptionsBuilder;
String response = chatClient
.prompt("Write a creative story")
.options(ChatOptionsBuilder.builder()
.withModel("gpt-4")
.withTemperature(0.9)
.withMaxTokens(1000)
.build())
.call()
.content();After configuring a request, execute it as either a synchronous call or a streaming request.
CallResponseSpec call();Returns a CallResponseSpec for processing the response.
Example:
String content = chatClient
.prompt("Hello")
.call()
.content();StreamResponseSpec stream();Returns a StreamResponseSpec for processing the streaming response.
Example:
Flux<String> stream = chatClient
.prompt("Tell me a story")
.stream()
.content();
stream.subscribe(System.out::print);import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.options.ChatOptionsBuilder;
import org.springframework.core.io.ClassPathResource;
record Answer(String summary, List<String> keyPoints) {}
Answer answer = chatClient
.prompt()
.system(spec -> spec
.text("You are an expert in {domain}")
.param("domain", "software architecture")
)
.user(spec -> spec
.text("Explain {topic}")
.param("topic", "microservices")
)
.advisors(spec -> spec
.advisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
.param("conversationId", "session-789")
)
.options(ChatOptionsBuilder.builder()
.withTemperature(0.7)
.withMaxTokens(500)
.build())
.call()
.entity(Answer.class);