Skip to main content
FlowDrop exposes the same set of lifecycle callbacks through two surfaces:
  • The <App> component takes them as flat on* propsonBeforeSave, onAfterSave, onSaveError, onApiError, onWorkflowLoad, onBeforeSwap, onAfterSwap.
  • The mount options bag (mountFlowDropApp, mountWorkflowEditor) takes the grouped eventHandlers object, which additionally wires onWorkflowChange, onDirtyStateChange, and onBeforeUnmount.
const app = await mountFlowDropApp(container, {
  eventHandlers: {
    /* handlers below */
  }
});
Every handler is optional.

Workflow lifecycle

HandlerSignatureWhen it fires
onWorkflowChange(workflow: Workflow, changeType: WorkflowChangeType) => voidAny modification to nodes, edges, config, or metadata
onWorkflowLoad(workflow: Workflow) => voidAfter a workflow is loaded and initialized
onDirtyStateChange(isDirty: boolean) => voidWhen the workflow transitions between saved and unsaved states

WorkflowChangeType values

ValueTrigger
node_addNode added to canvas
node_removeNode deleted
node_moveNode dragged to new position
node_configNode configuration values changed
edge_addConnection drawn between nodes
edge_removeConnection deleted
metadataWorkflow metadata changed
nameWorkflow name edited
descriptionWorkflow description edited

Save lifecycle

HandlerSignatureWhen it fires
onBeforeSave(workflow: Workflow) => Promise<boolean | void>Before save. Return false to cancel.
onAfterSave(workflow: Workflow) => Promise<void>After successful save
onSaveError(error: Error, workflow: Workflow) => Promise<void>When save fails

Node swap

HandlerSignatureWhen it fires
onBeforeSwap(context: SwapEventContext) => boolean | void | Promise<boolean | void>Before a node swap. Return false to cancel.
onAfterSwap(result: SwapResult, oldNode: WorkflowNode, newNodeId: string) => voidAfter a node swap is applied

Error & cleanup

HandlerSignatureWhen it fires
onApiError(error: Error, operation: string) => boolean | voidAny API request failure. Return true to suppress default toast. operation values: "save", "load", "fetchNodes", "fetchCategories", etc.
onBeforeUnmount(workflow: Workflow, isDirty: boolean) => voidBefore FlowDrop is destroyed/unmounted

Agent Spec execution

HandlerSignatureWhen it fires
onAgentSpecExecutionStarted(executionId: string) => voidExecution begins
onAgentSpecExecutionCompleted(executionId: string, results: Record<string, unknown>) => voidExecution succeeds
onAgentSpecExecutionFailed(executionId: string, error: Error) => voidExecution fails
onAgentSpecNodeStatusUpdate(nodeId: string, status: NodeExecutionInfo) => voidNode status changes during execution

Complete interface

interface FlowDropEventHandlers {
  onWorkflowChange?: (workflow: Workflow, changeType: WorkflowChangeType) => void;
  onDirtyStateChange?: (isDirty: boolean) => void;
  onBeforeSave?: (workflow: Workflow) => Promise<boolean | void>;
  onAfterSave?: (workflow: Workflow) => Promise<void>;
  onSaveError?: (error: Error, workflow: Workflow) => Promise<void>;
  onWorkflowLoad?: (workflow: Workflow) => void;
  onBeforeUnmount?: (workflow: Workflow, isDirty: boolean) => void;
  onApiError?: (error: Error, operation: string) => boolean | void;
  onBeforeSwap?: (context: SwapEventContext) => boolean | void | Promise<boolean | void>;
  onAfterSwap?: (result: SwapResult, oldNode: WorkflowNode, newNodeId: string) => void;
  onAgentSpecExecutionStarted?: (executionId: string) => void;
  onAgentSpecExecutionCompleted?: (executionId: string, results: Record<string, unknown>) => void;
  onAgentSpecExecutionFailed?: (executionId: string, error: Error) => void;
  onAgentSpecNodeStatusUpdate?: (nodeId: string, status: NodeExecutionInfo) => void;
}
For usage examples and patterns, see the Event System guide.