name: build-wizard-flow description: Creates multi-step wizard flows with validation and state persistence using @WizardHandler and WizardStep. Use when building forms, questionnaires, or multi-step conversations that need typed state and validation.
Build Wizard Flow
Quick Start
Annotate an object/class with @WizardHandler. Define nested steps extending WizardStep. KSP generates the WizardActivity; no manual Activity class needed.
import eu.vendeli.tgbot.types.component.MessageUpdate
@WizardHandler(trigger = ["/start"])
object RegistrationWizard {
object NameStep : WizardStep(isInitial = true) {
override suspend fun onEntry(ctx: WizardContext) {
message("What's your name?").send(ctx.user, ctx.bot)
}
override suspend fun validate(ctx: WizardContext): Transition {
val text = (ctx.update as? MessageUpdate)?.message?.text ?: return Transition.Retry()
return if (text.isNotBlank()) Transition.Next else Transition.Retry("Invalid name")
}
override suspend fun store(ctx: WizardContext): String? =
(ctx.update as? MessageUpdate)?.message?.text
}
object AgeStep : WizardStep() {
override suspend fun onEntry(ctx: WizardContext) {
message("How old are you?").send(ctx.user, ctx.bot)
}
override suspend fun validate(ctx: WizardContext): Transition {
val age = (ctx.update as? MessageUpdate)?.message?.text?.toIntOrNull()
return if (age != null && age in 1..150) Transition.Next else Transition.Retry()
}
override suspend fun store(ctx: WizardContext): Int? =
(ctx.update as? MessageUpdate)?.message?.text?.toIntOrNull()
}
}
WizardStep Lifecycle
- onEntry(ctx) — Called when entering the step. Send prompts, set keyboards.
- validate(ctx) — Return
Transitionbased on input. - store(ctx) — Return value to persist (or null). Type must match a state manager.
- onRetry(ctx, reason) — Called when validation fails (optional).
Transitions
| Transition | Effect |
|---|---|
Transition.Next |
Move to next step in sequence |
Transition.JumpTo(Step::class) |
Jump to specific step |
Transition.Retry() or Transition.Retry("reason") |
Stay on step, call onRetry |
Transition.Finish |
End wizard |
State Managers
Default: MapStringStateManager, MapIntStateManager, MapLongStateManager. KSP matches store() return type to the manager.
Override per step:
@WizardHandler.StateManager(CustomStateManager::class)
object CustomStep : WizardStep { ... }
WizardContext
ctx.user,ctx.update,ctx.botctx.getState(Step::class),ctx.setState(Step::class, value),ctx.delState(Step::class)— type-safe accessors generated by KSP for each step
Trigger and Scope
trigger = ["/start", "/register"]— commands that start the wizardscope = [UpdateType.MESSAGE]— default; useUpdateType.CALLBACK_QUERYfor button-triggered wizards
Related Skills
- add-wizard-handler — Configure @WizardHandler (trigger, scope, state managers)
- add-wizard-step — Implement WizardStep (onEntry, validate, store, transitions)