Spring AI Is Quietly Becoming an Agent Runtime

Spring AI 2.1 takes Session. The agent runtime ships in November 2026 as an experimental project, with a plan to merge it into Spring AI 3.0 around mid-2027.

Spring AI 2.0.0 shipped on 12 June 2026. The change that matters for agents is where the tool loop lives. In 1.x, a ChatModel could keep calling tools inside call . In 2.0, ChatModel.call returns the model's raw response. ChatClient registers a ToolCallingAdvisor , executes the tools the model asked for, and re-enters the advisor chain until the model stops asking. MCP tools come in through the same callback path, on MCP Java SDK 2.0. DateTimeTools is the class from the Spring AI tool docs. @Tool has been the method marker since the 1.0 milestones. The calls under it are what changed. the tool, unchanged from Spring AI 1.0 through 2.0 class DateTimeTools { @Tool(description = "Get the current date and time in the user's timezone") String getCurrentDateTime() { return LocalDateTime.now() .atZone(LocaleContextHolder.getTimeZone().toZoneId()) .toString(); } } Spring AI 1.x. The model ran the tools before call returned ChatResponse response = chatModel.call(new Prompt("What day is tomorrow?", ToolCallingChatOptions.builder() .toolCallbacks(ToolCallbacks.from(new DateTimeTools())) .internalToolExecutionEnabled(true) .build())); internalToolExecutionEnabled lived on ToolCallingChatOptions and on each provider's options. true was the internal loop. false meant you drove it. Spring AI 2.0 deletes the method. Both lines stop compiling. The upgrade notes say the behavior behind true is gone from every ChatModel . Spring AI 2.0. Same question, loop on the advisor String answer = ChatClient.create(chatModel) .prompt("What day is tomorrow?") .tools(new DateTimeTools()) .call() .content(); With tools present, ChatClient auto-registers ToolCallingAdvisor . You do not pass the 1.x flag. The advisor re-enters the chain until the model stops asking for tools. Spring AI 2.0. ChatModel.call no longer runs tools ChatResponse raw = chatModel.call(new Prompt("What day is tomorrow?", ToolCallingChatOptions.builder() .toolCallbacks(ToolCallbacks.from(new DateTimeTools())) .build())); raw.hasToolCalls() can be true and nothing has executed. From here you drive ToolCallingManager yourself, or you stay on ChatClient . This is the shape I want when I am testing the model. It is a bad shape for a workflow that must survive a restart. Spring AI 2.0. MCP tools are explicit ChatClient chatClient = ChatClient.builder(chatModel) .defaultTools(mcpTools) .build(); mcpTools is the auto-configured SyncMcpToolCallbackProvider . Spring does not register it on the client for you, because listing tools would call every MCP server at startup. .tools(mcpTools) on a single prompt is the per-call form. Turn the bean off with spring.ai.mcp.client.toolcallback.enabled=false . That is an agentic loop. It is also one request. The advisor can see each iteration. Memory, retries, and a guardrail can sit on the chain with it. When the HTTP call ends, the loop ends with it. A JVM restart has nothing to resume, because nothing in that chain was a workflow. I still want that loop. A recruiter question that needs one tool and one answer should stay a ChatClient call. The mistake is naming that call a runtime. April put it in 2.1. September moved it At Spring I/O, on 14 April 2026, Christian Tzolov walked a roadmap that Deleuze posted the same day. Spring AI 2.0, aimed at May, was the Boot 4 baseline, Jackson 3, null safety, and MCP, with the work spent on consistency. Spring AI 2.1, aimed at November, was a dedicated agentic API and annotations, durable workflow, and sessions. Spring AI 3.0, aimed at May 2027, was one virtual-thread stack, so a team would stop choosing between a blocking client and a reactive one. Two weeks later, on discussion #5917, someone asked how to keep a multi-agent workflow alive across steps, retries, and restarts. Deleuze answered with a module name: spring-ai-agent , for stateful agentic features and some kind of workflow management. He wanted it flexible. He also asked people to explore that design in a separate project, and to hold the pull request. September made the split concrete. Deleuze wrote that key parts of Spring AI Session should land in 2.1.0-RC1, and that the new agentic support would release in November 2026 as a separate project under Spring Projects Experimental, with a plan to merge it into Spring AI 3.0 mid next year. The GitHub milestone for 2.1.0-RC1 is dated 22 October 2026. I am writing on 15 October. I have not compiled that RC. The date is a milestone, and the September note is the commitment I am using. The September note does not publish a repository name. In April the module was spring-ai-agent . I am not going to invent a product name on top of that. When the repo appears, the name on the repo is the name. What 2.1.0-M1 did ship is a second OpenAI model, not an agent runtime. The 2.1 reference says the line is still in development and points a stable app at 2.0.1. I have not compiled the milestone. The types below are the ones that page documents. properties · Spring AI 2.1. Pick the Responses endpoint spring.ai.openai.chat.api=responses One ChatModel bean. responses creates OpenAiResponsesChatModel and skips OpenAiChatModel . The API key stays under spring.ai.openai . A second model bean makes ChatClient auto-configuration ambiguous, so the docs say to mark one @Primary or build the clients yourself. Spring AI 2.1. Reasoning options on one call ChatResponse response = chatModel.call(new Prompt("Plan the approval step.", OpenAiResponsesChatOptions.builder() .model("gpt-5-mini") .reasoningEffort("medium") .reasoningSummary("auto") .maxOutputTokens(1024) .build())); The model is stateless. Every request sends store: false , and that is not configurable. OpenAI is not holding the thread. A reasoning turn comes back as message parts: ReasoningPart , ToolCallPart , TextPart . Drop the encrypted reasoning blob and the next turn just reasons again. The same page says only InMemoryChatMemoryRepository keeps those parts today, and that durable memory for them is expected in 2.1.0-M2. java · Spring AI 2.1. Tools still need the advisor String answer = ChatClient.create(chatModel) .prompt() .advisors(ToolCallingAdvisor.builder().build()) .tools(new DateTimeTools()) .user("What day is tomorrow?") .call() .content(); This is the sample on the 2.1 Responses page. OpenAiResponsesChatModel runs no tool loop of its own. Hosted tools such as HostedTool.WebSearch execute inside OpenAI's request and show up as metadata, not as a local @Tool . None of this remembers a workflow after the process exits. A tool loop ends when the request ends. A workflow has to answer after the process comes back. The stack I would draw The picture I had in my head put sessions, memory, workflows, and the agent runtime in one new project, and then dropped that project into 3.0. The announcements split those layers. Session is moving into the library now. The runtime is the part that waits outside. Where each layer sits on 15 October 2026. The November and 2027 rows are the published plan, not a release I have built against. Layer Where it sits What it owns Spring AI 1.x Released Chat client, prompts, retrieval, early tools and advisors Spring AI 2.0 GA, 12 June 2026 Advisor chain, tool loop, MCP 2.0 Spring AI 2.1 M1 on 25 September. RC1 milestone 22 October Responses API, and key parts of Session Experimental agent project Announced for November 2026 Stateful agents and durable workflow. Repo name not in the note Spring AI 3.0 Keynote: May 2027. Merge: mid-2027 One virtual-thread stack, and that project once it graduates 3.0 is two promises sitting on the same year. The April keynote described the runtime model: virtual threads, one stack. The September note described the produ...