Aller au contenu principal

Intervention humaine (HITL)

Certains Workflows doivent attendre une intervention humaine avant de continuer. Lorsqu'un Workflow est suspendu, il peut renvoyer un message expliquant la raison de la suspension et les informations nécessaires pour poursuivre. Selon la saisie reçue, le Workflow peut ensuite reprendre ou s'arrêter. Cette approche convient aux approbations et rejets manuels, aux décisions soumises à validation ou à toute étape nécessitant une supervision humaine.

Suspendre un Workflow pour une intervention humaine
Lien direct vers Suspendre un Workflow pour une intervention humaine

La saisie avec intervention humaine fonctionne presque comme la suspension d'un Workflow au moyen de suspend(). La principale différence tient au fait que, lorsqu'une intervention humaine est requise, vous pouvez renvoyer suspend() avec une charge utile qui fournit à l'utilisateur le contexte ou les indications nécessaires pour continuer.

Suspension d'un Workflow avec suspend()

src/mastra/workflows/test-workflow.ts
import { createWorkflow, createStep } from '@mastra/core/workflows'
import { z } from 'zod'

const step1 = createStep({
id: 'step-1',
inputSchema: z.object({
userEmail: z.string(),
}),
outputSchema: z.object({
output: z.string(),
}),
resumeSchema: z.object({
approved: z.boolean(),
}),
suspendSchema: z.object({
reason: z.string(),
}),
execute: async ({ inputData, resumeData, suspend }) => {
const { userEmail } = inputData
const { approved } = resumeData ?? {}

if (!approved) {
return await suspend({
reason: 'Human approval required.',
})
}

return {
output: `Email sent to ${userEmail}`,
}
},
})

export const testWorkflow = createWorkflow({
id: 'test-workflow',
inputSchema: z.object({
userEmail: z.string(),
}),
outputSchema: z.object({
output: z.string(),
}),
})
.then(step1)
.commit()

Fournir un retour à l'utilisateur
Lien direct vers Fournir un retour à l'utilisateur

Lorsqu'un Workflow est suspendu, vous pouvez accéder à la charge utile renvoyée par suspend() en identifiant l'étape suspendue puis en lisant son suspendPayload.

src/test-workflow.ts
const workflow = mastra.getWorkflow('testWorkflow')
const run = await workflow.createRun()

const result = await run.start({
inputData: {
userEmail: 'alex@example.com',
},
})

if (result.status === 'suspended') {
const suspendStep = result.suspended[0]
const suspendedPayload = result.steps[suspendStep[0]].suspendPayload

console.log(suspendedPayload)
}

Exemple de sortie
Lien direct vers Exemple de sortie

Les données renvoyées par l'étape peuvent inclure un motif qui aide l'utilisateur à comprendre ce qui est nécessaire pour reprendre le Workflow.

{
reason: 'Confirm to send email.'
}

Reprendre un Workflow avec une saisie humaine
Lien direct vers Reprendre un Workflow avec une saisie humaine

Comme pour la reprise d'un Workflow, utilisez resume() avec resumeData pour poursuivre un Workflow après avoir reçu une saisie humaine. Le Workflow reprend à l'étape où il a été suspendu.

Reprise d'un Workflow avec resume()

const workflow = mastra.getWorkflow('testWorkflow')
const run = await workflow.createRun()

await run.start({
inputData: {
userEmail: 'alex@example.com',
},
})

const handleResume = async () => {
const result = await run.resume({
step: 'step-1',
resumeData: { approved: true },
})
}

Gérer un refus humain avec bail()
Lien direct vers handling-human-rejection-with-bail

Utilisez bail() pour arrêter l'exécution du Workflow à une étape sans déclencher d'erreur. Cette méthode est utile lorsqu'une personne refuse explicitement une action. Le Workflow se termine avec l'état success et toute logique placée après l'appel à bail() est ignorée.

const step1 = createStep({
execute: async ({ inputData, resumeData, suspend, bail }) => {
const { userEmail } = inputData
const { approved } = resumeData ?? {}

if (approved === false) {
return bail({
reason: 'User rejected the request.',
})
}

if (!approved) {
return await suspend({
reason: 'Human approval required.',
})
}

return {
message: `Email sent to ${userEmail}`,
}
},
})

Intervention humaine en plusieurs tours
Lien direct vers Intervention humaine en plusieurs tours

Pour les Workflows qui nécessitent une saisie à plusieurs étapes, le modèle de suspension reste identique. Chaque étape définit un resumeSchema ainsi qu'un suspendSchema, généralement assorti d'un motif qui peut servir à fournir un retour à l'utilisateur.

src/mastra/workflows/test-workflow.ts
const step1 = createStep({...});

const step2 = createStep({
id: "step-2",
inputSchema: z.object({
message: z.string()
}),
outputSchema: z.object({
output: z.string()
}),
resumeSchema: z.object({
approved: z.boolean()
}),
suspendSchema: z.object({
reason: z.string()
}),
execute: async ({ inputData, resumeData, suspend }) => {
const { message } = inputData;
const { approved } = resumeData ?? {};

if (!approved) {
return await suspend({
reason: "Human approval required."
});
}

return {
output: `${message} - Deleted`
};
}
});

export const testWorkflow = createWorkflow({
id: "test-workflow",
inputSchema: z.object({
userEmail: z.string()
}),
outputSchema: z.object({
output: z.string()
})
})
.then(step1)
.then(step2)
.commit();

Chaque étape doit être reprise dans l'ordre au moyen d'un appel distinct à resume() pour chaque étape suspendue. Cette approche facilite la gestion des approbations en plusieurs étapes, avec un retour cohérent dans l'interface utilisateur et un traitement clair des saisies à chaque stade.

const handleResume = async () => {
const result = await run.resume({
step: 'step-1',
resumeData: { approved: true },
})
}

const handleDelete = async () => {
const result = await run.resume({
step: 'step-2',
resumeData: { approved: true },
})
}