Describe the Bug
Spring AI OpenAI 2.0.0 final fails when a Prompt contains provider-neutral ToolCallingChatOptions.
This is exposed by google-adk-spring-ai, which creates generic Spring AI ChatOptions / ToolCallingChatOptions when converting ADK requests into Spring AI prompts. In Spring AI OpenAI 2.0.0 final, OpenAiChatModel.createRequest(...) casts Prompt.getOptions() directly to OpenAiChatOptions, causing a ClassCastException.
This behavior does not appear to occur with Spring AI OpenAI 2.0.0-M4. Based on local testing, 2.0.0-M4 appears to normalize generic prompt options into OpenAiChatOptions before request creation, while 2.0.0 final only injects default options when prompt options are null, allowing non-null generic options to reach the later cast.
Steps to Reproduce
-
Create a Java project using:
com.google.adk:google-adk:1.4.0
com.google.adk:google-adk-spring-ai:1.4.0
- Spring AI BOM
2.0.0
- Spring AI OpenAI
2.0.0
-
Configure an OpenAI-backed Spring AI ChatModel.
-
Create an ADK LlmAgent using SpringAI(chatModel, modelName).
-
Register at least one tool with the agent.
-
Invoke the agent so a tool-enabled request is sent to the model.
-
Observe the runtime exception below.
Expected Behavior
One of the following should occur:
- Spring AI OpenAI continues accepting or normalizing generic Spring AI
ToolCallingChatOptions, as appears to have happened in 2.0.0-M4, or
- ADK integrations can safely pass provider-neutral Spring AI options without causing runtime failures, or
- The Spring AI OpenAI contract clearly documents that only
OpenAiChatOptions are supported in Prompt.getOptions().
Observed Behavior
The request fails with:
java.lang.ClassCastException: class org.springframework.ai.model.tool.DefaultToolCallingChatOptions
cannot be cast to class org.springframework.ai.openai.OpenAiChatOptions
Stack trace:
at org.springframework.ai.openai.OpenAiChatModel.createRequest(OpenAiChatModel.java:683)
at org.springframework.ai.openai.OpenAiChatModel.call(OpenAiChatModel.java:194)
at com.google.adk.models.springai.SpringAI.generateContent(SpringAI.java:176)
Environment Details
- ADK Library Version (see maven dependency):
1.4.0
- OS: macOS and Linux
- TS Version (tsc --version): N/A (Java project)
Model Information
- Which model is being used: OpenAI-compatible model via Spring AI OpenAI (for example
gpt-4o)
🟡 Optional Information
Regression
Yes.
Local validation results:
- ADK
1.4.0 + Spring AI 2.0.0: fails with DefaultToolCallingChatOptions -> OpenAiChatOptions cast.
- ADK
1.4.0 + Spring AI 2.0.0-M4: no cast failure; request proceeds to model authentication.
Logs
java.lang.ClassCastException: class org.springframework.ai.model.tool.DefaultToolCallingChatOptions
cannot be cast to class org.springframework.ai.openai.OpenAiChatOptions
at org.springframework.ai.openai.OpenAiChatModel.createRequest(OpenAiChatModel.java:683)
at org.springframework.ai.openai.OpenAiChatModel.call(OpenAiChatModel.java:194)
at com.google.adk.models.springai.SpringAI.generateContent(SpringAI.java:176)
Screenshots / Video
N/A
Additional Context
When tools are present, ADK appears to construct generic Spring AI options using:
ToolCallingChatOptions.builder()
Spring AI OpenAI 2.0.0-M4 appears to normalize these options into OpenAiChatOptions before request creation.
Spring AI OpenAI 2.0.0 final appears to only replace options when they are null, then later casts non-null generic options in createRequest(...), resulting in the ClassCastException.
Because ADK emits provider-neutral Spring AI options, this causes tool-enabled ADK agents backed by Spring AI OpenAI 2.0.0 to fail consistently at runtime.
Minimal Reproduction Code
ChatModel chatModel = ...; // OpenAI-backed Spring AI ChatModel
BaseAgent agent =
LlmAgent.builder()
.name("test-agent")
.model(new SpringAI(chatModel, "gpt-4o"))
.tools(myTool)
.build();
// Invoke the agent so ADK converts a tool-enabled request into a Spring AI Prompt.
How often has this issue occurred?
Describe the Bug
Spring AI OpenAI
2.0.0final fails when aPromptcontains provider-neutralToolCallingChatOptions.This is exposed by
google-adk-spring-ai, which creates generic Spring AIChatOptions/ToolCallingChatOptionswhen converting ADK requests into Spring AI prompts. In Spring AI OpenAI2.0.0final,OpenAiChatModel.createRequest(...)castsPrompt.getOptions()directly toOpenAiChatOptions, causing aClassCastException.This behavior does not appear to occur with Spring AI OpenAI
2.0.0-M4. Based on local testing,2.0.0-M4appears to normalize generic prompt options intoOpenAiChatOptionsbefore request creation, while2.0.0final only injects default options when prompt options arenull, allowing non-null generic options to reach the later cast.Steps to Reproduce
Create a Java project using:
com.google.adk:google-adk:1.4.0com.google.adk:google-adk-spring-ai:1.4.02.0.02.0.0Configure an OpenAI-backed Spring AI
ChatModel.Create an ADK
LlmAgentusingSpringAI(chatModel, modelName).Register at least one tool with the agent.
Invoke the agent so a tool-enabled request is sent to the model.
Observe the runtime exception below.
Expected Behavior
One of the following should occur:
ToolCallingChatOptions, as appears to have happened in2.0.0-M4, orOpenAiChatOptionsare supported inPrompt.getOptions().Observed Behavior
The request fails with:
Stack trace:
Environment Details
1.4.0Model Information
gpt-4o)🟡 Optional Information
Regression
Yes.
Local validation results:
1.4.0+ Spring AI2.0.0: fails withDefaultToolCallingChatOptions -> OpenAiChatOptionscast.1.4.0+ Spring AI2.0.0-M4: no cast failure; request proceeds to model authentication.Logs
Screenshots / Video
N/A
Additional Context
When tools are present, ADK appears to construct generic Spring AI options using:
Spring AI OpenAI
2.0.0-M4appears to normalize these options intoOpenAiChatOptionsbefore request creation.Spring AI OpenAI
2.0.0final appears to only replace options when they arenull, then later casts non-null generic options increateRequest(...), resulting in theClassCastException.Because ADK emits provider-neutral Spring AI options, this causes tool-enabled ADK agents backed by Spring AI OpenAI
2.0.0to fail consistently at runtime.Minimal Reproduction Code
How often has this issue occurred?