How Spring AI’s AskUserQuestionTool Enables Zero‑Deviation Requirements
This article introduces Spring AI’s AskUserQuestionTool, a portable Java utility that lets AI agents ask clarification questions before answering, eliminating prompt‑driven misalignments, and demonstrates its configuration, workflow, and a complete runnable example on Spring Boot 3.5.0.
1. Introduction
Traditional AI interactions follow a single‑prompt model: the user provides a prompt, the model makes assumptions, and generates a response. When those assumptions do not match the user’s intent, repeated revisions are required, causing wasted time, cost, and loss of context.
The AskUserQuestionTool (User Question Tool) addresses this problem by allowing an AI agent to ask clarification questions before producing an answer, thereby collecting the exact requirements up front.
Spring AI brings this interactive pattern to the Java ecosystem while keeping the large language model (LLM) portable—once the question‑handling logic is defined, it works with OpenAI, Anthropic, Google Gemini, or any other supported model without code changes.
2. Practical Example
2.1 Tool Mechanics
AskUserQuestionTool is part of the spring-ai-agent-utils package and is a Spring‑AI port of Claude Code’s AskUserQuestion tool. It enables an AI agent to pose multiple‑choice questions to the user during execution.
The tool follows this workflow:
AI generates a question: The agent decides that user input is needed, builds a question (including text, title, 2‑4 options, and a multi‑select flag), and calls the askUserQuestion function.
User provides an answer: A custom handler receives the question, displays it via the UI, collects the response, and returns it to the AI.
Additional questioning: If further clarification is required, steps 1 and 2 repeat.
AI continues with context: The agent uses the collected answers to produce a solution that matches the user’s real needs.
Each question supports single‑ or multi‑selection, free‑text input, and rich contextual descriptions for every option.
2.2 Relationship to MCP Elicitation
Conceptually, AskUserQuestionTool mirrors the MCP Elicitation capability, which requests structured user input via JSON Schema from an MCP server. Unlike MCP Elicitation, AskUserQuestionTool operates entirely within the agent, requiring no external server.
Spring AI also provides the @McpElicitation annotation for server‑driven scenarios, offering full MCP Elicitation support.
2.3 Environment Setup
Environment: Spring Boot 3.5.0
Dependencies
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<dependency>
<groupId>org.springaicommunity</groupId>
<artifactId>spring-ai-agent-utils</artifactId>
</dependency>Configuration (application.yml)
spring:
ai:
openai:
api-key: ${API_KEY}
base-url: ${API_BASE_URL}
chat:
model: deepseek-v4-flashChatClient bean
@Configuration
public class ChatClientConfig {
@Bean
ChatClient chatClient(ChatClient.Builder builder) {
return builder
.defaultAdvisors(new SimpleLoggerAdvisor())
.defaultTools(AskUserQuestionTool.builder()
.questionHandler(this::handleQuestions)
.build())
.build();
}
}Question handler implementation
private Map<String, String> handleQuestions(List<Question> questions) {
Map<String, String> answers = new HashMap<>();
Scanner scanner = new Scanner(System.in);
for (Question q : questions) {
System.out.println("
" + q.header() + ": " + q.question());
for (int i = 0; i < q.options().size(); i++) {
Option opt = q.options().get(i);
System.out.printf(" %d. %s - %s%n", i + 1, opt.label(), opt.description());
}
System.out.println(q.multiSelect() ? " (Enter numbers separated by commas, or type custom text)"
: " (Enter a number, or type custom text)");
String response = scanner.nextLine().trim();
try {
String[] parts = response.split(",");
List<String> labels = new ArrayList<>();
for (String part : parts) {
int index = Integer.parseInt(part.trim()) - 1;
if (index >= 0 && index < q.options().size()) {
labels.add(q.options().get(index).label());
}
}
answers.put(q.question(), labels.isEmpty() ? response : String.join(", ", labels));
} catch (NumberFormatException e) {
answers.put(q.question(), response);
}
}
return answers;
}2.4 Testing with CommandLineRunner
A CommandLineRunner bean runs the agent and triggers the tool:
@Component
public class AskQuestionRunner implements CommandLineRunner {
private final ChatClient chatClient;
@Override
public void run(String... args) throws Exception {
String response = chatClient.prompt()
.user("你准备去中国的哪个地方旅游? 你应该使用 `AskUserQuestionTool` 工具")
.call()
.content();
System.err.println(response);
}
}When executed, the tool automatically generates three clarification questions. The user selects options by entering numbers, and the agent then produces a final answer that aligns perfectly with the clarified requirements.
Sample run screenshots (shown below) illustrate the generated questions and the final AI response.
3. Conclusion
The AskUserQuestionTool brings interactive, clarification‑driven AI to Spring applications, removing the need for repeated prompt tweaking and preserving conversation context. Its model‑agnostic design, seamless Spring integration, and straightforward configuration make it a practical solution for building zero‑deviation AI‑assisted workflows.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
