DEV Community

Solon Framework
Solon Framework

Posted on

Spring AI vs Solon AI - A Practical Comparison for Java Developers

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 (@Tool in Spring AI, @ToolMapping in 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();
Enter fullscreen mode Exit fullscreen mode

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:

  1. ChatModel — the raw, provider-neutral model call.
  2. ReActAgent — an agent with role, instructions, session, retries, and reflection loop.
  3. 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();
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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 + @ToolMapping to 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

Top comments (0)