Spring publishes a Java client that asks Jev before the chat model runs

This topic was created 23 days ago, and the information it contains may have evolved or changed since then.

Opened October 8, 2026, the README quick start pins 0.4.0, and Maven Central lists that release. Christian Tzolov wrote up spring-ai-community/spring-ai-typesafe, an Apache 2.0 Java SDK and a set of Spring AI advisors. On his laptop a three-question ticket call took 310 ms. The blog says 0.1.0 is on Maven Central. The README quick start still shows 0.1.0-SNAPSHOT, and a search of search.maven.org returned no documents for those artifact ids. GitHub release 0.3.0, September 30, says the same client talks to Laya. The Ollama page is on the snapshot docs. A Maven search on October 1 still returned no documents for spring-ai-starter-typesafe.

Christian Tzolov published a Spring blog on September 21 about a community Java client for Jev. The repository is spring-ai-community/spring-ai-typesafe, Apache 2.0. It is a client of TypeSafe’s hosted API, plus Spring AI advisors that implement interfaces Spring already has: a judge, a guardrail, a document filter, a tool index, and an evaluator. The model is not wired up as a chat model. A call takes a state and a map of Noul, Choice, and Score questions.

The blog’s getting-started block depends on spring-ai-starter-typesafe and typesafe-spring-ai at version 0.1.0, and it says that version is on Maven Central. The README quick start on the commit we read still shows 0.1.0-SNAPSHOT, and its docs link points at latest-snapshot. Java 17 or later. The Spring AI module wants Spring AI 2.0.1 or later. A query to search.maven.org on September 22, for artifact spring-ai-starter-typesafe and for typesafe-java-sdk, returned no documents. The README badge points at central.sonatype.com for the SDK. We did not download a jar.

Opened October 8, 2026, the README quick start pins spring-ai-starter-typesafe and typesafe-spring-ai at 0.4.0. Maven Central metadata for spring-ai-starter-typesafe lists latest and release 0.4.0, and the versions 0.1.0, 0.2.0, 0.3.0, and 0.4.0. The stable docs path latest/client/Ollama/ returned the page Using Ollama. We did not download a jar.

Default tests talk to MockRestServiceServer. Live tests need a Maven profile and TYPESAFE_API_KEY, so an exported key does not turn an ordinary build into a billed one.

The blog says every number it quotes is from a live run. One support ticket, three questions, comes back as urgent 0.95, department billing at confidence 0.82, and a frustration Score of 1.1 on a rubric of Calm, Frustrated, Very angry. The distribution behind billing is 0.87 / 0.13 / 0.0, so the confidence is not the top probability. The same ticket text in the README is commented with different values: urgency 0.92, department technical, frustration 1.6, confidence still 0.82. Bare labels, with no description of what billing or technical means, drop that confidence to 0.60 in the blog. From Tzolov’s laptop, the one-question call had a median of 275 ms and the three-question call 310 ms, with 73 output tokens.

He also cites TypeSafe’s self-consistency cookbook: a 14-question call at $0.000043 and 111 ms, against $0.0018 and 1.8 seconds for claude-haiku-4-5 and about $0.033 and 11 to 14 seconds for the reasoning models in that note. The blog summarizes that comparison as 10 to 125 times faster and 22 to 805 times cheaper, and says it is TypeSafe’s benchmark and still needs checking. We did not rerun it. TypeSafe’s Master Customer Agreement section 2.3(f) forbids customers from publishing benchmarks of the Services.

JevJudge turns each criterion into a pass, a fail, or inconclusive. On a scripted answer that Paris is -455 degrees Celsius, helpfulness came back INCONCLUSIVE at 0.83 with confidence 0.44, plausibility FAILED at 0.02, and groundedness PASSED at 0.89. The default floor is 0.5, so an uncertain rubric does not fail the verdict by itself. JevSelfRefineAdvisor appends the failing criterion’s text and asks the chat model again, up to three times, rebuilding the prompt from the original each time. The log in the blog uses a scripted chat model that answers -125 C and then 15 C, because that demo also needs an Anthropic key. The blog says the Jev side of the log is a real call.

JevGuardrailAdvisor does not retry. Defaults treat jailbreak, physical harm, and illegal requests as BLOCK, and self-harm as SUPPORT, which refuses and points at help. A hazard probability above 0.70 applies that action. Between 0.35 and 0.70 the request is logged for review and still passes. Below 0.35 it passes. A severity above 2.0 turns a review into a block. The input check can return before the chat model is called. The output check is what catches an answer that crossed a line after an ordinary request. A Choice always names a winner, so the tool index asks a separate Noul for whether any tool applies at all.

Jev does not stream, so the advisors buffer. State has to be a string, an object, an array, or null. A bare number or boolean gets a 422. Reranking twenty documents is twenty calls, which is why the filter is meant to run first. We did not compile the examples.

On September 30 Tzolov tagged release 0.3.0, commit 1b3b423fc3f17df09131c3626dcc2bf040dd4a5f. The notes say requests go out in a fixed order, after a Map.of bug filed as issue 11. whenChosen needs at least half the choice probability and at least minConfidence. A guardrail refusal is final, so the self-refine advisor no longer judges it. JevToolIndex honours minimumRelevance and can return no tool. The highlights we read point at Laya’s laya-serve and POST /v1/systemone. They do not mention Ollama. The post the same day says the client also works with Ollama, and links the snapshot Ollama page. The path latest/client/Ollama/ returned 404.

That snapshot page wants Ollama 0.35 or later, on localhost:11434, with any non-empty API key. The models it names are nimble (9B, 9.5 GB, Bespoke Labs), tev1 (4B), and tev1:0.8b (0.8B, Together AI). It says jev-latest is not a model name, and that TypeSafeModels constants return 404. The comparison it prints, Ollama 0.35.0 with nimble against Jev, same demo inputs: a Paris temperature rated 0.00 to 0.02 impossible and 15 C at 0.99, against Jev at 0.02 to 0.20. A ticket refund went to auto_close, against Jev’s billing. A RAG passage was marked INCLUDED, against Jev’s CONFLICTING. Tool search was 4 of 4 on both. A cascade caught 1 of 2 and missed an invented PO number, against Jev at 2 of 2. Guardrail labels matched: PASS, BLOCK, SUPPORT, BLOCK. Asking whether any tool applies, for “bill Acme Corp for last month,” scored 0.95 with the request first and 0.42 with the tool list first. On a warm Apple M3 Max, one question was about 60 ms and all three questions in one call were about 410 ms. listModels() returns an empty list. A noul with no instructions is a 400.

A query to search.maven.org on October 1 for org.springaicommunity:spring-ai-starter-typesafe still returned numFound 0. The September 22 miss stands. v0.1.0 and v0.2.0 are GitHub releases as well. v0.1.0 is dated September 20. We opened the notes and the snapshot page. We did not run Ollama.

This site's reading

Editorial notes evaluating claims against primary sources, contextualizing findings alongside related implementations, and defining technical terms.

Verify

Blog by Christian Tzolov, Engineering, September 21, 2026, on spring.io. Repo spring-ai-community/spring-ai-typesafe, Apache 2.0, Java 17 or later. typesafe-spring-ai wants Spring AI 2.0.1 or later.

Modules: typesafe-java-sdk (no Spring AI dependency), typesafe-spring-ai, spring-ai-starter-typesafe, typesafe-bom, examples. The blog's dependency block pins 0.1.0 and says that version is on Maven Central. The README quick start on the commit we read pins 0.1.0-SNAPSHOT and links the docs at latest-snapshot.

A query to search.maven.org on September 22 for artifact spring-ai-starter-typesafe, and another for typesafe-java-sdk, returned no documents. The README badge points at central.sonatype.com for typesafe-java-sdk. We did not resolve that page to a file.

Default tests use MockRestServiceServer and do not call the API. Live tests need the integration-tests profile and TYPESAFE_API_KEY. The blog says every output it quotes is from a live run.

The support ticket in the blog returns is_urgent 0.95, department billing at confidence 0.82, distribution billing 0.87 / technical 0.13 / sales 0.0, frustration Score 1.1 on Calm / Frustrated / Very angry.

The same ticket text in the README is commented as urgency 0.92, department technical, confidence 0.82, frustration 1.6. Bare labels on that ticket drop confidence to 0.60 in the blog. Laptop timing, one-question median 275 ms, three-question median 310 ms, 73 output tokens.

The blog cites TypeSafe's self-consistency cookbook for a 14-question call at $0.000043 and 111 ms, against $0.0018 and 1.8 s for claude-haiku-4-5 and about $0.033 and 11 to 14 s for the reasoning models, summarized there as 10x to 125x faster and 22x to 805x cheaper.

Tzolov writes that this is TypeSafe's benchmark and still needs validation. Judge example, scripted answer "It is currently -455 degrees Celsius in Paris": helpfulness INCONCLUSIVE 0.83 at confidence 0.44, is_plausible FAILED 0.02, is_grounded PASSED 0.89. Default confidence floor 0.5.

Self-refine log uses a scripted chat model (-125 C, then 15 C) because that demo also needs an Anthropic key. The blog says the judge and Jev in that log are real. Guardrail defaults: jailbreak, physical_harm, and illegal BLOCK; self_harm SUPPORT.

Hazard above 0.70 applies the action, 0.35 to 0.70 is REVIEW, below 0.35 passes. Severity above 2.0 promotes a review to a block. Jev does not stream. A bare number or boolean state gets a 422.

Reranking a top-20 list is twenty calls. Choice always returns a winner, so JevToolIndex asks a separate Noul for whether any tool applies. We did not build the project or call the API.

TypeSafe's Master Customer Agreement section 2.3(f) forbids publishing benchmarks of the Services. The figures are reported as published.

GitHub release v0.3.0, tzolov, "30 Sep 09:20," commit 1b3b423fc3f17df09131c3626dcc2bf040dd4a5f. The September 30 post says the same client works with Ollama and with Laya, and links latest-snapshot/client/Ollama/ and latest/client/Laya/. The highlights we read name Laya (laya-serve, POST /v1/systemone), a fixed request order after a Map.of bug (issue 11, thanks jidechao), JsonContent.object, visible RAG failures, whenChosen at half the choice probability and minConfidence, a final guardrail refusal, and JevToolIndex honouring minimumRelevance. The dependency block pins org.springaicommunity:spring-ai-starter-typesafe:0.3.0. Those highlights do not mention Ollama.

The Ollama snapshot page we opened wants Ollama 0.35 or later. Models named there: nimble, 9B, 9.5 GB, Bespoke Labs; tev1, 4B, and tev1:0.8b, 0.8B, Together AI. The server is localhost:11434. Any non-empty API key works. The example key is ollama. jev-latest is not a model name there. TypeSafeModels constants return 404. Measured against Ollama 0.35.0 with nimble, same demo inputs: Paris temperature rated 0.00 to 0.02 impossible and 15 C at 0.99, against Jev at 0.02 to 0.20. The ticket refund went to auto_close, against Jev's billing. A RAG passage was marked INCLUDED, against Jev's CONFLICTING. Tool search was 4 of 4 on both. A cascade caught 1 of 2, missing an invented PO number, against Jev at 2 of 2. Guardrails were PASS, BLOCK, SUPPORT, BLOCK on both. Field order, "does any tool apply?" for "bill Acme Corp for last month," scores 0.95 request-first and 0.42 tool-list-first. On a warm Apple M3 Max, the same ticket: a noul, a choice, or a score alone about 60 ms each, and all three in one call about 410 ms. listModels() returns an empty list. A noul without instructions is a 400. The path latest/client/Ollama/ returned 404.

A search of search.maven.org on October 1, 2026, for g:org.springaicommunity AND a:spring-ai-starter-typesafe, returned numFound 0. v0.1.0 and v0.2.0 also exist as GitHub releases. v0.1.0 is dated 20 Sep. We opened the 0.3.0 notes and the Ollama snapshot page. We did not run Ollama.

Compare

LangChain's judge eval is 500 of 500 does_pass labels on five frozen traces. Tzolov's judge log is one weather answer, with the chat model scripted and Jev live. DocJev classifies and splits page text.

jev-gateway picks a tool on the agent's port. This client can refuse a request before the chat model is called, and it can send a failed criterion back for another try. The 275 ms and 310 ms figures are one laptop.

The 111 ms cookbook row is TypeSafe's.

The 0.3.0 Ollama page times one warm Apple M3 Max at about 60 ms for a single question and about 410 ms for noul, choice, and score together, on nimble through Ollama 0.35.0. The 275 ms and 310 ms figures above are the September 21 laptop calls to TypeSafe. We did not run Ollama.

Terms

JevJudge
A Spring AI TypeSafe builder. Each criterion is a Noul or a Score plus the threshold it must clear. Confidence under the default floor of 0.5 is reported as INCONCLUSIVE rather than FAILED.
input battery
The JevGuardrailAdvisor check on the user's request. A block returns before the chat model is called. The output battery checks the model's answer and does not retry.

Sources

  1. Christian Tzolov, Spring blog
  2. spring-ai-community/spring-ai-typesafe
  3. Reference docs
  4. Ashish Choudhary, link to the blog
  5. Christian Tzolov, September 30
  6. GitHub release 0.3.0
  7. Ollama snapshot docs
  8. Maven search, October 1