Every agent builder knows this failure mode. You give the agent a task, "plan our team offsite", and it just runs. It picks a city. It picks a budget. It picks the one week half the team is on holiday. Now you're not reviewing a plan. You're undoing one.
The Spring AI team put it well in their AskUserQuestionTool post: the AI makes assumptions, and each assumption creates rework. Their fix is a tool that flips the default. The agent asks first, and acts only once it has real answers.
ByteChef is an open-source workflow automation and AI agent platform built on Spring AI, so it runs the same tool. In Part 1 we gave agents know-how with skills. In this part we teach them to ask.
TL;DR: The Ask User Question Tool lets a ByteChef AI Agent stop and ask the user 1 to 4 multiple-choice questions before it acts. In a deployed chat, the workflow suspends for up to 30 days and resumes when the answers arrive. No thread is held while it waits. Try it with the offsite planner template.
The example: an offsite planner that asks first
The template has three steps:
- New Chat Request - a message arrives in the workflow chat.
- AI Agent - the Chat (stream) action with an Anthropic model, Chat Memory, and the Ask User Question Tool in its Tools slot.
- Reply - the plan goes back to the chat.
The system prompt does the real work:
You plan team events. Never guess requirements. Before you plan anything,
call the AskUserQuestionTool once with three or four multiple-choice
questions covering budget, dates, team size and location. Offer 3 or 4
concrete options per question. After the answers arrive, produce a
one-page plan.
Two rules matter here:
- "Never guess requirements" tells the model that asking is expected, not a failure.
- "Call the tool once" stops it from asking one question at a time and dragging the conversation out.
What the model actually sees
The tool comes from Spring AI's spring-ai-agent-utils toolkit. The model sees a tool named AskUserQuestionTool that takes 1 to 4 questions. Each question has:
-
header- a short label, 12 characters max, like "Budget" -
question- the question itself -
options- 2 to 4 choices, each with alabeland adescription -
multiSelect- for questions where more than one answer fits
For the offsite planner, a call looks roughly like this:
{
"questions": [
{
"header": "Budget",
"question": "What's the total budget for the offsite?",
"multiSelect": false,
"options": [
{ "label": "Under $5k", "description": "Local venue, day trips" },
{ "label": "$5k to $15k", "description": "Nearby city, one night" },
{ "label": "$15k+", "description": "Travel, multiple nights" }
]
},
{
"header": "Dates",
"question": "Which week works best?",
"multiSelect": true,
"options": [
{ "label": "Mid May", "description": "Before summer holidays" },
{ "label": "Early June", "description": "Good weather, busier venues" },
{ "label": "September", "description": "After holidays, everyone back" }
]
}
]
}
The model writes these itself, from the user's request and your system prompt.
In plain Spring AI you'd also write a question handler: the code that shows the questions and collects the answers. On a console, that's reading a line from stdin. In a real product, the user might answer in ten seconds or tomorrow, from a different device. That gap is what ByteChef fills.
What happens when the agent asks
When the agent calls the tool, ByteChef sends the questions to the chat as an ask_user_question event. The chat renders each question with its header and a numbered list of options. You answer by typing, so you can pick an option or write your own answer.
Here's a real test run. Asked to plan a two-day offsite, the agent sent four questions instead of a plan:
What happens next depends on where the chat runs.
In a deployed workflow, the questions come with a resume URL and the workflow suspends. It isn't holding a thread. The run is persisted and can wait up to 30 days. When you answer, the chat posts to the resume URL, and the AI Agent picks up exactly where it stopped, with your answers as the tool result, and streams the plan back.
In the editor's test chat, there's no resume URL. The questions still show, but the agent is told to end its turn and read the answers from your next message. Because the template has Chat Memory, the agent still sees its own questions when your answer arrives, so it behaves the same.
This suspend/resume mechanism is the same one behind ByteChef's Approval component. Waiting for someone to approve and waiting for someone to answer are the same problem: a run that has to stop, wait for days, survive a restart, and continue on an outside signal.
Two limits worth knowing:
- The tool needs the Chat (stream) action. With the non-streaming Chat action there's no way to deliver the questions, so the agent is told to proceed on its best judgment and state its assumptions.
- If the questions can't be delivered, the agent gets the same instruction. It never waits for answers nobody can see.
Try it in 4 steps
The template needs only an Anthropic connection.
- Import the template. Open Plan a team offsite with an agent that asks before it plans and add it to a project.
- Connect the model. Add your Anthropic connection to the model under the AI Agent.
- Test it in the editor. Open the chat and write "Plan an offsite for my team." You should get 3 or 4 questions back instead of a plan. Reply with your choices in one message and the agent writes the plan.
- Deploy it. Deploy the project, open Chats in the Automation sidebar, and pick the workflow. Now the run really pauses while it waits for you.
Thanks to Chat Memory, you can ask for changes afterwards, like "move it to September", without starting over.
Why asking first matters
It's tempting to treat clarifying questions as polite extras. For agents, they're closer to a correctness tool:
- They prevent rework. A wrong guess costs the failed step, the tokens spent getting there, and the turns you spend correcting it. One round of questions is cheaper.
- They're a natural human-in-the-loop gate. For anything that matters, like spending money, emailing a customer, or deleting records, "ask before acting" is the safe default.
- They don't tie anything up. A deployed run actually suspends. The agent can wait days without holding a worker.
Spring AI vs. ByteChef: what you get for free
The Spring AI post ends where a library ends: here's the tool, write a handler. Here's what ByteChef adds on top:
| Plain Spring AI | ByteChef |
|---|---|
| You implement the question handler | Built in |
| A console handler blocks the current thread | Deployed workflow suspends up to 30 days and frees the worker |
| Getting questions to a UI is your job | Streamed to the chat, run resumes when the answer is posted back |
| Adding the tool means code and config | One tool on the AI Agent |
The question format, the library, and model portability stay the same. The template uses Claude, but the tool works with any model provider ByteChef supports.
Wrapping up
The most useful agent behaviors are often the boring ones. "Ask before you assume" isn't flashy, but it's the difference between an agent whose work you undo and one whose work you can trust.
Import the offsite planner template, add your Anthropic connection, and ask it to plan your next offsite. Then add the Ask User Question Tool to your own agents wherever a guess would be expensive.
If you like where this is going, a star on GitHub helps a lot.
Originally published on the ByteChef blog.


Top comments (0)