Workflows
Declare and run multi-step workflows using FormDefinition and the blocks runtime.
Workflows are multi-step processes you declare in code. The runtime lives in @stndrds/blocks, powered by RilayKit.
Form definitions
A workflow is expressed as a FormDefinition — a typed object with slots and steps. Slots define which records the workflow acts on (the "inputs"); steps define the sequence of form screens the user fills in.
// @noverify
import type { FormDefinition } from "@stndrds/schema";
const onboardingWorkflow: FormDefinition = {
name: "contact-onboarding",
label: "Contact Onboarding",
status: "published",
version: 1,
slots: [
{
id: "contact",
objectName: "contact",
label: "Contact",
mode: "create",
},
],
steps: [
{
id: "basic-info",
label: "Basic info",
rows: [],
},
{
id: "assign",
label: "Assign owner",
rows: [],
},
],
};There is no workflow() builder — workflows are plain FormDefinition objects registered via the form registry. Each FormSlot has a mode: "create", "select", "optional", or "create_if_not_empty".
Trigger
You can start a workflow in three ways:
- UI button — call
useCreateFormSubmissionwith the form ID and optional slot values to pre-fill records. - Programmatic submission — call the same hook server-side or from an automation.
- Schedule — attach a schedule to the form definition and the runtime fires it automatically.
// @noverify
import { useCreateFormSubmission } from "@stndrds/react";
function StartOnboarding({ formId }: { formId: string }) {
const submit = useCreateFormSubmission();
return (
<button
onClick={() =>
submit.mutate({
formId,
slotValues: { contact: { firstName: "Ada" } },
})
}
>
Start onboarding
</button>
);
}Observe
Submissions are first-class objects. Use useFormSubmissionsByRecord to fetch all submissions linked to a specific record, or query across submissions with the dedicated hooks.
// @noverify
import { useFormSubmissionsByRecord } from "@stndrds/react";
function SubmissionHistory({ recordId }: { recordId: string }) {
const { data } = useFormSubmissionsByRecord(recordId);
return <ul>{data?.map((s) => <li key={s.id}>{s.status}</li>)}</ul>;
}Submission status flows through: draft → submitted → processing → completed (or failed).
See Workflows concept for the mental model behind slots, steps, and instances.