Documentation Index
Fetch the complete documentation index at: https://ai.aidalinfo.fr/llms.txt
Use this file to discover all available pages before exploring further.
Human steps pause a workflow until a manual decision or additional information is provided. Declare them with createHuman and reuse them across workflows.
import { createHuman, createStep, createWorkflow } from "@ai_kit/core";
import { z } from "zod";
const fetchDraftApplication = createStep<
{ applicantId: string },
{ applicantId: string; amount: number; history: string[] }
>({
id: "fetch-draft-application",
description: "Load a case awaiting validation",
inputSchema: z.object({ applicantId: z.string().min(1) }),
handler: async ({ input }) => ({
applicantId: input.applicantId,
amount: 4200,
history: ["2019: opened", "2023: updated"],
}),
});
export const manualReview = createHuman<
{ applicantId: string; amount: number; history: string[] },
{ decision: string; comment: string }
>({
id: "manual-review",
output: ({ current }) => ({
case: {
id: current.applicantId,
amount: current.amount,
history: current.history,
},
}),
input: ({ ask }) =>
ask.form({
title: "Manual case validation",
fields: [
ask.text({ id: "comment", label: "Comment" }),
ask.select({
id: "decision",
label: "Decision",
options: ["approve", "reject"],
}),
],
}),
});
const finalizeDecision = createStep<
{ decision: string; comment: string },
{ status: string }
>({
id: "finalize-decision",
handler: ({ input, context }) => ({
status: `${context.initialInput.applicantId}:${input.decision}:${input.comment}`,
}),
});
export const onboardingWorkflow = createWorkflow({ id: "onboarding" })
.then(fetchDraftApplication)
.human(manualReview)
.then(finalizeDecision)
.commit();
- The output of
fetchDraftApplication is injected into manualReview (output.current) and delivered to the client through pendingHuman.output.
- The human response becomes the input of
finalizeDecision, which can also access the original data via context.initialInput.
Execution cycle
const run = onboardingWorkflow.createRun();
const { stream, final } = await run.stream({ inputData: { applicantId: "app-123" } });
for await (const event of stream) {
if (event.type === "step:human:requested") {
const { form, output } = event.data;
ui.displayReviewForm(form, output.case);
}
}
const pending = await final;
if (pending.status === "waiting_human") {
await run.resumeWithHumanInput({
stepId: "manual-review",
data: { decision: "approve", comment: "Looks good" },
});
}
run.resumeWithHumanInput validates the response using the human step schema and resumes the workflow until completion.
Best practices
- Use stable identifiers for human steps—workflow resumes rely on them.
- Send rich metadata in
output to simplify UI rendering (summaries, links, stats).
- Record
step:human:* events in your observability platform to track turnaround times.