본문으로 건너뛰기

인간 참여 루프(HITL)

일부 Workflow는 계속하기 전에 사람의 입력을 위해 일시 ​​중지해야 합니다. Workflow가 다음과 같은 경우suspended, 일시 중지된 이유와 진행하는 데 필요한 사항을 설명하는 메시지를 반환할 수 있습니다. 그러면 Workflow는 다음 중 하나를 수행할 수 있습니다.재개하다또는보석수신된 입력을 기반으로 합니다. 이 접근 방식은 수동 승인, 거부, 제한적 결정 또는 사람의 감독이 필요한 모든 단계에 적합합니다.

사람의 입력을 위한 Workflow 일시 중지
사람의 입력을 위한 Workflow 일시 중지에 대한 직접 링크

Human-in-the-loop 입력은 다음과 같이 작동합니다.pausing a workflow using suspend(). 핵심적인 차이점은 사람의 입력이 필요할 때 suspend() 를 사용자에게 반환하여 계속 진행하는 방법에 관한 맥락이나 안내를 제공할 수 있다는 것입니다.

Pausing a workflow with 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()

사용자 피드백 제공
사용자 피드백 제공에 대한 직접 링크

Workflow가 일시 중지되면 다음에서 반환된 페이로드에 액세스할 수 있습니다.suspend() 하려면 일시 중단된 단계를 식별하고 해당 단계의 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)
}

예제 출력
예제 출력에 대한 직접 링크

단계에서 반환된 데이터에는 이유가 포함될 수 있으며 사용자가 Workflow를 재개하는 데 필요한 것이 무엇인지 이해하는 데 도움이 될 수 있습니다.

{
reason: 'Confirm to send email.'
}

사람의 입력으로 Workflow 재개
사람의 입력으로 Workflow 재개에 대한 직접 링크

마찬가지로restarting a workflow, use resume() with resumeData 하여 사람의 입력을 받은 후 Workflow를 계속합니다. Workflow는 일시 중지된 단계부터 재개됩니다.

Restarting a workflow with 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 },
})
}

인간의 거부 처리bail()
handling-human-rejection-with-bail에 대한 직접 링크

사용bail() 하여 오류를 발생시키지 않고 특정 단계에서 Workflow 실행을 중지합니다. 이는 사람이 작업을 명시적으로 거부할 때 유용할 수 있습니다. Workflow는 success status, and any logic after the call to bail() is skipped.

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}`,
}
},
})

다중 회전 인간 입력
다중 회전 인간 입력에 대한 직접 링크

여러 단계에서 입력이 필요한 Workflow의 경우 일시 중단 패턴은 동일하게 유지됩니다. 각 단계는resumeSchema, and suspendSchema 와 함께 완료되며, 일반적으로 사용자 피드백을 제공하는 데 사용할 수 있는 사유가 포함됩니다.

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();

각 단계는 별도의 호출을 통해 순서대로 재개되어야 합니다.resume() 를 일시 중단된 각 단계에 사용합니다. 이 접근 방식은 각 단계에서 일관된 UI 피드백과 명확한 입력 처리를 통해 다단계 승인을 관리하는 데 도움이 됩니다.

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