Questions Form
by @edonadei
Present multiple clarifying questions as an interactive Telegram form using inline buttons. Use when the agent needs to ask the user 2 or more clarifying questions before proceeding with a task, and wants to present them all at once in a structured form layout with selectable options and an "Other" free-text escape hatch. Triggers when: gathering multi-faceted requirements, onboarding flows, preference collection, or any scenario requiring structured multi-question input from the user via Telegr
clawhub install questions-formπ About This Skill
name: questions-form description: > Present multiple clarifying questions as an interactive Telegram form using inline buttons. Use when the agent needs to ask the user 2 or more clarifying questions before proceeding with a task, and wants to present them all at once in a structured form layout with selectable options and an "Other" free-text escape hatch. Triggers when: gathering multi-faceted requirements, onboarding flows, preference collection, or any scenario requiring structured multi-question input from the user via Telegram.
Questions Form
Present multiple clarifying questions as a Telegram inline-button form. All questions appear at once; the user answers in any order, then submits.
When to Use
Do not use this pattern for a single yes/no question β just send one message with buttons for that.
Form Protocol
Step 1: Compose the Form
Define each question internally as an object:
{ id: "type", text: "What type of project?", options: ["Web App", "Mobile", "API"] }
{ id: "timeline", text: "What is your timeline?", options: ["This week", "This month", "No rush"] }
{ id: "budget", text: "Budget range?", options: ["< $1k", "$1k-5k", "$5k-10k", "> $10k"] }
Initialize internal tracking state:
form_state = { type: null, timeline: null, budget: null }
awaiting_freetext = null
form_submitted = false
Step 2: Send the Header
Send a plain message (no buttons) as the form introduction:
{
"action": "send",
"channel": "telegram",
"message": "I have a few questions before we proceed.\nPlease answer each one by tapping a button, then tap Submit when done."
}
Step 3: Send Each Question
For each question, send a separate message with inline buttons. Put selectable options in rows of 2-3 buttons. Always put "Other" on its own last row.
The callback_data must follow this convention: form:
Example:
{
"action": "send",
"channel": "telegram",
"message": "1. What type of project is this?",
"buttons": [
[
{ "text": "Web App", "callback_data": "form:type:web" },
{ "text": "Mobile", "callback_data": "form:type:mobile" },
{ "text": "API", "callback_data": "form:type:api" }
],
[
{ "text": "Other (type your answer)", "callback_data": "form:type:other" }
]
]
}
{
"action": "send",
"channel": "telegram",
"message": "2. What is your timeline?",
"buttons": [
[
{ "text": "This week", "callback_data": "form:timeline:this_week" },
{ "text": "This month", "callback_data": "form:timeline:this_month" },
{ "text": "No rush", "callback_data": "form:timeline:no_rush" }
],
[
{ "text": "Other (type your answer)", "callback_data": "form:timeline:other" }
]
]
}
{
"action": "send",
"channel": "telegram",
"message": "3. Budget range?",
"buttons": [
[
{ "text": "< $1k", "callback_data": "form:budget:lt_1k" },
{ "text": "$1k-5k", "callback_data": "form:budget:1k_5k" }
],
[
{ "text": "$5k-10k", "callback_data": "form:budget:5k_10k" },
{ "text": "> $10k", "callback_data": "form:budget:gt_10k" }
],
[
{ "text": "Other (type your answer)", "callback_data": "form:budget:other" }
]
]
}
Step 4: Send the Submit Button
After all questions, send the submit/cancel message:
{
"action": "send",
"channel": "telegram",
"message": "When you've answered all questions above, tap Submit.",
"buttons": [
[{ "text": "\u2713 Submit All Answers", "callback_data": "form:submit" }],
[{ "text": "\u2717 Cancel", "callback_data": "form:cancel" }]
]
}
Step 5: Handle Callbacks
When you receive a callback starting with form::
Regular option (form: where value is not other):
form_state[qid] = value"Got it -- : " "Other" option (form:):
"Type your answer for: " awaiting_freetext = qidform_state[qid] = "Got it -- : " awaiting_freetextSubmit (form:submit):
form_state for any null values"You still need to answer: "
form_submitted = true and proceed with the collected answersCancel (form:cancel):
form_state"Form cancelled. Let me know how you'd like to proceed."Step 6: Use the Answers
Once submitted, reference the collected answers as structured data and proceed:
Collected: { type: "mobile", timeline: "End of March", budget: "1k_5k" }
Now continue with the original task using these clarified requirements.
Changing Answers
Users can click a different button for any question at any time before submitting. Simply overwrite the previous value and acknowledge the change:
"Updated --
Callback Data Convention
form: prefixform:: form:Button Layout Rules
"Other (type your answer)""\u2713 Submit All Answers""\u2717 Cancel"Edge Cases and Advanced Patterns
See references/form-patterns.md for: