Formulaires et confirmations

Les workflows conversationnels peuvent demander à l’utilisateur une entrée structurée : champs typés avec validation, options à choix unique ou multiple, téléchargements de fichiers, confirmations accepter/refuser. Utilisez FormInput pour les formulaires complets et ConfirmationInput / AcceptDeclineConfirmation pour les prompts en un clic.

Entrées de formulaire structurées

Entrées de formulaire structurées

Pour les workflows qui nécessitent une entrée de formulaire structurée avec des champs typés, une validation et un rendu d’interface personnalisé, utilisez FormInput plutôt que ChatInput :

from datetime import date, datetime

import mistralai.workflows as workflows
import mistralai.workflows.plugins.mistralai as workflows_mistralai
from mistralai.workflows.conversational import (
    FormInput,
    TextField,
    NumberField,
    DateField,
    DateTimeField,
    SingleChoice,
)


class ExpenseForm(FormInput):
    """Structured form for expense submission."""

    description: str = TextField(description="Expense description")
    amount: float = NumberField(
        description="Amount in USD",
        minimum=0,
        maximum=10000,
    )
    category: str = SingleChoice(
        options=[
            ("travel", "Travel"),
            ("equipment", "Equipment"),
            ("software", "Software"),
        ],
        description="Expense category",
    )
    expense_date: date = DateField(description="Date of expense")
    due_date: datetime = DateTimeField(description="Reimbursement due date")
    receipt_id: str = TextField(
        description="Receipt ID",
        pattern=r"^RCP-\d{6}$",
    )


@workflows.workflow.define(
    name="expense-submission-workflow",
    workflow_display_name="Expense Submission",
    workflow_description="Submit an expense with structured form",
)
class ExpenseSubmissionWorkflow(workflows.InteractiveWorkflow):
    @workflows.workflow.entrypoint
    async def run(self) -> workflows_mistralai.ChatAssistantWorkflowOutput:
        expense = await self.wait_for_input(
            ExpenseForm,
            label="Submit Expense",
        )

        result = f"""Expense submitted:
- Description: {expense.description}
- Amount: ${expense.amount:.2f}
- Category: {expense.category}
- Date: {expense.expense_date.isoformat()}
- Due date: {expense.due_date.isoformat()}
- Receipt: {expense.receipt_id}"""

        return workflows_mistralai.ChatAssistantWorkflowOutput(
            content=[workflows_mistralai.TextOutput(text=result)]
        )
Une entrée de formulaire structurée affichée dans Vibe Work.
Une entrée de formulaire structurée affichée dans Vibe Work.
Types de champs

Types de champs

Type de champDescriptionPropriétés
TextFieldEntrée de textedescription, pattern (regex facultative), prefilled_value, error_message
NumberFieldEntrée numériquedescription, minimum, maximum, exclusive_minimum, exclusive_maximum, prefilled_value
DateTimeFieldSélecteur de date et d’heuredescription, prefilled_value (chaîne de date et heure ISO 8601)
DateFieldSélecteur de datedescription, prefilled_value (chaîne de date ISO 8601)
SingleChoiceMenu déroulant/sélecteuroptions (liste de tuples ou de chaînes), description, prefilled_value
MultiChoiceSélection multipleoptions (liste de tuples ou de chaînes), description, prefilled_value
FileFieldTéléchargement de fichierdescription, multiple (False par défaut), include_metadata (False par défaut)

Tous les types de champs, sauf FileField, prennent en charge un paramètre facultatif prefilled_value. Il s’agit uniquement d’une indication d’interface : elle préremplit le champ du formulaire, mais ne le rend pas facultatif. La valeur doit toujours être envoyée explicitement par l’utilisateur. Les valeurs préremplies non valides (hors limites, qui ne correspondent pas au motif, option inconnue) sont ignorées silencieusement.

TextField

TextField

name: str = TextField(description="Your name", prefilled_value="John Doe")
email: str = TextField(
    description="Email address",
    pattern=r"^[\w.-]+@[\w.-]+\.\w+$",  # Optional regex validation
)
booking: str = TextField(
    description="Booking reference",
    pattern=r"^00\d{8}$",
    error_message="Booking reference must be 00 followed by 8 digits.",
)

Par défaut, une valeur qui ne respecte pas pattern est rejetée avec un message généré qui affiche la regex à l’utilisateur, par exemple ^00\d{8}$. Définissez error_message pour le remplacer par un libellé exploitable par l’utilisateur. Le message sert uniquement à l’affichage : il ne modifie pas ce que le champ accepte. Contrairement au message généré, il s’affiche tel qu’il est écrit, sans adaptation à la langue de l’utilisateur.

error_message remplace aussi la regex affichée dans l’indication sous le champ.

Un champ de texte affiché dans Vibe Work.
Champ de texte dans Vibe Work.
NumberField

NumberField

amount: float = NumberField(
    description="Amount",
    minimum=0,           # Inclusive minimum
    maximum=10000,       # Inclusive maximum
    prefilled_value=100,   # Pre-filled value
)
price: float = NumberField(
    description="Price",
    exclusive_minimum=0,   # Must be greater than 0
    exclusive_maximum=100, # Must be less than 100
)
Un champ numérique affiché dans Vibe Work.
Champ numérique dans Vibe Work.
DateTimeField

DateTimeField

from datetime import datetime

scheduled_at: datetime = DateTimeField(
    description="Schedule date and time",
    prefilled_value="2025-01-15T10:00:00Z",  # ISO 8601 datetime string
)
Un champ de sélection de date et d’heure affiché dans Vibe Work.
Champ date-heure dans Vibe Work.
DateField

DateField

from datetime import date

scheduled_at: date = DateField(
    description="Schedule date",
    prefilled_value="2025-01-15",  # ISO 8601 date string
)
Un champ de sélection de date affiché dans Vibe Work.
Champ date dans Vibe Work.
SingleChoice

SingleChoice

# With labels (value, display_label)
priority: str = SingleChoice(
    options=[
        ("low", "Low Priority"),
        ("medium", "Medium Priority"),
        ("high", "High Priority"),
    ],
    description="Select priority",
    prefilled_value="medium",  # Pre-selected option
)

# Simple string options (value = label)
status: str = SingleChoice(
    options=["pending", "approved", "rejected"],
    description="Status",
)
Un menu déroulant à choix unique affiché dans Vibe Work, avec des options de priorité.
Un menu déroulant à choix unique affiché dans Vibe Work, avec des options de statut.
Champ à choix unique dans Vibe Work.
MultiChoice

MultiChoice

# With labels (value, display_label)
tags: list[str] = MultiChoice(
    options=[
        ("frontend", "Frontend"),
        ("backend", "Backend"),
        ("infra", "Infrastructure"),
    ],
    description="Select applicable tags",
    prefilled_value=["frontend"],  # Pre-selected options
)

# Simple string options (value = label)
colors: list[str] = MultiChoice(
    options=["red", "green", "blue"],
    description="Pick colors",
)
Un champ à choix multiple affiché dans Vibe Work, avec des options de tags.
Un champ à choix multiple affiché dans Vibe Work, avec des options de couleur.
Champ à choix multiple dans Vibe Work.
FileField

FileField

from mistralai.workflows.conversational import FileField, FileWithMetadataValue

# Single file upload (plain URL)
document: str = FileField(description="Upload a document")

# Multiple file uploads (plain URLs)
attachments: list[str] = FileField(description="Upload files", multiple=True)

# Single file upload with metadata
document: FileWithMetadataValue = FileField(description="Upload a document", include_metadata=True)

# Multiple file uploads with metadata
attachments: list[FileWithMetadataValue] = FileField(
    description="Upload files", multiple=True, include_metadata=True
)
Un champ de téléchargement de fichier unique affiché dans Vibe Work.
Un champ de téléchargement de plusieurs fichiers affiché dans Vibe Work, avec les fichiers joints.
Champ de téléchargement de fichier dans Vibe Work.

Par défaut, le workflow reçoit des URL (chaînes) qui pointent vers les fichiers téléchargés par l’utilisateur. Avec include_metadata=True, il reçoit plutôt des objets FileWithMetadataValue :

ChampTypeObligatoireDescription
filenamestrOuiNom Original du fichier
urlstrOuiURL signée pour télécharger le fichier
content_typestrOuiType MIME du fichier

Ces URL peuvent expirer. Si votre workflow doit accéder aux fichiers sur le long terme, il doit donc les stocker ailleurs.

Entrées de confirmation

Entrées de confirmation

Pour les workflows qui nécessitent une confirmation simple à choix unique avec soumission directe, utilisez ConfirmationInput ou AcceptDeclineConfirmation. Ces helpers créent un formulaire à champ unique où la sélection d’une option soumet immédiatement le formulaire.

ConfirmationInput

ConfirmationInput

ConfirmationInput fournit une liste d’options à afficher sous forme de boutons. La sélection d’une option doit soumettre immédiatement le formulaire :

import mistralai.workflows as workflows
import mistralai.workflows.plugins.mistralai as workflows_mistralai


@workflows.workflow.define(
    name="type-selection-workflow",
    workflow_display_name="Type Selection",
    workflow_description="Select your favorite type",
)
class TypeSelectionWorkflow(workflows.InteractiveWorkflow):
    @workflows.workflow.entrypoint
    async def run(self) -> workflows_mistralai.ChatAssistantWorkflowOutput:
        await workflows_mistralai.send_assistant_message("Let's find out your type preference!")

        selection = await self.wait_for_input(
            workflows_mistralai.ConfirmationInput(
                options=[
                    ("fire", "Fire"),
                    ("water", "Water"),
                    ("grass", "Grass"),
                    ("electric", "Electric"),
                ],
                description="What is your favorite type?",
            )
        )

        selected_type = selection.choice  # Returns the value, e.g., "fire"
        return workflows_mistralai.ChatAssistantWorkflowOutput(
            content=[workflows_mistralai.TextOutput(text=f"You selected {selected_type}!")]
        )
Une entrée de confirmation affichée dans Vibe Work, avec un bouton pour chaque option.
Entrée de confirmation dans Vibe Work.
PropriétéTypeDescription
optionslist[tuple[str, str]] ou list[str]Liste d’options sous forme de tuples (value, label) ou de chaînes simples
descriptionstrDescription affichée au-dessus des options

L’objet renvoyé possède une propriété choice qui contient la valeur de l’option sélectionnée.

AcceptDeclineConfirmation

AcceptDeclineConfirmation

AcceptDeclineConfirmation est une confirmation spécialisée avec deux options : accepter et refuser. Les clients peuvent l’afficher comme une interface de validation standard avec des raccourcis clavier pour répondre rapidement :

import mistralai.workflows as workflows
import mistralai.workflows.plugins.mistralai as workflows_mistralai


@workflows.workflow.define(
    name="approval-workflow",
    workflow_display_name="Approval",
    workflow_description="Confirm an action",
)
class ApprovalWorkflow(workflows.InteractiveWorkflow):
    @workflows.workflow.entrypoint
    async def run(self) -> workflows_mistralai.ChatAssistantWorkflowOutput:
        confirmation = await self.wait_for_input(
            workflows_mistralai.AcceptDeclineConfirmation(
                description="Do you want to proceed with this action?",
                accept_label="Yes, proceed",
                decline_label="Cancel",
            )
        )

        if workflows_mistralai.is_accepted(confirmation):
            return workflows_mistralai.ChatAssistantWorkflowOutput(
                content=[workflows_mistralai.TextOutput(text="Action confirmed!")]
            )
        else:
            return workflows_mistralai.ChatAssistantWorkflowOutput(
                content=[workflows_mistralai.TextOutput(text="Action cancelled.")]
            )
Une confirmation accepter/refuser affichée dans Vibe Work, avec deux boutons pour accepter et refuser.
Confirmation accepter/refuser dans Vibe Work.
PropriétéTypeDescription
descriptionstrDescription affichée au-dessus des boutons
accept_labelstrLibellé du bouton d’acceptation
decline_labelstrLibellé du bouton de refus

Utilisez la fonction helper is_accepted() pour vérifier si l’utilisateur a accepté ou refusé :

if workflows_mistralai.is_accepted(confirmation):
    # User accepted
    pass
else:
    # User declined
    pass