Formulaires et confirmations
Les workflows conversationnels peuvent demander à l'utilisateur une entrée structurée : champs typés avec validation, choix unique ou multiple, téléchargement de fichiers, confirmations accepter/refuser. Utilisez FormInput pour les formulaires complets et ConfirmationInput / AcceptDeclineConfirmation pour les invites en un clic.
Entrées de formulaire structurées
Pour les workflows nécessitant une entrée structurée avec champs typés, validation et rendu d'UI 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 | Champ texte | description, pattern (regex optionnelle), prefilled_value |
NumberField | Champ numérique | description, minimum, maximum, exclusive_minimum, exclusive_maximum, prefilled_value |
DateTimeField | Sélecteur de date/heure | description, prefilled_value (chaîne de date/heure au format ISO 8601) |
DateField | Sélecteur de date | description, prefilled_value (chaîne de date au format ISO 8601) |
SingleChoice | Liste déroulante/unique choix | options (liste de tuples ou chaînes), description, prefilled_value |
MultiChoice | Choix multiples | options (liste de tuples ou chaînes), description, prefilled_value |
FileField | Téléchargement de fichier | description, multiple (par défaut False), include_metadata (par défaut False) |
Tous les types de champs (sauf FileField) prennent en charge un paramètre optionnel prefilled_value. Il s'agit uniquement d'une indication UI : il préremplit le champ de formulaire mais ne le rend pas optionnel. La valeur doit toujours être explicitement soumise par l'utilisateur. Les valeurs préremplies non valides (hors limites, motif non correspondant, 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
)
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) pointant vers les fichiers téléchargés par l'utilisateur. Avec include_metadata=True, il reçoit des objets FileWithMetadataValue à la place :
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
filename | str | Oui | Nom de fichier original |
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 a besoin d’un accès à long terme aux fichiers, il est responsable de leur stockage ailleurs.
Entrées de confirmation
Pour les workflows nécessitant une confirmation simple par choix unique avec validation directe, utilisez ConfirmationInput ou AcceptDeclineConfirmation. Ces aides créent un formulaire à un seul champ où la sélection d’une option soumet immédiatement le formulaire.
ConfirmationInput
ConfirmationInput propose une liste d’options devant être affichées 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 (valeur, libellé) ou de chaînes simples |
description | str | Description affichée au-dessus des options |
L’objet retourné contient une propriété choice avec 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 des réponses rapides :
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 Accepter |
decline_label | str | Libellé du bouton Refuser |
Utilisez la fonction auxiliaire 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