Migrating from 1.x to 2.x

This content was generated with the assistance of AI and should be verified against the official documentation of each tool and framework before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

Written against Spring AI 2.0.1, Spring Boot 4.1.x and Java 21 (verified 2026-09-29), from the official Upgrade Notes as they stood on that date, checked against the 2.0.1 jars and, where marked, by running code. Spring AI version 2.0.0 became generally available on 2026-06-12 and 2.0.1 is the current stable release. The 2.0 line requires Java 17 or later, Spring Boot 4.0 or 4.1 with Spring Framework 7, Jackson 3 and JSpecify nullability, so a Spring AI upgrade is also a Spring Boot upgrade, and the Boot 4 migration is the larger part of the work for most projects. This page is the reference to keep beside the compiler while you upgrade: the rows are the changes DocsAssistant-style code runs into, each with a link to the note it comes from. The rest of the sub-section describes 2.0.1 as if it were the only version; this page is the one place that looks back. A 2.1 milestone exists on Maven Central, but nothing here is based on it. The most common renames also fit in one box of the printable Spring AI Cheat Sheet, and the version baseline on the landing page lists every version this sub-section targets.

How to upgrade

flowchart TD A["1.x application on Boot 3.x"] --> B["Get the tests green on 1.x first"] B --> C["Move to Spring Boot 4.x and Java 17+ (Framework 7, Jackson 3)"] C --> D["Set spring-ai-bom to 2.0.x"] D --> E["Run OpenRewrite recipes for the mechanical part"] E --> F["Fix what the compiler reports: tables below"] F --> G["Update properties: drop .options, renamed keys"] G --> H["Review the silent changes: same code, different behaviour"] H --> I["Run the evaluation suite and compare answers, cost, latency"]
  1. Green tests first. An upgrade of this size needs a baseline. Tests with a scripted ChatModel (see Testing) are ideal, since they do not change when the provider does.

  2. Boot 4 and Java. Move the platform first or together with the BOM; Spring AI 2.0.x supports Spring Boot 4.0.x and 4.1.x. Jackson 3 changes the ObjectMapper package to tools.jackson.databind and the builder to JsonMapper.

  3. BOM. Import spring-ai-bom 2.0.1 (or the latest 2.0.x). All org.springframework.ai artifacts take their version from it.

  4. Recipes. Run the OpenRewrite recipes in the next section, then read the diff.

  5. Compile. Work through the tables below.

  6. Properties. Start the application with a configuration check; unknown keys under spring.ai are silently ignored by Boot, so compare your files with the tables, or run the recipe that renames them.

  7. Behaviour. Read the "compiles but behaves differently" table. These are the changes no compiler will report.

OpenRewrite recipes

Three sets of recipes exist. Two are from Spring AI and cover the MCP changes of 2.0.0-M3; one is a community recipe that covers most of the mechanical 2.0 changes.

Table 1. Recipes for the 1.x to 2.0 upgrade
Recipe What it does Source

io.arconia.rewrite.spring.ai2.UpgradeSpringAi_2_0

Upgrades org.springframework.ai dependencies to 2.0.x; flattens the .options. infix in property keys for embedding, image, audio, moderation and OCR; comments out removed properties; converts ChatOptions arguments to builders; renames toolCallbacks(…​)/defaultToolCallbacks(…​) to tools(…​)/defaultTools(…​); renames getDefaultOptions() to getOptions() and N() to n(); updates coordinates and types for Anthropic, MCP, Mistral, OpenAI and Google. It does not migrate AnthropicChatModel construction from AnthropicApi

Arconia: Spring AI 2.0 (community project)

org.springframework.ai.migration.M3MigrateMcpAnnotations

Removes the org.springaicommunity:mcp-annotations dependency and rewrites imports to org.springframework.ai.mcp.annotation.*

migrate-to-2-0-0-M3.yaml in the Spring AI repository, see the upgrade notes

org.springframework.ai.migration.M3MigrateMcpSpringTransports

Moves the mcp-spring-webflux and mcp-spring-webmvc coordinates and the transport classes to Spring AI’s packages

same file

org.springframework.ai.migration.M3MigrateMcpClientCustomizer

Rewrites McpSyncClientCustomizer and McpAsyncClientCustomizer to McpClientCustomizer<McpClient.SyncSpec> and <McpClient.AsyncSpec>

same file

org.springframework.ai.migration.MigrateToSpringAI200M3

Umbrella recipe that applies all of the M3 recipes above

same file

The recipe names were read from the community documentation and from the YAML file in the Spring AI repository on 2026-09-29; the recipes themselves were not run for this page. The Spring AI ones are invoked like this, with the plugin version the notes use:

mvn org.openrewrite.maven:rewrite-maven-plugin:6.32.0:run \
  -Drewrite.configLocation=https://raw.githubusercontent.com/spring-projects/spring-ai/refs/heads/main/src/rewrite/migrate-to-2-0-0-M3.yaml \
  -Drewrite.activeRecipes=org.springframework.ai.migration.M3MigrateMcpAnnotations \
  -Dmaven.compiler.failOnError=false

Source: Spring AI: Upgrade Notes (the M3 recipes and the plugin version).

The community recipe is run like this:

./mvnw -U org.openrewrite.maven:rewrite-maven-plugin:run \
  -Drewrite.recipeArtifactCoordinates=io.arconia.migrations:rewrite-spring:LATEST \
  -Drewrite.activeRecipes=io.arconia.rewrite.spring.ai2.UpgradeSpringAi_2_0

Two cautions. A recipe changes source files, so run it on a clean branch and read every hunk; LATEST in the second command floats, so pin a version for a repeatable run. And the M3 note warns that a pom.xml that declares mcp-spring-webflux without a version, relying on a BOM, may fail to parse before the recipe can run, which is why that note tells you to patch those files first. The same community project has io.arconia.rewrite.spring.ai1.UpgradeSpringAi_1_0 for the older 0.8 to 1.0 jump (Arconia: Spring AI 1.0); the Spring AI notes link to it for the 1.0.0-RC1 upgrade.

Modules and dependencies

Table 2. Build and module changes
Old (1.x) New (2.0.1) Notes

spring-ai-advisors-vector-store

spring-ai-vector-store-advisor

upgrade notes

QuestionAnswerAdvisor and VectorStoreChatMemoryAdvisor in org.springframework.ai.chat.client.advisor.vectorstore (since 1.0.0)

Same package, now in the renamed spring-ai-vector-store-advisor artifact; only pre-1.0 milestone code that imports them from org.springframework.ai.chat.client.advisor needs new imports. RetrievalAugmentationAdvisor is in the spring-ai-rag artifact

Read from the 1.0.3 sources and the 2.0.1 jars, not listed in the notes; see Retrieval & RAG Bridge

spring-ai-azure-openai and its starter

spring-ai-openai (drop the Azure prefix on class names; adapt the properties)

upgrade notes

spring-ai-openai-sdk and its starter

spring-ai-openai (which now uses the official openai-java SDK; spring.ai.openai.* properties and builders remain)

upgrade notes

spring-ai-oci-genai

Removed; the Oracle project provides it

upgrade notes

Azure Cosmos DB vector store and chat memory

External module maintained by the Cosmos DB team

upgrade notes

spring-ai-hanadb-store; spring-ai-spring-cloud-bindings

Removed

upgrade notes

MiniMax dedicated support

Use the Anthropic module against MiniMax’s Anthropic-compatible URL

upgrade notes

org.springaicommunity:mcp-annotations

spring-ai-mcp-annotations, package org.springframework.ai.mcp.annotation.*

upgrade notes

io.modelcontextprotocol.sdk:mcp-spring-webflux, mcp-spring-webmvc

org.springframework.ai:mcp-spring-webflux, mcp-spring-webmvc; transport classes in org.springframework.ai.mcp.server. and .client.

upgrade notes

spring-ai-autoconfigure-model-chat-memory-redis, spring.ai.chat.memory.redis.* (2.0.1)

spring-ai-autoconfigure-model-chat-memory-repository-redis, spring.ai.chat.memory.repository.redis.*; the old module still works through a transitive dependency for now

upgrade notes

org.springframework.retry.support.RetryTemplate as the type of Spring AI’s retry bean

org.springframework.core.retry.RetryTemplate (Spring Framework 7); spring.ai.retry.* keeps its names

Read from the 2.0.1 jars, not listed in the notes; see Production & Deployment

Evaluators such as RelevancyEvaluator and FactCheckingEvaluator

Package org.springframework.ai.chat.evaluation, artifact spring-ai-client-chat

Read from the 2.0.1 jars; see Evaluation

Jackson 2 (com.fasterxml.jackson.databind)

Jackson 3 (tools.jackson.databind, JsonMapper); JsonParser deprecated for JsonHelper and JacksonUtils.getDefaultJsonMapper(); JSON methods removed from ModelOptionsUtils; McpJsonParser removed

upgrade notes

OpenSearch client 2.x, Testcontainers class OpensearchContainer

OpenSearch client 3.6, OpenSearchContainer

upgrade notes

Options and properties

Table 3. Options, defaults and property paths
Old (1.x) New (2.0.1) Notes

Mutable options, copy() and fromOptions()

Strictly immutable options; start a builder from one with mutate()

upgrade notes

ChatModel.getDefaultOptions()

getOptions() (the old name is deprecated)

upgrade notes

Defaults set in the property classes

Defaults set in the options constructors

upgrade notes

spring.ai.openai.chat.options.model

spring.ai.openai.chat.model (flattened; the .options form is still accepted and deprecated)

upgrade notes

ChatClient.options(builtOptions), defaultOptions(builtOptions)

Pass the builder: .options(OpenAiChatOptions.builder().temperature(0.2)); it is layered over the model’s start-up options, but it replaces the client’s defaultOptions(…​) rather than merging with them (see Chat Options)

upgrade notes

.N(3) on options builders

.n(3)

upgrade notes

spring.ai.ollama.chat.think-option

spring.ai.ollama.chat.think

upgrade notes

Media.builder().data(Object)

Typed overloads: data(byte[]), data(String), data(URI), data(URL), data(Resource) (2.0.1)

upgrade notes

buildRequestPrompt on models

Not public API any more; and internalCall / internalStream are private: use call and stream

upgrade notes

The 2.0 properties that are new and worth adopting are spring.ai.chat.client.tool-calling.enabled, spring.ai.chat.client.tool-search-advisor., spring.ai.tools.limits., spring.ai.tools.throw-exception-on-error and spring.ai.tools.resolution.fallback.enabled. The full list for your version is in the starters' configuration metadata.

Tools

Table 4. Tool calling
Old (1.x) New (2.0.1) Notes

Each ChatModel runs the tool loop; internalToolExecutionEnabled(false) to run it yourself

The loop lives in ToolCallingAdvisor, auto-registered by ChatClient. ChatModel.call returns the raw tool calls. internalToolExecutionEnabled and its property are removed

upgrade notes

ToolExecutionEligibilityPredicate

ToolExecutionEligibilityChecker on ToolCallingAdvisor.Builder, or as a bean

upgrade notes

ToolCallAdvisor

ToolCallingAdvisor

upgrade notes

FunctionCallback, FunctionCallingOptions, defaultFunctions(…​), .functions(…​)

ToolCallback / FunctionToolCallback, ToolCallingChatOptions, defaultTools(…​), .tools(…​)

upgrade notes

toolNames(…​) and tools found by bean name (SpringBeanToolCallbackResolver)

Attach a ToolCallback or a @Tool object to the request; the resolver is removed. In 2.0.1 the bean fallback is off by default (spring.ai.tools.resolution.fallback.enabled)

upgrade notes

ChatClient ToolSpec consumer

Removed; use tools(…​)

upgrade notes

MethodToolCallbackProvider throwing IllegalStateException

IllegalArgumentException for no @Tool methods or duplicate names

upgrade notes

ToolContext.TOOL_CALL_HISTORY, getToolCallHistory()

Removed; conversation history belongs to the advisors

upgrade notes

Every tool definition sent on every call

New and optional: ToolSearchToolCallingAdvisor (org.springframework.ai.chat.client.advisor.toolsearch, starter spring-ai-starter-tool-search-advisor, spring.ai.chat.client.tool-search-advisor.enabled=true) sends only the tools that match the request

upgrade notes

streamToolCallResponses on the advisor builders and its properties

Removed

upgrade notes

The @Tool and ToolCallbackProvider model itself did not change; see Tool Calling and ToolCallingAdvisor & Tool Search.

ChatClient, advisors and memory

Table 5. ChatClient, advisors and chat memory
Old (1.x) New (2.0.1) Notes

MessageChatMemoryAdvisor.builder(memory).conversationId("s1")

No default conversation ID; pass ChatMemory.CONVERSATION_ID on every call, or the advisor throws IllegalArgumentException. ChatMemory.DEFAULT_CONVERSATION_ID is removed

upgrade notes

PromptChatMemoryAdvisor

MessageChatMemoryAdvisor (same builder API; history goes in as messages, not text in the system prompt)

upgrade notes

BaseChatMemoryAdvisor.getConversationId(Map, String)

getConversationId(Map)

upgrade notes

Memory advisor default order HIGHEST_PRECEDENCE + 1000

Advisor.DEFAULT_CHAT_MEMORY_PRECEDENCE_ORDER = HIGHEST_PRECEDENCE + 200, outside the tool loop (+ 300); memory stores only the final exchange

upgrade notes

JDBC repository table without a sequence column

sequence_id BIGINT column and an index; the timestamp is exposed as metadata

upgrade notes

MongoChatMemoryRepository returning newest first

Oldest first like every other repository; remove any reversal workaround

upgrade notes

ChatClient.create(chatModel) running an internal tool loop

Auto-registers ToolCallingAdvisor; disable with spring.ai.chat.client.tool-calling.enabled=false

upgrade notes

ChatMemory as the only memory abstraction

Unchanged in 2.0. The community spring-ai-session project, which handles tool-call messages, is planned to replace it in 2.1; see Agentic Patterns

upgrade notes

Marker-less advisors

New marker interfaces ToolAdvisor and MemoryAdvisor

upgrade notes

See Chat Memory, Chat Memory Repositories and Advisors for the 2.0.1 behaviour.

Structured output, MCP, audio and observability

Table 6. Other areas
Old (1.x) New (2.0.1) Notes

BeanOutputConverter.postProcessSchema(JsonNode)

Override generateSchema() and call super.generateSchema(). Schemas now use JsonSchemaGenerator with OpenAPI-style format hints, and optional properties are no longer required

upgrade notes

MCP Java SDK 1.x

SDK 2.0.0: server tool-input validation on by default (validateToolInputs(false) to restore the old behaviour); Tool.inputSchema() is a Map<String, Object>; the sealed schema interfaces are open, so exhaustive switch needs a default

upgrade notes

CreateMessageResult.builder(), CreateMessageRequest.builder() with no arguments

Required fields up front: CreateMessageResult.builder(role, content, model), CreateMessageRequest.builder(messages, maxTokens); the no-argument builders are deprecated

upgrade notes

elicit(TypeReference)

ParameterizedTypeReference

upgrade notes

McpSyncClientCustomizer, McpAsyncClientCustomizer; customizeRequest() on transport builders

McpClientCustomizer<B>; httpRequestCustomizer() / asyncHttpRequestCustomizer()

upgrade notes

@McpTool methods that throw a checked exception or Error and expect the model to see it (2.0.1)

Only RuntimeException`s (other than `McpError) reach the model as an error result; the rest fail hard

upgrade notes

SpeechModel, StreamingSpeechModel, SpeechPrompt, SpeechResponse (org.springframework.ai.openai.audio.speech)

TextToSpeechModel, StreamingTextToSpeechModel, TextToSpeechPrompt, TextToSpeechResponse in org.springframework.ai.audio.tts; the speed is a Double. Removed in 1.1.0-RC1, so a 1.1 application has already seen this

upgrade notes

TranscriptionModel alone; OpenAiAudioSpeechModel.stream buffering the whole reply

TranscriptionModel extends StreamingTranscriptionModel (the default stream fails with UnsupportedOperationException); OpenAI speech streams real chunks (2.0.1), so blockFirst() returns only the first chunk

upgrade notes

Tool span tool_call <name>, gen_ai.operation.name=framework

Span execute_tool <name>, gen_ai.operation.name=execute_tool; new spring.ai.tool.type and spring.ai.tool.call.id. Update dashboards and alerts that match the old names

upgrade notes

Provider-specific cache numbers in metadata

Usage.getCacheReadInputTokens() and getCacheWriteInputTokens()

upgrade notes

Provider changes

Table 7. Providers
Old (1.x) New (2.0.1) Notes

AnthropicApi, new AnthropicChatModel(api, options)

AnthropicChatModel.builder(); the module is built on the official anthropic-java SDK; cache classes moved to org.springframework.ai.anthropic; CitationDocument is AnthropicCitationDocument

upgrade notes; Anthropic migration guide

Anthropic maxTokens default 500

4096; set it explicitly if you relied on the old cap to bound cost

same

OpenAI tool schemas strict(true) by default

strict is false unless you set OpenAiChatOptions#strict(true) (2.0.1)

upgrade notes

Default temperature 0.7 supplied by the starters

Removed; each provider’s default applies, so set temperature if you depend on a value

upgrade notes

Mistral moderation dangerousAndCriminalContent

Split into dangerous and criminal, new jailbreaking; chat constants MAGISTRAL_*, DEVSTRAL and OPEN_MISTRAL_NEMO removed (2.0.1)

upgrade notes

GoogleGenAiEmbeddingConnectionDetails in the old package

New package

upgrade notes

Same code, different behaviour

These changes need no edit to compile, and each can change what a running application does. Check every row against your code.

Table 8. Changes that compile but behave differently
Change Effect Notes

Conversation ID mandatory in the built-in memory advisors

Calls that relied on a default ID now throw; a hard-coded ID that used to be shared silently is gone

upgrade notes

Memory advisor outside the tool loop

Tool-call and tool-result messages are no longer written to the repository; only the final user and assistant messages are

upgrade notes

Tool fallback resolution off (2.0.1)

A tool registered only as a bean can no longer be called unless attached to the request; the call fails closed

upgrade notes

Tool call limits (2.0.1)

150 calls per turn and 40 per tool by default; an agent that legitimately needs more must raise them

upgrade notes

Usage accumulated over the tool loop (2.0.1)

Token counts after a tool exchange are now the total, so exact-count assertions and cost dashboards change

upgrade notes

No default temperature

Answers from a model whose own default is 1.0 vary more than they did at 0.7

upgrade notes

OpenAI strict off; Anthropic maxTokens 4096

Schema adherence is checked less strictly; replies can be longer and cost more

see the provider table

MCP server validates tool input

Clients that sent loosely typed arguments now get error results

upgrade notes

@McpTool exception handling (2.0.1)

A checked exception no longer becomes an error message for the model

upgrade notes

HTTP transport header names lower-cased in the WebMvc MCP transport

A custom ServerTransportSecurityValidator that looks up mixed-case names finds nothing

upgrade notes

OpenAI-compatible base-url needs /v1 (checked by running it)

A base URL without /v1 reached POST /chat/completions on a recording server, not /v1/chat/completions, so a local server answers 404. Not in the notes; see Local Models

verified on 2.0.1

Advisor default order 0 for QuestionAnswerAdvisor and RetrievalAugmentationAdvisor (checked by running it)

They sit inside the tool loop, so retrieval runs again on every pass of the loop; give them an order before ToolCallingAdvisor to retrieve once. See Retrieval & RAG Bridge

verified on 2.0.1

Migrating code from the books

Two books in this guide’s bibliography were written against versions before 2.0. Their concepts are sound; their code needs the changes below. The snippets are shapes of the API those versions used, written for this page (not taken from the books), and are not compiled.

Spring AI in Action (Spring AI 1.0.3, Spring Boot 3.5)

Spring AI in Action is close to 2.0 in style: fluent ChatClient, advisors, tools with @Tool, MCP. Most of the migration is the tables above. Its examples typically look like this:

Spring AI 1.0.x style: does not compile on 2.0.1
ChatClient client = ChatClient.builder(chatModel)
    .defaultAdvisors(PromptChatMemoryAdvisor.builder(memory).conversationId("session-1").build())
    .defaultOptions(OpenAiChatOptions.builder().temperature(0.2).build())
    .defaultToolNames("currentWeather")
    .build();

and the 2.0.1 form is:

MigratedDocsAssistant.java: the 2.0.1 forms of the changes above
package com.example.docsassistant;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.ToolCallingAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.model.tool.ToolExecutionEligibilityChecker;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/** The 2.0.1 form of the code the older books and 1.x tutorials show. */
@Configuration(proxyBeanMethods = false)
class MigratedDocsAssistant {

    record WeatherRequest(String city) { }

    record WeatherResponse(String summary) { }

    /** Was: a raw java.util.function.Function bean found by name. Now: an explicit ToolCallback. */
    @Bean
    ToolCallback currentWeather() {
        return FunctionToolCallback.builder("currentWeather",
                        (WeatherRequest request) -> new WeatherResponse("sunny in " + request.city()))
                .description("Get the weather in a city")
                .inputType(WeatherRequest.class)
                .build();
    }

    /** Was: an advisor created with .conversationId("...") or PromptChatMemoryAdvisor. */
    @Bean
    ChatClient memoryClient(ChatModel chatModel, ChatMemory chatMemory, ToolCallback currentWeather) {
        return ChatClient.builder(chatModel)
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
                .defaultTools(currentWeather)   // defaultToolCallbacks(...) is deprecated for removal in 2.0
                .build();
    }

    String ask(ChatClient client, String conversationId, String question) {
        return client.prompt()
                .user(question)
                // options() takes the builder, not a built object; the fields you set override the model's start-up options,
                // and a request's options replace (not merge with) any defaultOptions(...) on the client
                .options(OpenAiChatOptions.builder().temperature(0.2))
                // the conversation id is required and supplied per call; derive it from the authenticated user, never from client input alone
                .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
                .call()
                .content();
    }

    /** Was: options.copy() / fromOptions(). Options are immutable; mutate() starts a builder from one. */
    ChatOptions lowerTemperature(ChatOptions options) {
        return options.mutate().temperature(0.0).build();
    }

    /** Was: internalToolExecutionEnabled(false). Now: decide in the advisor when the loop continues. */
    @Bean
    ToolExecutionEligibilityChecker stopOnFinishReasonStop() {
        return response -> response != null && response.hasToolCalls()
                && !"stop".equals(response.getResult().getMetadata().getFinishReason());
    }

    ToolCallingAdvisor insideTheLoopHistory() {
        return ToolCallingAdvisor.builder().disableInternalConversationHistory().build();
    }
}

The class compiled against 2.0.1. It is not a program to run; each method shows one change:

  • the Function bean found by name becomes an explicit ToolCallback and is attached to the client;

  • the memory advisor is MessageChatMemoryAdvisor, with the conversation ID passed on each call;

  • options(…​) takes the builder;

  • mutate() replaces copy();

  • a ToolExecutionEligibilityChecker and ToolCallingAdvisor.builder() replace internalToolExecutionEnabled.

Other points for the Spring AI in Action examples, in the book’s own order of topics:

Table 9. Book topics and their 2.0.1 equivalents (Spring AI in Action)
Topic What to change

Getting started, Azure OpenAI

spring-boot-starter-web is now spring-boot-starter-webmvc in Initializr; Azure OpenAI runs through the OpenAI module, see Setup & Starters

Prompts, options

Options are builders; .options is gone from property paths; ChatClient.options(…​) takes a builder; see Chat Options

RAG

Same concepts, builders and packages; rename the spring-ai-advisors-vector-store dependency to spring-ai-vector-store-advisor and add spring-ai-rag for the modular advisor; see Integrating with Spring AI

Memory

Add a conversation ID to every call; PromptChatMemoryAdvisor is removed; the JDBC schema gains sequence_id; see Chat Memory Repositories

Tools

@Tool and @ToolParam are unchanged; bare Function beans need FunctionToolCallback; tools are attached per request; see Tool Calling

MCP

Annotations moved to org.springframework.ai.mcp.annotation.*; SDK 2.0 validates inputs; the server protocol property is spring.ai.mcp.server.protocol; see MCP Server and MCP Client

Observability, security

Update dashboards for execute_tool; see Observability and Security & Guardrails

Agents, Embabel

The book’s Embabel chapter predates the 1.x releases; see Agentic Patterns

Mastering Spring AI (Spring AI 0.8.x)

Mastering Spring AI predates the fluent ChatClient, advisors, chat memory and MCP; it is a good source for concepts, prompt types and governance, and almost none of its code compiles today. Migrating from it is a rewrite in the direction of the 1.0 API followed by the 2.0 tables. These renames happened across the 0.8 to 1.0 milestones, before the current upgrade notes begin; treat the table as a map, and confirm each name in the 2.0.1 reference before relying on it.

Spring AI 0.8.x style: does not compile on 2.0.1
BeanOutputParser<Actor> parser = new BeanOutputParser<>(Actor.class);
String format = parser.getFormat();
ChatResponse response = chatClient.call(new Prompt(question + format));
Actor actor = parser.parse(response.getResult().getOutput().getContent());

@Bean
FunctionCallback weather() {
    return FunctionCallbackWrapper.builder(new WeatherService())
        .withName("CurrentWeather").withDescription("Get the weather").build();
}

Source: Spring AI: Upgrade Notes (the 1.0.0-M7 and 1.0.0-RC1 sections list the renames).

Table 10. Book API and its current form
0.8.x API 2.0.1 form Notes

ImageClient

ImageModel, see Image Generation

rename

OpenAiAudioTranscriptionClient

OpenAiAudioTranscriptionModel behind TranscriptionModel, see Audio Transcription & Speech

rename

BeanOutputParser, getFormat()

BeanOutputConverter, or simply .entity(Actor.class), see Structured Output

rename

getContent() on messages

getText()

rename

FunctionCallbackWrapper, FunctionCallback

@Tool methods, or FunctionToolCallback, see Tool Calling

upgrade notes

Manual history in the prompt

MessageChatMemoryAdvisor with ChatMemory, see Chat Memory

new since the book

chatClient.call(prompt) on the model-level ChatClient

ChatModel.call(prompt), or the fluent ChatClient.prompt()…​call(), see ChatModel & ChatClient

the old model-level interface became ChatModel

Starter names like spring-ai-openai-spring-boot-starter

spring-ai-starter-model-openai, spring-ai-starter-vector-store-pgvector, …​

upgrade notes

Milestone and snapshot repositories in the POM

Not needed: 2.0.x is on Maven Central

see Setup & Starters

javax.* imports

jakarta.*

Boot 3 and later

Function calling by name in the prompt options

Tools attached to the request

see the Tools table

Governance, LLMOps, scaling chapter

Concepts still apply; see Production & Deployment for the current APIs

The 1.0 upgrade notes for the milestone renames of memory (…​Repository suffixes and spring.ai.chat.memory.repository.*), observability (include-prompt became log-prompt) and starters are on the 1.0.0-RC1 and 1.0.0-M7 sections of the same page.

Verify the upgrade

Compiling is not enough. After the mechanical changes:

  • Run the scripted-model tests: they catch wiring, advisor order and tool-loop changes without a provider.

  • Run the evaluation set against the same model before and after, and compare answers, latency, token use and cost; see Evaluation. Answers change with the default temperature and with structured-output schema changes even when the model is the same.

  • Check the metrics and dashboards listed in Observability for the renamed tool span and the accumulated usage.

  • Read the startup log for deprecation warnings on .options property paths and fix them now; the deprecated forms exist to ease the transition.

  • Re-test the security paths from Security & Guardrails: per-request tool registration, @PreAuthorize on tools and the conversation ID derived from the token.