The module-25 chatbot, rebuilt as a Spring Boot
@AcpAgent that talks to the model through Spring AI's ChatClient.
It exists to answer one question: "Am I locked to one model provider?" No. The
ACP agent never changes — the model is whatever Spring AI autoconfigures from the
spring-ai-starter-model-* dependency on the classpath.
| Module | How it calls the model |
|---|---|
| 25 | Raw Anthropic Java SDK (clearest call site) |
| 26 (this) | Spring AI ChatClient — multi-provider |
| 27 | LangChain4j ChatModel |
The ACP handlers (@Initialize / @NewSession / @Prompt) are identical to the
module-23 echo bean. The only difference from
echo is the body of @Prompt:
String answer = chatClient.prompt().user(request.text()).call().content();
context.sendMessage(answer);Spring AI's ChatClient sits over a ChatModel that's autoconfigured from the
starter on the classpath. To use OpenAI, Gemini, or a local Ollama model instead
of Anthropic, swap the dependency and the spring.ai.<provider>.* properties —
ChatbotAgentBean does not change:
<!-- this module -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-anthropic</artifactId>
</dependency>
<!-- swap for: spring-ai-starter-model-openai / -ollama / ... -->This module depends on org.springaicommunity:acp-spring-boot-starter (the same
autoconfig as module 23), aligned to ACP SDK 0.12.0. Autoconfiguration
discovers the @AcpAgent bean and manages the agent lifecycle.
- Java 21 (Spring Boot 4)
ANTHROPIC_API_KEYexported (read viaspring.ai.anthropic.api-key)
./mvnw package -pl module-26-spring-ai-chatbot -q
./mvnw exec:java -pl module-26-spring-ai-chatbotChatClient also streams — .stream().content() returns a Flux<String>:
chatClient.prompt().user(request.text()).stream().content()
.toStream().forEach(context::sendMessage);