LangChain4j vs Spring AI: two ways to bring a LLM into a JVM
After integrating Spring AI into a Kotlin backend, the natural next step was comparing it with LangChain4j, the other JVM library that comes up constantly in discussions about AI on the Java and Kotlin side. Both do roughly the same thing: call a LLM, manage tools, structure output, but they start from two opposite points, and that starting point shows in every line of code.
Two philosophies, not two implementations of the same idea#
Spring AI starts from the framework: a ChatClient injects like any Spring
bean, configuration flows through the usual Spring mechanisms
(application.yml, auto-configuration), and the integration aims to
disappear into the conventions already in place on a Spring Boot project.
LangChain4j starts from the model: the library assumes no framework, it
exposes its own abstractions (chains, agents, conversational memory) that
can coexist with Spring, Quarkus, Micronaut, or no framework at all.
| Spring AI | LangChain4j | |
|---|---|---|
| Starting point | The Spring framework | The model and its abstractions |
| Framework dependency | Strong, built for Spring Boot | None, usable standalone |
| Configuration | application.yml, Spring auto-configuration | Explicit construction in code |
| Structured output | entity(), direct deserialization | AI Services interfaces, generated dynamically |
| Adoption curve on an existing Spring project | Low, fits into existing conventions | Medium, introduces its own vocabulary |
What that looks like in code#
The same need, scoring a mission offer against a stack, is written in LangChain4j as an annotated interface rather than an imperative call:
interface MissionScorer {
@SystemMessage("Score an offer from 0 to 100 against the given stack.")
@UserMessage("Stack: {{stack}}\n\nOffer: {{mission}}")
ScoreResult score(@V("stack") String stack, @V("mission") String mission);
}
MissionScorer scorer = AiServices.create(MissionScorer.class, model);
ScoreResult result = scorer.score(stackSummary, missionDescription);The MissionScorer interface has no hand-written implementation here:
LangChain4j generates one dynamically from the annotations. It's elegant,
and it pushes the prompt to the same first-class status as a method
signature. It's also what, for a developer coming from a pure Spring world,
takes real adjustment time: the behavior no longer lives in the method body,
it lives in its annotations.
Where Spring AI wins: an existing Spring Boot project#
On an existing Spring Boot backend, with its auto-configuration, observability and established conventions, Spring AI has an advantage that isn't technical but organizational: it doesn't ask you to learn a new vocabulary, just a new kind of bean.
That was the case for the example built on MissionMatch: Spring AI slotted into an existing hexagonal architecture without redefining anything, because everything else in the project already spoke Spring.
Where LangChain4j wins: portability and agents#
LangChain4j takes the lead as soon as the project isn't a Spring project, or as soon as the need goes beyond a simple model call: orchestrating multiple tools, conversational memory, agents that chain several calls. Its abstractions are designed for those cases from the start, where Spring AI stays closer to a typed HTTP client than to an agent-orchestration framework.
Picking LangChain4j for its agent capabilities on a project that, in reality, only needs a simple model call imports complexity and a vocabulary that aren't justified. The question isn't "which one is more powerful", it's "what does this specific project actually need to do".
The deciding factor, in practice#
The choice doesn't come down to performance benchmarks, both call the same model behind a thin abstraction layer. It comes down to one question: is the project already structured around Spring, or does it need a library that assumes nothing about the rest of the stack? On an existing Spring Boot backend, Spring AI costs less to adopt. On a neutral project, or one that genuinely needs to orchestrate multiple tools and agents, LangChain4j offers a vocabulary already designed for that, which Spring AI isn't meant to cover on its own.