Flow Studio
Capturing Widget Interactions
How user interactions within a widget are captured and translated into workflow resume signals — the interaction event model and data flow.
Interaction Event Model
Widgets communicate with the platform through interaction callbacks. When a user performs a meaningful action (clicks a button, submits a selection, drags a card), the widget calls callbacks.onInteraction(eventName, data).
// Inside a widget bundle:
function mount(container: HTMLElement, props: Record<string, unknown>, callbacks: WidgetCallbacks) {
const approveBtn = container.querySelector('#approve-btn');
approveBtn?.addEventListener('click', () => {
const selectedItems = getSelectedItems();
const totalApproved = selectedItems.reduce((sum, item) => sum + item.amount, 0);
// Fire interaction — resumes the workflow
callbacks.onInteraction('approve', {
approvedItems: selectedItems,
rejectedItems: getRejectedItems(),
totalApproved,
notes: getNotesFieldValue()
});
});
}
Resume API Call
The WidgetRenderer's onInteraction handler calls the HIL resume endpoint:
POST /api/executions/{executionId}/resume
{
"action": "interaction",
"interactionEvent": "approve",
"interactionData": {
"approvedItems": [{ "id": "item-1", "amount": 450.00 }],
"rejectedItems": [],
"totalApproved": 450.00,
"notes": "All receipts verified"
}
}
Node Output from Interaction
{
"approvedItems": [{ "id": "item-1", "amount": 450.00 }],
"rejectedItems": [],
"totalApproved": 450.00,
"notes": "All receipts verified",
"_interactionEvent": "approve",
"_interactedBy": "user-alice",
"_interactedAt": "2026-05-25T14:30:00Z"
}
Port Routing by Interaction Event
Map different interaction events to different ports using the interactionPortMap config:
{
"interactionPortMap": {
"approve": "approved",
"reject": "rejected",
"requestAmendment": "amendment"
}
}
Design principle: Widgets should only fire interactions when a user intentionally takes an action — not on every UI state change. Each interaction call resumes the workflow. Multiple accidental firings would cause unexpected behavior.