Wait for approval (webhook gate)
Source: src/workflows/shared/actions/wait-for-approval.ts. Composes Convex rows (waiting run step + approvalsrecord) with the Workflow SDK's createWebhook({ respondWith: "manual" }) and the Flowman human decision resume route.
Helpers
- waitForApprovalDecision — opens the waiting step, creates the approval row, binds the Workflow SDK webhook, waits for the reviewer, closes Convex bookkeeping, and returns only approved decisions.
- approvalChangedBody — reads an edited email preview body from an approved decision when the reviewer changed the draft.
- Low-level helpers remain exported for custom gates that need to control the Workflow SDK webhook directly.
Decision JSON
The modal / API proxies to /api/approvals/[slug]/resolve, which POSTs a body shaped as {decision: "approved" | "rejected", changes?, reason? }. Rejections throw from waitForApprovalDecision with the reviewer reason or the configured fallback message.
Usage
typescript
import {
approvalChangedBody,
waitForApprovalDecision,
} from "@/workflows/shared/actions";
const decision = await waitForApprovalDecision({
record,
stepKey: "legalReview",
title: "Sign-off",
preview: {
type: "email",
from: "bot@corp",
to: "you@corp",
subject: "Please review",
body: draftedEmail,
},
rejectionMessage: "Workflow failed: approval was rejected.",
});
const reviewedBody = approvalChangedBody(decision) || draftedEmail;