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
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)]
)
Types de champs
| Type de champ | Description | Propriétés |
|---|---|---|
TextField | Entrée de texte | description, pattern (regex facultative), prefilled_value, error_message |
NumberField | Entrée numérique | description, minimum, maximum, exclusive_minimum, exclusive_maximum, prefilled_value |
DateTimeField | Sélecteur de date et d’heure | description, prefilled_value (chaîne de date et heure ISO 8601) |
DateField | Sélecteur de date | description, prefilled_value (chaîne de date ISO 8601) |
SingleChoice | Menu déroulant/sélecteur | options (liste de tuples ou de chaînes), description, prefilled_value |
MultiChoice | Sélection multiple | options (liste de tuples ou de chaînes), description, prefilled_value |
FileField | Téléchargement de fichier | description, 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
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.

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
)
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
)
DateField
from datetime import date
scheduled_at: date = DateField(
description="Schedule date",
prefilled_value="2025-01-15", # ISO 8601 date string
)
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",
)

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",
)

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
)

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 :
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
filename | str | Oui | Nom Original du fichier |
url | str | Oui | URL signée pour télécharger le fichier |
content_type | str | Oui | Type 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
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 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}!")]
)
| Propriété | Type | Description |
|---|---|---|
options | list[tuple[str, str]] ou list[str] | Liste d’options sous forme de tuples (value, label) ou de chaînes simples |
description | str | Description 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 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.")]
)
| Propriété | Type | Description |
|---|---|---|
description | str | Description affichée au-dessus des boutons |
accept_label | str | Libellé du bouton d’acceptation |
decline_label | str | Libellé 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