Lets AI agents ask structured clarifying questions with a beautiful tabbed modal UI.
Instead of guessing what the user wants, the agent presents clear options and lets the user choose β directly inside the Agent Zero web interface.
- Structured Questions β Agent presents 1β4 questions, each with 2β4 predefined options
- Tabbed Modal UI β Clean, animated tabbed interface that fits the Agent Zero dark theme
- Markdown Previews β Options can include markdown preview panes for rich context
- Multi-Select Support β Allow users to pick multiple options per question
- Free-Text "Other" β Users can always type a custom answer beyond the provided options
- Optional Notes β Each question has a notes field for additional context
- Review & Submit β Final review tab shows all answers before submission
- Non-Blocking β The tool waits for user input without breaking the agent loop
- Timeout Handling β Configurable timeout (default 300s) with graceful fallback
- Notification Integration β Pushes a notification when questions are pending
- Responsive Design β Works on desktop and mobile viewports
- The agent calls the
ask_user_questiontool with a JSON payload of questions - The tool creates a pending session and fires a notification
- It blocks (async) until the user answers or the timeout expires
- The structured answers are returned to the agent as a formatted message
- The frontend polls for pending questions every 2 seconds
- When a question is detected, a modal appears with tabbed questions
- The user selects options, adds notes, and submits
- The answer is sent to the backend API, which signals the waiting tool
In your Agent Zero instance, go to Settings β Plugins β Browse and search for "Ask User Question".
- Clone this repository into your Agent Zero plugins directory:
cd /path/to/agent-zero/usr/plugins
git clone https://github.com/Reaperrhs/a0-plugin-ask-user-question.git ask_user_question-
Restart Agent Zero (or reload plugins from settings).
-
The plugin auto-registers:
- Tool:
ask_user_question(available to the agent) - API endpoints:
/plugins/ask_user_question/get_pendingand/plugins/ask_user_question/submit_answer - WebUI extension: Modal component injected into the chat page
- Tool:
{
"questions": [
{
"question": "Which database would you like to use?",
"header": "Database",
"options": [
{ "label": "PostgreSQL", "description": "Robust relational database" },
{ "label": "MongoDB", "description": "Flexible document store" },
{ "label": "SQLite", "description": "Lightweight, file-based" }
]
}
]
}{
"questions": [
{
"question": "Which architecture style do you prefer?",
"header": "Architecture",
"options": [
{
"label": "Microservices",
"description": "Distributed services with independent deployment",
"preview": "## Microservices\n\n- Independent deploy\n- Service mesh\n- Event-driven"
},
{
"label": "Modular Monolith",
"description": "Single deployable with module boundaries"
},
{
"label": "Serverless",
"description": "Functions-as-a-service, auto-scaling"
}
]
},
{
"question": "What is the priority for this project?",
"header": "Priority",
"multiSelect": false,
"options": [
{ "label": "Speed", "description": "Ship fast, iterate later" },
{ "label": "Quality", "description": "Production-grade from the start" },
{ "label": "Cost-efficient", "description": "Minimize infrastructure and dev time" }
]
}
],
"timeout": 120
}When the user answers, the agent receives:
User answered the following questions:
Q1: Which architecture style do you prefer?
Selected: Microservices
Q2: What is the priority for this project?
Selected: Speed
Notes: We need MVP in 2 weeks
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
questions |
array | β | β | 1β4 structured question objects |
timeout |
integer | β | 300 | Seconds to wait for user response |
| Field | Type | Required | Description |
|---|---|---|---|
question |
string | β | Question text (must end with ?) |
header |
string | β | Tab label, max 16 characters |
options |
array | β | 2β4 option objects |
multiSelect |
boolean | β | Allow multiple selections (default: false) |
| Field | Type | Required | Description |
|---|---|---|---|
label |
string | β | Display text (max 60 chars) |
description |
string | β | Brief explanation |
preview |
string | β | Markdown shown in a preview pane |
These labels are auto-provided and cannot be used:
Otherβ Always shown with a free-text inputType something.Chat about thisNext β
Check if there are pending questions for a context.
Parameters:
context_id(string, required) β The chat context ID
Response (pending):
{
"ok": true,
"pending": true,
"session_id": "uuid",
"questions": [...],
"created_at": 1234567890.123
}Response (no pending):
{
"ok": true,
"pending": false
}Submit answers or cancel a pending session.
Parameters:
session_id(string, required) β The session ID fromget_pendinganswers(array, required unless cancelled) β Array of answer objectscancelled(boolean) β Set totrueto decline answering
Answer Object:
{
"question_index": 0,
"selected": ["Option Label"],
"other_text": "",
"notes": ""
}Response:
{ "ok": true }ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Agent Zero Framework β
β β
β βββββββββββββββββββ ββββββββββββββββββββββββββββββ β
β β Agent (LLM) ββββββββββΆβ tools/ask_user_question β β
β β β β - Validates questions β β
β β βββββββββββ - Creates session β β
β β β β - Waits on asyncio.Event β β
β βββββββββββββββββββ ββββββββββββ¬ββββββββββββββββββ β
β β β
β β create_session() β
β βΌ β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β helpers/state.py (In-Memory) ββ
β β _pending: Dict[context_id β PendingSession] ββ
β β - create_session() - submit_answer() ββ
β β - get_pending() - cancel_session() ββ
β β - cleanup_old_sessions() (10min TTL) ββ
β ββββββββββββ¬βββββββββββββββββββββββββββββββ²ββββββββββββββββββ
β β β β
β β API β event.set() β
β βΌ β β
β ββββββββββββββββββββββββ βββββββββββββββ΄ββββββββββββββββ β
β β api/get_pending.py β β api/submit_answer.py β β
β β GET/POST β β POST β β
β ββββββββββββ¬ββββββββββββ βββββββββββββββββββββββββββββββ β
β β β
βββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββ
β HTTP
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β WebUI (Browser) β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β webui/ask-store.js (Alpine.js Store) ββ
β β - Polls /get_pending every 2s ββ
β β - Manages modal state, answers, navigation ββ
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β extensions/webui/page-head/ask-question-setup.html ββ
β β - Injected into page <head> ββ
β β - Contains CSS + Alpine.js modal template ββ
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- In-Memory: Sessions are stored in a Python dictionary, keyed by
context_id - TTL: Sessions expire after 10 minutes (
_MAX_AGE = 600) - Supersession: New questions for the same context cancel previous pending ones
- Asyncio.Event: The tool blocks on an
asyncio.Eventthat is set when the user submits or cancels
- The Alpine.js store polls
get_pendingevery 2 seconds - When a pending session is detected, the modal appears automatically
- After submission, the modal closes and polling resumes
ask_user_question/
βββ plugin.yaml # Plugin metadata
βββ api/
β βββ __init__.py
β βββ get_pending.py # GET/POST endpoint for pending questions
β βββ submit_answer.py # POST endpoint for submitting answers
βββ helpers/
β βββ __init__.py
β βββ state.py # In-memory session state management
βββ tools/
β βββ __init__.py
β βββ ask_user_question.py # Agent tool (async, blocking wait)
βββ prompts/
β βββ agent.system.tool.ask_user_question.md # Agent prompt instructions
βββ extensions/
β βββ webui/
β βββ page-head/
β βββ ask-question-setup.html # CSS + Alpine modal template
βββ webui/
βββ ask-store.js # Alpine.js reactive store
- Symlink or copy the plugin into your Agent Zero
usr/plugins/directory - Restart Agent Zero
- In a chat, the agent can invoke the tool when it needs clarification
- Styles: Edit the
<style>block inextensions/webui/page-head/ask-question-setup.html - Modal Template: Edit the Alpine.js
x-datatemplate in the same file - Store Logic: Edit
webui/ask-store.jsfor polling, state, and API calls - All CSS variables reference the Agent Zero theme (
--color-primary,--color-background-elevated, etc.)
This project is licensed under the MIT License.
Copyright Β© 2025 Agent Zero Community