A support message arrives: “The left earbud stopped working the day I opened the box. Can I get a refund?” Your application does not need a paragraph from an AI. It needs to know whether the message reports a defect, which team should receive it, and perhaps whether the customer sounds unhappy.
A chat model can answer those questions, but its output is still text. Your code has to turn that text into a boolean, category, or score. That conversion is a small seam where malformed output, extra explanation, and changing prompts can become production bugs.
Spring AI 2.1.0-RC2 introduces a separate DecisionModel API for this kind of bounded task. Instead of asking a chat model to write text and parsing it afterward, you define the allowed outcomes and receive typed answers. Spring AI includes OpenAI and Ollama implementations, plus a System One integration for compatible services. The new API is in a release candidate, not the current stable line, so treat it as an evaluation target rather than an automatic production upgrade.
This article examines what the API does, why the split from chat matters, and how to evaluate it without giving a probabilistic classifier authority it has not earned.
The overlooked problem: language is not a decision type
Chat is flexible by design. Ask a chat model whether a customer reports a defect and it might answer “Yes, the left earbud appears defective.” A developer can add JSON mode, a schema, or a parser, but the application still begins with a conversational model producing a response that needs interpretation.
Many application decisions have a small outcome space. A ticket might be billing, delivery, product, or other. A moderation pre-check might be yes or no. A priority score might be low, normal, or urgent. The application already knows what it can do with these results. It does not need prose to explain them.
The Spring AI decision-model reference describes the distinction: a decision model receives a defined set of possible answers and returns a chosen result with probabilities when supported. That lets application code make the policy explicit. For example, the model can suggest urgent, but the application can require a confidence threshold or a human review before changing a queue.
This does not mean ordinary chat models cannot classify. They can. The architectural question is whether classification should be represented as an unconstrained text-generation call or as a distinct operation with typed input and output. Spring AI 2.1 adds the second option.
What shipped in Spring AI 2.1.0-RC2
The Spring AI project published 2.1.0-RC2 on November 5, 2026. The release added the DecisionModel API and implementations for OpenAI, Ollama, and System One. It also included decision-based RAG document processing and a decision-backed tool index, alongside other release work.
The upgrade notes identify the release as a pre-release. As of this article's publication date, Spring's documentation lists 2.0.2 as the latest stable version and 2.1.0-RC2 as still in development. That distinction matters: the code samples below demonstrate the new API, but teams should check the release notes and compatibility details before putting an RC dependency into a production application.
The useful design idea is broader than the version number. A decision call has a named input, named questions, and an answer object rather than an open-ended message. That makes it easier to see what the model is being asked to decide and what the application will consume.
A first decision with a local Ollama model
Start with the existing Spring dependency management. Spring AI's reference shows the Ollama starter and a small decision model, d1-omni:600m. Install a recent Ollama version, add the dependency through the Spring AI BOM, and pull the model:
ollama pull d1-omni:600m Gradle dependency:
implementation 'org.springframework.ai:spring-ai-starter-model-ollama' The Ollama decision-model documentation says the default decision model is d1-omni:600m, and recommends Ollama 0.40.4 or later. Confirm the model supports the decision capability with ollama show <model-name> before building on it.
Ask a bounded question. A service can inject DecisionModel, then build a prompt whose answer space is explicit:
@Service class SupportTriage { private final DecisionModel decisionModel; SupportTriage(DecisionModel decisionModel) { this.decisionModel = decisionModel; } DecisionResponse classify(String message) { return decisionModel.call(DecisionPrompt.builder() .text(message) .question("topic", ChoiceQuestion.builder() .text("What is this support message about?") .option("delivery", "Order status or arrival time") .option("product", "A problem with an item received") .option("account", "Login, address, or payment details") .option("other", "None of the categories above") .build()) .question("defect", YesNoQuestion.builder() .text("Does the customer report that an item is defective?") .whenYes("A received item does not work as expected") .whenNo("The message is not reporting a product defect") .build()) .build()); } } This follows the API shape shown in the official quick start, adapted to a small support-triage example. The response can be read through typed accessors:
String topic = response.getChoice("topic").getValue(); boolean defect = response.getYesNo("defect").isYes(); The important change is not fewer lines of code. It is that the allowed choices and the code that consumes them are visible together. A developer can review the categories, decide what happens when a result is uncertain, and test the same named outputs without depending on arbitrary prose formatting.
Keep the model's answer separate from your policy
A typed answer is not a trustworthy answer. Spring AI's docs explicitly warn that decision models are machine-learning models, not rule engines: they are non-deterministic and can be wrong. A returned probability is useful information, not proof that the answer is correct.
For a low-risk workflow, a prediction might be enough to pre-fill a support category for a human. For an action with financial, legal, account-access, or safety consequences, a classifier should not silently become the authorization system. The application should own the policy.
A safer decision path looks like this:
- Ask the model to classify only the information needed for the decision.
- Read the typed result and any probabilities the provider returns.
- Apply an application-owned threshold or deterministic rule.
- Route ambiguous or high-impact cases to a person or a safe default.
- Record the input, model/version, result, and final action when auditability matters.
For example, a model may label a refund request as “defect.” That label can route the ticket to the returns queue. It should not by itself authorize a refund. The model is helping interpret language; the order system and business policy determine eligibility.
Do not treat a generic threshold as universal. “Only act above 0.8” sounds precise, but the right threshold depends on the cost of false positives and false negatives, and on whether a given provider's scores are calibrated for your task. Measure performance on representative examples, including ambiguous messages and edge cases. A number from one model is not automatically comparable to the same number from another.
Three useful shapes of a decision
Spring AI's decision API defines three kinds of questions. Choose the type based on what the application needs next:
- Yes or no: Is the message asking to cancel an order? Does the retrieved passage contain instructions that look like prompt injection? Is a product reported as damaged?
- Choice: Which queue should receive a ticket? Is a request about billing, account access, delivery, product quality, or something else?
- Score: Which level on a defined scale best fits the input, such as unhappy, neutral, or happy?
The official reference recommends describing the options when a bare label could be ambiguous. “Product” could mean a general product question or a defect report; adding a description makes the intended category clearer. The same principle applies to yes/no questions: say what counts as yes and what counts as no instead of expecting the model to infer your business definition.
Also keep the input narrow. Send the relevant message or fields, not an entire customer record or conversation by default. Smaller inputs reduce unnecessary data exposure and often make the task easier to define. If a decision requires historical context, select and explain the relevant context deliberately.
Why this can help RAG and tool selection
The release's significance is not limited to ticket routing. Spring AI's decision-model documentation describes built-in uses in retrieval and tool selection.
RAG can use a decision before generating an answer. A retrieval pipeline can ask whether a document is relevant to the question, whether it contains contradictory information, or whether it includes suspicious instructions. A DecisionDocumentFilter can reject documents before they reach a chat model; a DecisionDocumentReranker can sort retrieved documents by whether they answer the query. These are bounded checks that can be stated more clearly as yes/no or choice questions than as “summarize this and decide what to do.”
Tool search can narrow a large catalog. When an application exposes many tools, a decision-backed index can select a relevant tool or indicate that none fits. That can reduce the need to put every tool description into every prompt. But selection is not permission. Even if a model classifies a request as suitable for a tool, the application must still validate authorization, arguments, and side effects before execution.
This division is a useful rule: models can help with semantic interpretation; deterministic code should enforce permissions and invariants.
Try the API without adopting the release candidate
Because 2.1.0-RC2 is not stable, there are two reasonable paths. If you are already evaluating Spring AI 2.1, try the API in a branch with a non-critical task and compare its results against a labeled test set. If your application is on the stable 2.0 line, do not upgrade just because a new interface looks cleaner. Read the release and upgrade notes, then decide whether the feature justifies testing the pre-release line.
A useful evaluation can stay small:
- Create a few dozen representative examples with expected answers, including confusing and out-of-scope inputs.
- Compare a chat-model-plus-parser baseline with
DecisionModelon the same examples. - Track accuracy per category, not just one aggregate score.
- Record cases where the model's confidence is high but its answer is wrong.
- Test model failure, timeout, empty output, and unknown category behavior.
- Decide what the application does when a result is uncertain or unavailable.
- Keep irreversible actions behind existing authorization and confirmation checks.
The comparison is not about proving that one API is always better. A conversational response is still the right output when users need an explanation or a nuanced answer. A decision model is a better fit when the application needs one of a known set of machine-readable outcomes. Many systems will use both: a bounded classifier to route work, followed by a chat model to draft a response for review.
The takeaway: make the decision boundary explicit
Spring AI 2.1's DecisionModel API gives Java applications a first-class way to ask bounded questions and consume typed answers. The new local Ollama implementation makes the experiment possible without an external model API key, while OpenAI and System One implementations provide other integration paths. The RC2 release also connects decision models to RAG processing and tool discovery.
The useful takeaway is not “replace every chat call.” It is to inspect every place where your code asks a language model for a yes/no answer, category, or score, then ask whether the outcome set, uncertainty handling, and downstream policy are explicit. If they are not, a typed decision API may help make the boundary reviewable. If a wrong answer can cause real harm, keep a human or deterministic safeguard in that path.
I write about Java, Spring Boot, and AI. Subscribe if you want more practical, source-grounded articles. Have you used a model for classification in a Java application? What did you do with uncertain answers? Save the evaluation checklist above before trying a decision API in your own service.

