Human-in-the-Loop with USER_INPUT
Some processes require human approval, review, or sign-off. A USER_INPUT task suspends the running workflow, emits a Notification Service event, and holds the run in PAUSED state until a permitted user submits their input.
The Workflow#
The Weather_Alert_Human_Approval workflow fetches and analyses weather information and then pauses to request user approval.
fetch_weather (SCRIPT_EXECUTION) → analyze_weather (SCRIPT_EXECUTION → severity) → request_approval (USER_INPUT) ← workflow PAUSES here → act_on_decision (SCRIPT_EXECUTION) ← reads the human's answerThe USER_INPUT Task#
Here's the configuration for the USER_INPUT task in the Weather_Alert_Human_Approval workflow. It specifies the notification type as well as the requried _userInput needed to continue.
{ _type: "USER_INPUT", _name: "request_approval", _sequenceno: 3, _inputParams: { _sendNotification: true, _notificationId: "weather_alert_approval", _userInputPermissions: [ { _userType: "user", _id: approverUserId } ], _userInput: { approve: { type: "string", enum: ["yes", "no"] }, note: { type: "string" } } }}Key fields:
_userInputdeclares the shape of the answer expected from the human: here anapproveenum and a free-textnote._userInputPermissionslists who may provide the reqruied input. You can provide multiple individual users and user groups to the_userInputPermissionsto allow users to provide the required input to the workflow. User groups are specified by configuring{ _userType: 'usergroup', _id: <_id of the user group> }while individual users are specifed by{ _userType: 'user', _id:<_id of a user> }. Your user _id was when you deployed the template package for the course. You can see it by right clickingWeather_Alert_Human_Approvaland selecting 'View Definition JSON'._sendNotification/_notificationIdcause the pause to emit a Notification Service event so a UI or subscriber can react. These live at the top of_inputParams, as siblings of_userInput.
Because the run may wait for a person, the definition sets a generous _timeoutSeconds: 3600.
Reading the Human's Input Downstream#
USER_INPUT output is addressed differently from a script output — the submitted fields live under {{task name}}._output._userInput.<field>:
{ _type: "SCRIPT_EXECUTION", _name: "act_on_decision", _sequenceno: 4, _inputParams: { _userType: "weather_workflow_demo_static", _scriptName: "actOnApprovalDecision", approve: "${request_approval._output._userInput.approve}", note: "${request_approval._output._userInput.note}", severity: "${analyze_weather._output.scriptOutput}" }}actOnApprovalDecision then dispatches on the answer. Sending the alert when approve === "yes" and suppressing it otherwise.
Running the Workflow#
- Run
runWeatherWorkflowwith input copying and pasting this value into the input field:
{ "workflowUserType": "weather_workflow_transformer_static" }
- Monitor with
getLatestWorkflowRunByUserType.
The run advances to request_approval and then pauses (PAUSED).
Submit the human decision by running
updateWeatherUserInputRunwith the following input:{ "approve": "yes", "note": "Approved via the course" }With no
workflowRunId, theupdateWeatherUserInputRunscript targets the latest run of the user-input workflow. It resolves the paused run and itsUSER_INPUTtask, then calls the SDK:IafWorkflowSvc.updateUserInput(runId, userInputId, { _userInput: { approve, note } }, ctx)The run resumes,
act_on_decisionruns, and the workflow completes. Confirm withgetLatestWorkflowRunByUserTypeorpollWorkflowUntilComplete.
Inspecting the Pause / Notification#
Two helpers exist to understand the paused state and its notification context:
resolveWeatherUserInputRun(internal helper) locates the run, itsUSER_INPUTtask, the runtimeuserInputId, and the_notificationId.sendWeatherUserInputNotificationsurfaces the notification context: it builds an event payload shaped like the liveworkflowsvc.UserInputevent and lists the current user's Notification Service history and any matching triggers.
There is no API to re-fire the UserInput event after the fact — the workflow emits workflowsvc.UserInput once, when the task starts (because _sendNotification: true). To actually reach an approver by email or webhook, a Notification Service trigger must be configured to filter on event = UserInput and notificationId = weather_alert_approval. This is the bridge between a paused workflow and the outside world; the helper lets you verify that bridge is in place.
Human Input is an API Call#
Notice that completing a human task is an ordinary authenticated API call (updateUserInput). In a real application that call is made by a UI action, a chatbot, or another service. Anything that can present the decision to a permitted user and post their answer. The workflow does not care what the front end is; it only cares that a permitted user submitted an answer of the declared shape.