[spring-ai] ToolConverter silently drops enum and items from tool parameter schemas
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
Research direction
The drop happens in ToolConverter#convertSchemaToSpringAi, reached from convertToSpringAiTools when each ToolDefinition input schema is built; start by reading that method and the genai Schema and Spring AI schema types it maps between. Reproduce with the issue's minimal example (an enum string property plus an array property with items), then map enum_ and items per property, recursing into nested properties. Done means the emitted inputSchema JSON contains enum and items for those parameters while the existing ToolConverter tests still pass.
Written by the indexing model from the issue text.
Description
Describe the Bug
ToolConverter#convertSchemaToSpringAi (used by convertToSpringAiTools) maps only
type, properties, description and required when converting a genai Schema
to a Spring AI ToolDefinition input schema. enum and items are silently
dropped.
Impact: any ADK tool whose parameters use enum-constrained strings or typed arrays —
including the mainstream path of annotated FunctionTool methods (enum Java fields,
List<String> parameters) — ends up with a degraded schema sent to the model:
enum parameters become free-form strings (models then send invalid values), and array
parameters lose their element type.
Steps to Reproduce
- Define a
BaseToolwhosedeclaration()returns aFunctionDeclarationwith
parameterscontaining an enum property and an array-with-items property. - Convert it via
new ToolConverter().convertToSpringAiTools(...). - Inspect
getToolDefinition().inputSchema()— noenum, noitems.
Expected Behavior
enum, items (and ideally format, nullable, minItems/maxItems) survive the
conversion, so the model receives the same parameter constraints the ADK tool declared.
Observed Behavior
Identical output on 1.9.0 and 1.11.0 (latest):
declared: color = string + enum ["red","green"], tags = array of string (items)
converted inputSchema:
{"description":"参数","type":"object","properties":{"color":{"description":"颜色","type":"string"},"tags":{"description":"标签","type":"array"}},"required":["color"]}
^ no "enum" ^ no "items"
Environment Details
- ADK Library Version: verified on 1.9.0 and 1.11.0 with identical output;
on currentmain,convertSchemaToSpringAistill only emitstype/properties - OS: macOS (logic bug, OS-independent)
- TS Version: N/A (Java)
Model Information
Model-independent — the loss happens in tool-definition conversion before any model
call. Observed with GLM via an OpenAI-compatible gateway.
Regression
N/A.
Additional Context
We maintain a patched bridge for this reason (among others): we bypass the wrapped
conversion and restore the original callbacks per tool name so the raw schema reaches
the model. A minimal fix is to map enum_ and items in convertSchemaToSpringAi;
serializing the genai Schema to JSON directly would also work and would future-proof
against further field drift.
Minimal Reproduction Code
Schema color = Schema.builder().type("string")
.description("颜色").enum_(List.of("red", "green")).build();
Schema tags = Schema.builder().type("array")
.description("标签").items(Schema.builder().type("string").build()).build();
Schema params = Schema.builder().type("object")
.properties(Map.of("color", color, "tags", tags))
.required(List.of("color"))
.build();
BaseTool tool = new BaseTool("probeTool", "probe") {
@Override public Optional<FunctionDeclaration> declaration() {
return Optional.of(FunctionDeclaration.builder()
.name("probeTool").description("probe").parameters(params).build());
}
@Override public Single<Map<String, Object>> runAsync(Map<String, Object> args, ToolContext ctx) {
return Single.just(Map.of());
}
};
String schema = new ToolConverter()
.convertToSpringAiTools(Map.of("probeTool", tool))
.get(0).getToolDefinition().inputSchema();
// schema contains no "enum" and no "items"
How often has this issue occurred?
Always (100%) — every enum/array tool parameter.
- Dominant language
- Java
- Stars
- 1.7k
- Forks
- 431
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 46
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from google/adk-java
-
GeminiUtil placeholder user turn ("Continue output. DO NOT look at this line ...") is flagged by prompt injection filtersPossibly taken @innoprej claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
[spring-ai] Streaming responses ending with CJK punctuation (。!?) are misclassified as partial and never persisted to the sessionPossibly taken @hirematha claimed this 3 days ago. Openwaiting on reporter
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
google/adk-java#1608 · 2 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
[core] Client disconnects don't cancel the model stream (per-step flow is cached) — and there is no public API to cancel an in-flight runPossibly taken @hemasekhar-p claimed this 2 days ago. Openneeds review
google/adk-java#1618 · 6 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
[spring-ai] Bridge drops reasoning_content (thinking) — surface it as partial events and/or persist itPossibly taken @hemasekhar-p claimed this 3 days ago. Openneeds review
google/adk-java#1616 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
-
[FEATURE] Port bypass_multi_tools_limit for built-in search tools from adk-pythonPossibly taken @hirematha claimed this 3 days ago. Openneeds review
Difficulty 5/5 Over a week Newbie friendliness 35/100
google/adk-java#1598 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
liquid-java/liquidjava#373 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
NationalSecurityAgency/ghidra#9748 ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
spring-mcp-tools
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
explyt/spring-plugin#591 ·
Maintainers usually reply within 1 day