The Question Types Reference

The type key for each question in your config.yml tells VIBE what kind of input to show the user. Here is a reference for all available types.

Common Attributes

Most question types share a set of common configuration keys.

Key Type Required? Description
label string Yes The user-facing text for the question.
type string Yes The type of question widget to display (e.g., text, number).
required boolean No Controls required validation, completion gating, and required UI markers. Defaults to true (fields with a default still count as optional for completion).
default any No A default value to pre-fill the answer with.
help string No Longer, more detailed helper text that appears with the question. Can contain Markdown.
hint string No A short hint that often appears as placeholder text inside the input field.
# Example showing all common attributes
questions:
  project_code:
    label: Project Code
    type: text
    required: false
    default: PROJ-2024
    help: The internal code for tracking this project, like `PROJ-2024-FIN`. Can be found in the project charter.
    hint: e.g., PROJ-2024-FIN

Note: Required validation only kicks in after a field is submitted/answered (to avoid blocking every auto-submit), and newly relevant fields are only auto-validated when required: true.


options Format

The options key is used by radio, select, and multichoice to define the available choices. It accepts two formats that can be freely mixed within the same list.

Simple string format — the string is used as both the stored value and the display label:

options:
  - Standard
  - Premium
  - Enterprise

Object format — for separate values and labels, help text, or followups:

options:
  - value: standard
    label: Standard Plan
  - value: premium
    label: Premium Plan
    help: Includes priority support and SLA guarantees.
    followups:
      - premium_contact

Key Type Required? Description
value string Yes The stored value (what your template sees). Required when using object format.
label string No The display text shown to the user. Defaults to value if omitted.
help string No Explanatory text shown with the option. Supported by radio and multichoice only — causes a validation error on select.
followups list No List of question IDs to show nested under this option when selected. See Follow-up Questions below.

You can mix both formats in one list:

options:
  - Simple Option                  # string → value and label are both "Simple Option"
  - value: detailed
    label: Detailed Option
    help: This one has extra metadata.


Follow-up Questions

Follow-up questions let you nest related questions inside a parent widget, so they appear indented directly under the option that triggers them. This is a UI placement hint — it controls where the question renders, not when it's relevant (that's still determined by your template's {% if %} logic via the probing mechanism).

Supported types: multichoice, radio/select, and bool.

Per-option followups (multichoice, radio, select)

Add a followups list to any option object. When the user selects that option, the listed questions appear nested underneath it.

questions:
  delivery_method:
    type: radio
    label: Preferred delivery method
    options:
      - value: courier
        label: Courier delivery
        followups:
          - courier_company
      - value: pickup
        label: Self pickup
      - value: digital
        label: Digital delivery
        followups:
          - download_format

  courier_company:
    type: text
    label: Preferred courier company

  download_format:
    type: select
    label: Download format
    options:
      - PDF
      - DOCX

Question-level followups (bool)

For bool, followups are a mapping on the question itself, keyed by yes and no:

questions:
  needs_insurance:
    type: bool
    label: Does the shipment require insurance?
    followups:
      yes:
        - insurance_amount
      no:
        - waiver_reason

  insurance_amount:
    type: amount
    label: Insurance coverage amount
    currencies:
      - USD

  waiver_reason:
    type: text
    label: Reason for declining insurance

Note: Followup questions must be defined as regular questions in the same questions block. They are rendered inside the parent widget instead of as standalone top-level questions. Followups can be nested — a followup question can itself have followups.


text / textarea

For freeform text input. Use textarea for longer, multi-line text.

questions:
  project_name:
    type: text
    label: Project Name

  project_description:
    type: textarea
    label: Project Description
    help: Provide a brief summary of the project goals.
    required: false

assisted

An enhanced textarea that includes an AI-powered assist button to help the user draft text. It is ideal for fields requiring creative or descriptive content.

Extension note: assisted is part of the Assistant extension and requires LLM endpoints to be configured.

Key Type Required? Description
type string Yes Must be set to assisted.
label string Yes The user-facing text for the question.
prompt string Yes A Jinja2 template string that will be rendered and sent to the LLM as its instruction.
model string No The ID of the LLM endpoint to use, as defined by the administrator in the system config.yml. If omitted, the system default is used.

Example:

questions:
  procurement_object:
    type: text
    label: What do you want to buy?

  procurement_description:
    type: assisted
    label: Describe the thing you want to buy
    model: claude-opus
    prompt: Create a one-paragraph description of {{ procurement_object }} suitable for a procurement process.

User Interaction:

  1. The user can type in the text area manually.
  2. Clicking the assist button sends the rendered prompt to the specified LLM.
  3. The AI's response is streamed directly into the text area.
  4. If the button is clicked again, the user is prompted for refinement instructions, and the AI generates a new version based on the original prompt, the current text, and the new instructions.

Template Access: In your .md or .docx template, an assisted variable behaves exactly like a standard text variable. You access its final content with {{ procurement_description }}.

number

For numeric input. You can specify min and max values for validation.

questions:
  contract_duration:
    type: number
    label: Contract Duration (months)
    min: 1
    max: 60
    help: Enter the length of the contract in full months.

amount

For monetary values, combining a numeric input with a currency.

Fixed Currency Example: If you provide only one currency, it will be displayed as a static symbol or code next to the number input.

questions:
  project_budget:
    type: amount
    label: Project Budget
    min: 0
    currencies:
      - USD
    currency_position: left

Selectable Currency Example: If you provide multiple currencies, a dropdown menu will appear for the user to select from.

questions:
  transaction_fee:
    type: amount
    label: Transaction Fee
    required: false
    currencies:
      - USD
      - EUR
      - GBP

amount Specific Options:

Key Type Description
currencies list A list of allowed currency codes (e.g., ["USD", "EUR"]). If only one is provided, the currency is fixed.
min number The minimum allowed numeric value.
max number The maximum allowed numeric value.
currency_position string left (default) or right. Where to display a fixed currency symbol.
currency_symbol string Manually override the currency symbol (e.g., "$"). By default, it's looked up from a standard map.

Template Access: An amount variable is automatically formatted for printing. You can also access its parts.

The total budget is {{ project_budget }}.

Value: {{ project_budget.value }}
Currency: {{ project_budget.currency }}

bool

For a simple "Yes" or "No" choice, rendered as radio buttons. Supports question-level followups keyed by yes and no.

questions:
  include_nda:
    type: bool
    label: Does this project require an NDA?
    default: true
    required: false

tristate

For a three-way choice: "Yes", "No", or "Don't know", rendered as radio buttons. Use this when you need to distinguish between "No" and "uncertain/not applicable/don't know".

questions:
  is_international:
    type: tristate
    label: Is this an international transaction?
    help: Select "Don't know" if you're unsure or if this doesn't apply.

Customizing the third option label:

questions:
  requires_legal_review:
    type: tristate
    label: Does this require legal review?
    none_label: Not applicable

  has_data_privacy_concerns:
    type: tristate
    label: Are there data privacy concerns?
    none_label: Maybe
    required: true

tristate Specific Options:

Key Type Description
none_label string Label for the third option (default: "Don't know"). Use values like "Not applicable", "Maybe", "Uncertain", etc.
default boolean or null Default selection: true for Yes, false for No, null for the third option, or omit to leave unselected.

Template Access:

A tristate variable has three possible values: true, false, or none (Python None). All three are valid answers that satisfy required: true.

{% if is_international is true %}
This is an international transaction.
{% elif is_international is false %}
This is a domestic transaction.
{% elif is_international is none %}
The international status is unknown.
{% endif %}

Important: Always use the is operator with true, false, or none when checking tristate values. Other comparison operators are not supported and will cause validation errors.

When to use tristate vs bool:

  • Use bool when you need a definitive yes/no answer and uncertainty should block progress
  • Use tristate when "don't know" or "not applicable" is a valid, meaningful answer that allows the document to proceed

date

For collecting a date from a calendar picker. Dates are in YYYY-MM-DD format.

effective_date:
  type: date
  label: Agreement Effective Date
  min_date: 2020-01-01

radio / select

For a list of choices where the user can only choose one option. Supports per-option followups.

contract_type:
  type: radio
  label: Contract Type
  options:
    - value: premium
      label: Premium Support
      help: Includes 24/7 phone support.
    - value: standard
      label: Standard Support
      help: Email support with a 48-hour response time.

Use radio for a set of radio buttons (all options always visible). Use select for a dropdown menu (the help attribute cannot be used with select).

multichoice

For a list of checkboxes where the user can select multiple options. Supports per-option followups.

service_scope:
  type: multichoice
  label: Services Included
  required: false
  options:
    - Discovery & Strategy
    - UI/UX Design
    - Backend Development
    - Ongoing Support

structured

For collecting complex, nested data structures based on definitions. Structured questions create grouped fields with dot notation form names.

Basic structured question using a definition:

questions:
  primary_contact:
    label: Primary Contact Person
    type: structured
    definition: person_definition
    help: Main person responsible for this project
definitions:
  person_definition:
    first_name:
      label: First name
      type: text
      help: Enter the person's first (or given) name
    last_name:
      label: Last name
      type: text
      help: Enter the person's last name (surname)
    email:
      label: Email Address
      type: email
      required: false

Template access with dot notation:

**Contact:** {{ primary_contact.last_name }}, {{ primary_contact.first_name }}
**Email:** {{ primary_contact.email }}

Form field naming: Structured fields use dot notation (primary_contact.full_name, billing_address.street) to avoid namespace collisions.

period

For collecting time periods in four modes: duration (quantity + unit), until (end date), indefinite (no end), or event (event-based). Period questions create sophisticated time-based inputs with validation, date arithmetic, and template access patterns.

All Modes Available (Default Behavior): By default, all four modes are available to users unless restricted via the modes property.

questions:
  contract_duration:
    label: Contract Duration
    type: period
    default_mode: duration
    default_unit: months
    min_quantity: 1
    max_quantity: 60
    help: How long should this contract last?

Restricting Available Modes: Use the modes property to limit which modes users can choose from.

questions:
  project_deadline:
    label: Project Deadline
    type: period
    modes:
      - until
    min_date: 2024-01-01
    max_date: 2030-12-31
    help: When must the project be completed by?

Multiple Modes with Constraints: Allow specific modes and configure each one appropriately.

questions:
  service_term:
    label: Service Term
    type: period
    modes:
      - duration
      - indefinite
    duration_units:
      - weeks
      - months
      - years
    default_mode: duration
    default_unit: months
    min_quantity: 1
    max_quantity: 36
    required: false
    help: Choose a fixed duration or indefinite service term

Event Mode Configuration: For periods that end when a specific event occurs.

questions:
  project_phase:
    label: Project Phase Duration
    type: period
    modes:
      - duration
      - event
    default_mode: event
    duration_units:
      - days
      - weeks
    allowed_events:
      - milestone completion
      - budget approval
      - client signoff
    required: false
    help: When does this phase end?

Period Configuration Options:

Key Type Description
modes array List of allowed modes: ["duration", "until", "indefinite", "event"]. Defaults to all four modes.
default_mode string Which mode to pre-select. Must be one of the allowed modes. Defaults to "duration" if available.
duration_units array List of allowed units for duration mode: ["days", "weeks", "months", "years"]. Defaults to all units.
default_unit string Which unit to pre-select for duration mode. Must be one of the allowed duration_units. Defaults to "months".
min_quantity number Minimum allowed quantity for duration mode (default: 1).
max_quantity number Maximum allowed quantity for duration mode (optional).
min_date string Earliest allowed date for until mode in YYYY-MM-DD format (optional).
max_date string Latest allowed date for until mode in YYYY-MM-DD format (optional).
allowed_events array List of allowed event names for event mode (optional).

Template Usage: Periods are accessed as structured objects with mode-specific properties and convenience methods.

{% if contract_duration %}
**Contract Duration:** {{ contract_duration.display }}

{% if contract_duration.is_duration %}
  Duration: {{ contract_duration.quantity }} {{ contract_duration.unit }}
{% elif contract_duration.is_until %}
  End Date: {{ contract_duration.date }}
{% elif contract_duration.is_indefinite %}
  No fixed end date
{% elif contract_duration.is_event %}
  Ends when: {{ contract_duration.event }}
{% endif %}
{% endif %}

Date Arithmetic: Duration periods can be added to dates for calculations.

{% if start_date and duration_period and duration_period.is_duration %}
**Start Date:** {{ start_date }}
**Duration:** {{ duration_period }}
**End Date:** {{ start_date + duration_period }}
{% endif %}

Available Properties:

  • period.mode - One of "duration", "until", "indefinite", or "event"
  • period.display - Enhanced formatted string (e.g., "6 months", "until August 15, 2025", "indefinitely")

Convenience Properties:

  • period.is_duration - Boolean: true if mode is "duration"
  • period.is_until - Boolean: true if mode is "until"
  • period.is_indefinite - Boolean: true if mode is "indefinite"
  • period.is_event - Boolean: true if mode is "event"

Mode-Specific Properties:

  • For duration mode:
  • period.quantity - The numeric duration (e.g., 12)
  • period.unit - The time unit (e.g., "months")
  • For until mode:
  • period.date - The end date in YYYY-MM-DD format (e.g., "2025-12-31")
  • For event mode:
  • period.event - The event name (e.g., "project completion")

Built-in String Formatting: Periods automatically format to readable text when used directly in templates:

  • Duration mode: "12 months", "1 year", "3 weeks"
  • Until mode: "until 2025-12-31" or "until August 15, 2025"
  • Indefinite mode: "indefinitely"
  • Event mode: "until project completion"

Validation Rules:

  • Duration mode: Quantity must be a positive number within specified min/max bounds
  • Until mode: Date must be valid YYYY-MM-DD format within specified date range
  • Event mode: Event name must be provided; if allowed_events is specified, must be from that list
  • Indefinite mode: No additional validation required
  • Required validation: If required=true, user must provide a complete period value

Common Patterns:

# Flexible period with all modes available (default behavior)
project_timeline:
  label: Project Timeline
  type: period
  default_mode: duration
  default_unit: weeks
  min_quantity: 1
  max_quantity: 104
  help: Choose duration, end date, indefinite, or event-based

# Date-only period for deadlines
submission_deadline:
  label: Submission Deadline
  type: period
  modes:
    - until
  min_date: 2024-06-01
  max_date: 2024-12-31
  help: Final date for submission

# Duration-only period for contracts
service_period:
  label: Service Period
  type: period
  modes:
    - duration
  duration_units:
    - months
    - years
  default_unit: months
  min_quantity: 3
  max_quantity: 36
  help: Length of service commitment

# Event-based period with constrained options
warranty_period:
  label: Warranty Period
  type: period
  modes:
    - event
  allowed_events:
    - first failure
    - one year elapsed
    - contract termination
  help: When does the warranty coverage end?

# Duration or indefinite for ongoing arrangements
maintenance_agreement:
  label: Maintenance Agreement Duration
  type: period
  modes:
    - duration
    - indefinite
  duration_units:
    - months
    - years
  default_mode: indefinite
  help: Duration of ongoing maintenance coverage

list

For collecting multiple items of the same structure. Lists can use either inline field definitions or definition references.

List using a definition:

questions:
  team_members:
    label: Team Members
    type: list
    item_label: Team Member
    uses: person_definition
    min_items: 1
    max_items: 10
  project_tasks:
    label: Project Tasks
    type: list
    item_label: Task
    uses: task_definition
    required: false

definitions:
  # person_definition as above
  task_definition:
    name:
      label: Task Name
      type: text
    due_date:
      label: Due Date
      type: date
      required: false
    priority:
      label: Priority
      type: select
      options:
        - Low
        - Medium
        - High

Template access:

# Team Members
{% for member in team_members %}
- **{{ member.last_name}}**, {{ member.first_name }} ({{ member.email }})
{% endfor %}

# Project Tasks
{% for task in project_tasks %}
- **{{ task.name }}** - Due: {{ task.due_date }} (Priority: {{ task.priority }})
{% endfor %}

List options:

  • min_items: Minimum number of items required
  • max_items: Maximum number of items allowed
  • item_label: Singular label for each item (e.g., "Team Member")
  • uses: Reference to definition name for item structure

For more details on structured questions and lists, see the "Reusable Data with definitions" guide.