If you build AI-powered applications on the JVM today, you will meet two frameworks quickly: Spring AI, the official AI layer of the vast Spring ecosystem, and Solon AI, the AI stack of the Solon project that also embeds into any Java framework — including Spring Boot itself.
They solve the same problem — connect your Java code to LLMs, tools, RAG pipelines, and agents without locking yourself to one vendor — but they approach it with very different philosophies. This article compares them feature by feature, with side-by-side code for every major capability. All Solon AI snippets below were verified against the solon-ai source (v4.x), and the Spring AI snippets follow the current Spring AI 1.0.x reference documentation.
What They Share
The overlap is larger than the marketing suggests. Both frameworks offer:
- A portable chat model abstraction — one interface, many providers (OpenAI, Anthropic, Google Gemini, Ollama, Azure, DeepSeek, DashScope, ...). Write once, swap the backend by configuration.
-
Tool calling via annotated Java methods (
@Toolin Spring AI,@ToolMappingin Solon AI), with the framework managing the request/execute/return loop. - Structured output — map model responses directly onto Java POJOs.
- A full RAG chain — document loaders, splitters, embedding models, vector store adapters (PGVector, Redis, Milvus, Qdrant, Chroma, ...), and metadata filtering.
- Chat memory / conversation persistence, with pluggable stores.
- MCP (Model Context Protocol) on both sides: consume external MCP servers and expose your own services as MCP servers.
- Sync and streaming responses, plus GraalVM native image support.
Both are Apache 2.0 licensed and production-oriented. The interesting part is where they diverge.
Difference #1: The Ecosystem Contract
This is the deepest difference.
Spring AI is an AI abstraction layer for the Spring ecosystem. Its idioms are Spring idioms: Boot starters, auto-configuration, dependency injection, Micrometer observability. It requires Java 17+ (the upcoming 2.0 line targets Java 21+), and in practice it lives inside a Spring Boot application.
Solon AI is framework-neutral. It runs standalone on plain JDK 8 through 26, and it can be embedded into Spring Boot, Quarkus, Vert.x, or jFinal as just another library. If you have a legacy Java 8 service in a bank and want to add LLM features, this distinction decides the question by itself.
Difference #2: API Style — Advisor Chain vs. Builder + Agent
Spring AI's high-level API is ChatClient, a fluent builder in the spirit of WebClient. Cross-cutting behaviors — memory, RAG, tool execution — are composed as an Advisor chain:
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(chatMemory).build(), // memory
QuestionAnswerAdvisor.builder(vectorStore).build() // RAG
)
.build();
String answer = chatClient.prompt()
.user("What is our refund policy for enterprise contracts?")
.call()
.content();
Advisors are interceptors wrapping the call: they can rewrite the prompt, inject retrieved documents, and post-process the response. It is a clean, extensible pattern — but everything is a ChatClient concern.
Solon AI instead exposes a ladder of abstractions, from low to high:
-
ChatModel— the raw, provider-neutral model call. -
ReActAgent— an agent with role, instructions, session, retries, and reflection loop. -
TeamAgent— multi-agent collaboration with routing protocols.
The equivalent of the snippet above in Solon AI:
ChatModel chatModel = ChatModel.of("https://api.openai.com/v1")
.apiKey(apiKey)
.model("gpt-4o")
.build();
ReActAgent supportBot = ReActAgent.of(chatModel)
.name("SupportBot")
.instruction("Answer using only the provided knowledge base")
.build();
String answer = supportBot.prompt("What is our refund policy?")
.call().getContent();
Difference #3: Tool Calling
The concepts map almost one-to-one; only the annotations and wiring differ.
Spring AI — annotate a method, register the object, and the auto-registered ToolCallingAdvisor runs the tool loop:
class WeatherTools {
@Tool(description = "Get current weather for a city")
String getWeather(@ToolParam(description = "City name") String city) {
return weatherService.lookup(city);
}
}
String answer = chatClient.prompt()
.tools(new WeatherTools())
.user("Weather in Hangzhou?")
.call().content();
Solon AI — same idea with @ToolMapping and @Param:
public class WeatherTools extends AbsToolProvider {
@ToolMapping(description = "Get current weather for a city")
public String getWeather(@Param(description = "City name") String city) {
return weatherService.lookup(city);
}
}
ChatModel chatModel = ChatModel.of(apiUrl)
.apiKey(apiKey).model("gpt-4o")
.defaultToolAdd(new WeatherTools())
.build();
String answer = chatModel.prompt("Weather in Hangzhou?")
.call().getContent();
A Solon AI extra worth noting: the Talent system, where entire tool suites (terminal, mail, memory, browser automation) are mounted as swappable capability groups an agent can discover — closer to "skills" than to plain function calls.
Difference #4: Structured Output
Spring AI converts responses to POJOs at the ChatClient layer:
record ActorFilms(String actor, List<String> movies) {}
ActorFilms films = chatClient.prompt()
.user("List 3 movies of Tom Hanks")
.call()
.entity(ActorFilms.class);
Solon AI puts the constraint in ChatOptions.outputSchema(...). The framework generates a JSON Schema from your POJO and injects it into the instruction in a provider-neutral <output_schema> block — it does not rely on any vendor's native JSON mode, so the same code works on OpenAI, Ollama, DashScope, or Gemini:
ReActAgent extractor = ReActAgent.of(chatModel)
.name("ResumeExtractor")
.outputSchema(ResumeInfo.class) // POJO -> JSON Schema, enforced
.outputKey("resume")
.build();
On the response side, AssistantMessage.getJsonContent() strips markdown fences and toBean(Type) deserializes back to the same type.
Difference #5: RAG
Spring AI treats RAG as advisors. QuestionAnswerAdvisor implements naive RAG; RetrievalAugmentationAdvisor composes modular pipelines (query transformers, retrievers, post-processors) inspired by the Modular RAG paper. Filtering uses a portable SQL-like FilterExpression.
Advisor rag = RetrievalAugmentationAdvisor.builder()
.documentRetriever(VectorStoreDocumentRetriever.builder()
.vectorStore(vectorStore)
.similarityThreshold(0.50)
.build())
.build();
Solon AI treats RAG as a repository. One abstraction covers embedding, storage, retrieval, filtering, and prompt augmentation:
// Ingest
repository.insert(Document.of(text).metadata(Map.of("department", "support")));
// Retrieve with a filter expression pushed down to the store
QueryCondition cond = QueryCondition.from("refund policy")
.filterExpression("department == 'support'");
// Let the model drive retrieval itself (agentic RAG)
ChatModel chatModel = ChatModel.of(apiUrl)
.defaultToolAdd(new RepositoryTool(repository, 5))
.build();
RepositoryTool turns the repository into a tool, so the model decides when and what to search — agentic RAG out of the box. Spring AI can achieve similar behavior by combining tools with a vector store, but you assemble it yourself.
Difference #6: Memory
Spring AI: ChatMemory stores per-conversation messages (in-memory, JDBC, Cassandra...), surfaced through MessageChatMemoryAdvisor. Each call must supply ChatMemory.CONVERSATION_ID.
Solon AI: ChatSession is the message ledger with windowed retrieval (getLatestMessages(windowSize)), while AgentSession additionally persists workflow state — including pending human-in-the-loop checkpoints — with File and Redis backends. The session abstraction covers both chat history and long-running agent execution state in one object.
Difference #7: Agents and Orchestration
This is where the frameworks diverge most in ambition.
Spring AI's agent story is compositional: advisors + tools + (in recent versions) recursive advisors for self-reflection. Deep agentic workflows in the Spring world often pull in additional projects, e.g. Spring AI Alibaba's graph engine.
Solon AI ships agent primitives natively: ReActAgent with reflection and retries, TeamAgent with built-in collaboration protocols, dynamic skill admission, and Ai Flow — YAML-based flow orchestration for a low-code, Dify-like experience. If your application is an agent system, Solon AI gives you the vocabulary for it without extra dependencies.
Difference #8: MCP
Both fully support MCP:
-
Spring AI: dedicated Boot starters (
spring-ai-starter-mcp-client, etc.), annotation model (@McpTool,@McpResource,@McpPrompt), sync/async client and server, Stdio/SSE/Streamable-HTTP transports. -
Solon AI:
@McpServerEndpoint+@ToolMappingto expose services; client-side integration folds remote MCP tools into the local tool system; multiple endpoint groups per service.
Implementation detail: Spring AI builds on the official MCP Java SDK; Solon AI implements the protocol within its own runtime, which keeps the dependency tree small.
Difference #9: Runtime Footprint
The Solon project advertises (and its TechEmpower-style results back up) dramatically lower resource usage than comparable Spring Boot stacks: startup in fractions of a second, tens of MB of heap, tiny JARs. For serverless and edge deployments this matters; for a monolith behind an existing observability stack, it matters less. Spring AI compensates with first-class Micrometer integration, Spring Security, and the enormous Spring ecosystem of starters.
Summary Table
| Dimension | Spring AI | Solon AI |
|---|---|---|
| Ecosystem | Spring Boot native | Framework-neutral, embeddable anywhere |
| Java requirement | 17+ (2.0: 21+) | 8 ~ 26 |
| Core API | ChatClient + Advisor chain | ChatModel + Agent ladder |
| Tools |
@Tool + ToolCallback |
@ToolMapping + Talent system |
| Structured output | .entity(Class) |
outputSchema(Class), provider-neutral |
| RAG | Advisors, modular pipeline | Repository abstraction, agentic RAG built in |
| Memory | ChatMemory advisors | ChatSession + AgentSession (incl. HITL state) |
| Agents | Compositional (advisors/tools) | Native ReAct/Team agents + Ai Flow YAML |
| MCP | Starters + MCP Java SDK | Native implementation, multi-endpoint |
| Footprint | Typical Spring Boot | Very small, fast startup |
| Observability | Micrometer, Actuator | Solon ecosystem |
Which One Should You Pick?
Choose Spring AI when you already live in Spring Boot, your team's skills are Spring-centric, and you value the ecosystem: auto-configuration, starters for everything, Micrometer observability, and long-term commercial backing from the Spring team.
Choose Solon AI when you need AI features in a codebase that is not (or cannot be) a modern Spring Boot app: Java 8 legacy services, Quarkus/Vert.x/jFinal stacks, resource-constrained deployments — or when your application is fundamentally an agent system and you want native ReAct, team collaboration, skills, and YAML flow orchestration rather than assembling them from parts.
And remember the pragmatic option: because Solon AI embeds into Spring Boot, the choice is not always either/or — some teams use Spring Boot for the web tier and Solon AI for the agent core, taking the best of both ecosystems.
Both frameworks move fast, both are genuinely production-capable, and the competition between them is exactly what the Java AI ecosystem needs right now.
References
- Spring AI reference docs: https://docs.spring.io/spring-ai/reference/
- Spring AI project page: https://spring.io/projects/spring-ai
- Solon AI repository: https://github.com/opensolon/solon-ai
- Solon AI docs: https://solon.noear.org/article/learn-solon-ai
- Model Context Protocol: https://modelcontextprotocol.io
Top comments (0)