* draft
* Phase 1: Remove deprecated granular flow AI tools
Simplify AI chat flow mode to use only YAML-based editing:
- Remove all commented-out granular tools (add_step, remove_step, set_code, etc.)
- Clean up FlowAIChatHelpers interface to only essential methods
- Update system prompts to focus on YAML-only workflow
- Remove unused imports and type definitions
This is part of a larger refactoring to simplify the flow editing
experience to a single YAML editing tool with automatic diff visualization.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* use minified json
* use openflow in system prompt
* handle inputs
* cleaning
* cleaning
* diffmode in flowgraph
* remove acceptrejectmodule
* use new diff mode
* cleaning
* better props
* better logic
* cleaning
* accept reject logic
* use get set
* draft manager
* use diff manager
* draft
* Refactor flowDiffManager to be instance-based with auto-computation
- Remove singleton export, making it instantiable per FlowGraphV2
- Add afterFlow state tracking for auto-diff computation
- Add beforeInputSchema/afterInputSchema for schema change tracking
- Add $effect for reactive auto-computation when beforeFlow/afterFlow changes
- Add setAfterFlow() and setInputSchemas() methods
- Simplify accept/reject methods to just mark pending=false
- Add validation to throw error when accepting/rejecting without beforeFlow
- Update setSnapshot to accept undefined for clearing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Refactor FlowGraphV2 to own diffManager instance
- Import and create diffManager instance per FlowGraphV2
- Remove onAcceptModule and onRejectModule props
- Add validation $effect to error if both diffBeforeFlow and moduleActions provided
- Add $effect to sync props (diffBeforeFlow or moduleActions) to diffManager
- Add $effect to watch current flow changes and update afterFlow
- Replace computedDiff with diffManager.moduleActions
- Use raw modules instead of merged flow (diffManager handles merging)
- Expose getDiffManager() and setBeforeFlow() methods
- Pass diffManager to graph context instead of callbacks
- Remove $inspect for removed props
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update FlowModuleSchemaMap to use FlowGraphV2's diffManager
- Remove import of flowDiffManager singleton
- Update setBeforeFlow to call graph.setBeforeFlow()
- Update setModuleActions and getModuleActions to use graph.getDiffManager()
- Add getDiffManager() proxy method
- Simplify handleAcceptModule and handleRejectModule to use new API
- Handle editor state separately from diff operations
- Remove diffBeforeFlow, moduleActions, onAcceptModule, onRejectModule props passed to FlowGraphV2
- Remove onAcceptModule and onRejectModule from Props interface and destructured props
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update FlowAIChat to use flowModuleSchemaMap's diffManager
- Remove import of flowDiffManager singleton
- Update revertToSnapshot to use flowModuleSchemaMap.getDiffManager()
- Add null check for diffManager before using
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Verify FlowGraphDiffViewer compatibility with refactored architecture
FlowGraphDiffViewer already uses the correct prop patterns:
- Before graph: moduleActions prop (display-only mode)
- After graph: diffBeforeFlow prop (full diff mode with auto-computation)
Each FlowGraphV2 instance creates its own diffManager, making the side-by-side
view work correctly with independent diff state per graph.
No code changes required.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update graph components to use diffManager instead of callbacks
- Update graphBuilder.svelte.ts to pass diffManager instead of onAcceptModule/onRejectModule
- Update InputNode and ModuleN type definitions with diffManager
- Update ModuleNode.svelte to pass diffManager to MapItem
- Update MapItem.svelte to pass diffManager to FlowModuleSchemaItem
- Update FlowModuleSchemaItem.svelte to use diffManager directly for accept/reject
- Replace callback-based accept/reject with direct diffManager calls
- Only show accept/reject buttons when beforeFlow exists and action is pending
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix removed modules not showing in diff viewer
Problem: After refactoring, removed modules were no longer appearing in the
diff viewer because we changed effectiveModules from using the merged flow
(which includes removed modules) to using raw modules.
Solution:
- Add mergedFlow state to flowDiffManager to store timeline's merged flow
- Add markRemovedAsShadowed parameter support for side-by-side view
- Store timeline.mergedFlow in auto-computation $effect
- Add getter for mergedFlow and setMarkRemovedAsShadowed method
- Clear mergedFlow in clearSnapshot()
- Update FlowGraphV2 to set markRemovedAsShadowed in diffManager
- Update effectiveModules/FailureModule/PreprocessorModule to use mergedFlow
The merged flow contains all modules including removed ones, enabling:
- Unified view: Removed modules appear in red with "removed" badge
- Side-by-side view: Removed modules show as shadowed in After graph
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Simplify accept/reject logic by removing actions instead of toggling pending state
Previously, accepting or rejecting a module action would set pending to false but keep the action in the moduleActions map. This caused a bug where the $effect would overwrite moduleActions with fresh actions having pending: true, making accept/reject buttons reappear on previously handled modules.
Now, when a user accepts or rejects a module action, we remove it entirely from the moduleActions map. This is simpler and fixes the button reappearing issue.
Changes:
- acceptModule: Remove action from moduleActions instead of setting pending: false
- rejectModule: Remove action from moduleActions instead of setting pending: false
- checkAndClearSnapshot: Check if moduleActions is empty instead of checking pending states
- Fix typo: getModuleFromFrom → getModuleFromFlow
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* cleaning
* fix logic
* make diff drawer part of manager
* accept submodules
* fixes
* Phase 4: Add checkAndApplyChanges() helper to flowDiffManager
- Added new checkAndApplyChanges() function to apply mergedFlow to flowStore when all changes are decided
- This replaces the old checkAndClearSnapshot() behavior and ensures flowStore is updated atomically
- Handles both flow structure and input schema updates
* Phase 2: Simplify acceptModule() - only modify mergedFlow
- Remove flowStore mutations from acceptModule()
- For removed modules: just delete the shadowed (__prefix) version from mergedFlow
- For added/modified: no action needed (already correct in mergedFlow)
- Call checkAndApplyChanges() to apply changes when all decided
* Phase 3: Simplify rejectModule() - only modify mergedFlow
- Remove all flowStore mutations from rejectModule()
- For added modules: delete from mergedFlow
- For removed modules: replace shadowed (__) module with original from beforeFlow
- For modified modules: restore old version in mergedFlow
- For Input schema: revert afterInputSchema
- Call checkAndApplyChanges() to apply changes when all decided
* Phase 5: Verify acceptAll/rejectAll work with new architecture
- acceptAll() and rejectAll() already pass options correctly to acceptModule/rejectModule
- They will automatically benefit from checkAndApplyChanges()
- No changes needed for this phase
* Phase 6: Remove FlowGraphV2 reactive effect that updates afterFlow
- Removed the (lines 252-266) that continuously updated afterFlow
- This effect created reactive loops when flowStore changed
- afterFlow should only be set once when AI generates changes via setFlowYaml()
- The initial sync effect (lines 226-250) is kept for prop-driven diff mode
* Phase 7: Update FlowAIChat setFlowYaml to use diffManager
- Changed setFlowYaml() to use diffManager.setAfterFlow() instead of modifying flowStore
- flowStore remains unchanged during AI review phase
- Changes are staged in mergedFlow for user review
- Only applied to flowStore when all changes are accepted/rejected
- Added error handling for missing diffManager
* Fix linter warnings
- Remove unused FlowTimeline type import
- Fix ChangeTracker initialization with proper type parameter
- Keep deleteModuleFromFlow and checkAndClearSnapshot for potential future use
* Update plan document with implementation status
- Mark all phases as complete
- Add commit references
- Update file checklist
- Add implementation summary at top of document
* Add comprehensive implementation summary document
- Detailed overview of architecture changes
- Before/after comparisons for each file
- Complete testing scenarios checklist
- Troubleshooting guide
- Migration notes and backwards compatibility info
* Show pending modules in editor panel
- Pass diffManager from FlowModuleSchemaMap to FlowEditorPanel
- Add effectiveModules derived value that uses mergedFlow when in diff mode
- Update module iteration to use effectiveModules instead of flowStore
- Allows users to view added/modified modules during AI review
- Fixes issue where clicking on pending modules showed nothing
* Add implementation summary for show pending modules feature
* fix
* shorter system prompt
* Fix Input schema diff mode issues
- Add Accept/Reject buttons to Input node (previously only showed Diff button)
- Pass diffManager to FlowInput component
- Add effectiveSchema derived value that uses afterInputSchema when in diff mode
- Add effectiveDisabled to prevent editing Input when reviewing AI changes
- Update FlowInputViewer to show pending schema changes
- Fixes issue where Input schema changes couldn't be accepted/rejected
- Fixes issue where pending Input schema wasn't visible in the panel
* Disable delete and move buttons when in pending mode
- Add effectiveDeletable derived value that checks diffManager.hasPendingChanges
- Replace all instances of deletable with effectiveDeletable in template
- Prevents delete/move operations when AI changes are being reviewed
- Delete and move buttons are hidden when there are pending changes
- Buttons reappear once all changes are accepted or rejected
- Prevents conflicting operations during review phase
* no move or delte when reviewing
* use context
* inline script reduction
* use json
* rollback to direct modif
* fix merge
* cleaning
* fix reject removed
* add set step code tool
* better prompt
* add back relevant tools
* add back accept reject
* use edit mode for pending
* fix input
* remove unneeded effect
* cleaner + bug fix
* fix failure and preprocessor
* fix show diff for failure module
* fix accept reject on failre module
* no auto add module to context
* cleaning
* add back effect
* cleaning
* fix multiple setflowjson
* track effectivemoduleactions for graph rendering
* nit prompt
* styling
* rm md files
* rm flake copy
* cleaning
* fix z index
* fix revert
* only change before after
* use add remove modify tools
* input + failure + preproc tools
* parsing issues
* nit
* use raw schema for tools
* resolve ref for gemini
* fix schema
* show test on graph
* much cleaner logic
* ignore empty assets
* Remove debug console.log statements from production code
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Remove debug $inspect calls from FlowGraphV2
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add error logging to setFlowJson before re-throwing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Standardize null/undefined handling to prefer null
- Use .nullable().optional() instead of .nullish() in Zod schemas
- Simplify addModuleToFlow signature to use string | null
- Coerce undefined to null when extracting parsed args
- Simplify null checks to only check !== null
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Remove debug console.log from AI tool functions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Extract special module IDs to constants
Add SPECIAL_MODULE_IDS constant with INPUT, PREPROCESSOR, and FAILURE
to avoid magic strings throughout the flow AI chat code.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add cleanup for diffDrawer reference on unmount
Prevents potential memory leaks by clearing the diffDrawer reference
when the FlowGraphV2 component is destroyed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Use structuredClone instead of JSON.parse(JSON.stringify())
structuredClone is more efficient and type-safe for deep cloning objects.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Cache module lookups in reconstructMergedFlow
Move getAllModulesMap and getAllModuleIds calls outside the loop to avoid
redundant recomputation. Track merged IDs incrementally as modules are added.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Revert "Use structuredClone instead of JSON.parse(JSON.stringify())"
This reverts commit a62ba5b980.
* cleaning
* allow delete
* better openflow for ai agents + truncate system prompt
* handle ai agent tools
* fix set code for tool
* fix wrong cancel request called
* mark tool calls as canceled
* get lang instructions
* use streamiing args
* give db url to claude
* fix revert
* save and clear when leaving editor
* keep whitespace in user message
* uniformize colors
* fix diff button
* remove db from backend claude
* remove move module tool
* no failure and preprocessor
* fix error given to llm
* fix z index
* fix ts errors
* cleaning
* fix add module logic
* fix(copilot): add 'tools' to branchPath description for aiagent containers
The branchPath parameter description was missing 'tools' option for aiagent
containers and didn't mention branchall support.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(copilot): correct AI agent tool IDs and summaries documentation
Tool summaries CAN contain spaces (they're human-readable descriptions).
Only tool IDs must avoid spaces.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(copilot): remove reference to non-existent set_flow_json tool
The set_module_code tool description referenced set_flow_json which
doesn't exist as an exposed tool (it's an internal helper).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(copilot): clarify inspect_inline_script is read-only
The tool description incorrectly suggested it could modify code.
This tool only inspects - use set_module_code to modify.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(copilot): clarify afterId behavior for AI agent tools
Updated wording to clarify that afterId can be used but is optional
for AI agent tools since tool order doesn't affect execution.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(copilot): remove unused id param from get_instructions_for_code_generation
The id parameter was only used to check for preprocessor, which is no
longer needed. Simplified the tool to only require the language param.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs(copilot): add result format to search_scripts tool description
Helps AI understand what data format to expect from the tool.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs(copilot): add result format to resource_type tool description
Helps AI understand what data format to expect from the tool and
provides example resource type names.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* nit
* Add support for adding branches to branchall/branchone via add_module
Previously, add_module could only add modules inside existing branches.
Now, using insideId with branchPath=null will add a NEW branch to a
branchall or branchone container.
API:
- add_module({ insideId: "my_branchall", branchPath: null, value: { summary: "New Branch", skip_failure: false, modules: [] } })
- add_module({ insideId: "my_branchone", branchPath: null, value: { summary: "Condition", expr: "...", modules: [] } })
Changes:
- Extended addModuleToFlow to handle branchPath=null case
- Updated validation to allow branchPath=null when adding branches
- Updated tool descriptions and system prompt documentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* nit
* add remove branch tool
* check all ids for duplicates
* no dup
* nit
* cleaning
* fix dup ids
* split core.ts
* only mount diff drawer if useful
* remove wrong logic
* update exprs
* fix
* chore(flow): Add unit tests to flow diff manager (#7291)
* setup
* add basic tests for flowdiff
* add complex tests
* fix branch issue
* more complex tests
* add flow diff manager tests
* add utils
* better handling of moved case
* more tests for move case
* add buggy test case
* rm
* rework config
* cleaning
* fix config
* rm
* fix for reverting type change module
* all good
* rm
* add missing testmode
---------
Co-authored-by: Claude <noreply@anthropic.com>
968 lines
32 KiB
YAML
968 lines
32 KiB
YAML
openapi: "3.0.3"
|
|
|
|
info:
|
|
version: 1.589.3
|
|
title: OpenFlow Spec
|
|
contact:
|
|
name: Ruben Fiszel
|
|
email: ruben@windmill.dev
|
|
url: https://windmill.dev
|
|
|
|
license:
|
|
name: Apache 2.0
|
|
url: https://www.apache.org/licenses/LICENSE-2.0.html
|
|
|
|
paths: {}
|
|
|
|
externalDocs:
|
|
description: documentation portal
|
|
url: https://windmill.dev
|
|
|
|
components:
|
|
schemas:
|
|
OpenFlow:
|
|
type: object
|
|
description: Top-level flow definition containing metadata, configuration, and the flow structure
|
|
properties:
|
|
summary:
|
|
type: string
|
|
description: Short description of what this flow does
|
|
description:
|
|
type: string
|
|
description: Detailed documentation for this flow
|
|
value:
|
|
$ref: "#/components/schemas/FlowValue"
|
|
schema:
|
|
type: object
|
|
description: JSON Schema for flow inputs. Use this to define input parameters, their types, defaults, and validation. For resource inputs, set type to 'object' and format to 'resource-<type>' (e.g., 'resource-stripe')
|
|
required:
|
|
- summary
|
|
- value
|
|
|
|
FlowValue:
|
|
type: object
|
|
description: The flow structure containing modules and optional preprocessor/failure handlers
|
|
properties:
|
|
modules:
|
|
type: array
|
|
description: Array of steps that execute in sequence. Each step can be a script, subflow, loop, or branch
|
|
items:
|
|
$ref: "#/components/schemas/FlowModule"
|
|
failure_module:
|
|
description: Special module that executes when the flow fails. Receives error object with message, name, stack, and step_id. Must have id 'failure'. Only supports script/rawscript types
|
|
$ref: "#/components/schemas/FlowModule"
|
|
preprocessor_module:
|
|
description: Special module that runs before the first step on external triggers. Must have id 'preprocessor'. Only supports script/rawscript types. Cannot reference other step results
|
|
$ref: "#/components/schemas/FlowModule"
|
|
same_worker:
|
|
type: boolean
|
|
description: If true, all steps run on the same worker for better performance
|
|
concurrent_limit:
|
|
type: number
|
|
description: Maximum number of concurrent executions of this flow
|
|
concurrency_key:
|
|
type: string
|
|
description: Expression to group concurrent executions (e.g., by user ID)
|
|
concurrency_time_window_s:
|
|
type: number
|
|
description: Time window in seconds for concurrent_limit
|
|
debounce_delay_s:
|
|
type: number
|
|
description: Delay in seconds to debounce flow executions
|
|
debounce_key:
|
|
type: string
|
|
description: Expression to group debounced executions
|
|
skip_expr:
|
|
type: string
|
|
description: JavaScript expression to conditionally skip the entire flow
|
|
cache_ttl:
|
|
type: number
|
|
description: Cache duration in seconds for flow results
|
|
cache_ignore_s3_path:
|
|
type: boolean
|
|
flow_env:
|
|
type: object
|
|
description: Environment variables available to all steps
|
|
additionalProperties:
|
|
type: string
|
|
priority:
|
|
type: number
|
|
description: Execution priority (higher numbers run first)
|
|
early_return:
|
|
type: string
|
|
description: JavaScript expression to return early from the flow
|
|
chat_input_enabled:
|
|
type: boolean
|
|
description: Whether this flow accepts chat-style input
|
|
notes:
|
|
type: array
|
|
description: Sticky notes attached to the flow
|
|
items:
|
|
$ref: "#/components/schemas/FlowNote"
|
|
required:
|
|
- modules
|
|
|
|
Retry:
|
|
type: object
|
|
description: Retry configuration for failed module executions
|
|
properties:
|
|
constant:
|
|
type: object
|
|
description: Retry with constant delay between attempts
|
|
properties:
|
|
attempts:
|
|
type: integer
|
|
description: Number of retry attempts
|
|
seconds:
|
|
type: integer
|
|
description: Seconds to wait between retries
|
|
exponential:
|
|
type: object
|
|
description: Retry with exponential backoff (delay doubles each time)
|
|
properties:
|
|
attempts:
|
|
type: integer
|
|
description: Number of retry attempts
|
|
multiplier:
|
|
type: integer
|
|
description: Multiplier for exponential backoff
|
|
seconds:
|
|
type: integer
|
|
minimum: 1
|
|
description: Initial delay in seconds
|
|
random_factor:
|
|
type: integer
|
|
minimum: 0
|
|
maximum: 100
|
|
description: Random jitter percentage (0-100) to avoid thundering herd
|
|
retry_if:
|
|
$ref: "#/components/schemas/RetryIf"
|
|
|
|
FlowNote:
|
|
type: object
|
|
description: A sticky note attached to a flow for documentation and annotation
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: Unique identifier for the note
|
|
text:
|
|
type: string
|
|
description: Content of the note
|
|
position:
|
|
type: object
|
|
description: Position of the note in the flow editor
|
|
properties:
|
|
x:
|
|
type: number
|
|
description: X coordinate
|
|
y:
|
|
type: number
|
|
description: Y coordinate
|
|
required:
|
|
- x
|
|
- y
|
|
size:
|
|
type: object
|
|
description: Size of the note in the flow editor
|
|
properties:
|
|
width:
|
|
type: number
|
|
description: Width in pixels
|
|
height:
|
|
type: number
|
|
description: Height in pixels
|
|
required:
|
|
- width
|
|
- height
|
|
color:
|
|
type: string
|
|
description: Color of the note (e.g., "yellow", "#ffff00")
|
|
type:
|
|
type: string
|
|
enum: [free, group]
|
|
description: Type of note - 'free' for standalone notes, 'group' for notes that group other nodes
|
|
locked:
|
|
type: boolean
|
|
default: false
|
|
description: Whether the note is locked and cannot be edited or moved
|
|
contained_node_ids:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: For group notes, the IDs of nodes contained within this group
|
|
required:
|
|
- id
|
|
- text
|
|
- color
|
|
- type
|
|
|
|
RetryIf:
|
|
type: object
|
|
description: Conditional retry based on error or result
|
|
properties:
|
|
expr:
|
|
type: string
|
|
description: JavaScript expression that returns true to retry. Has access to 'result' and 'error' variables
|
|
required:
|
|
- expr
|
|
|
|
StopAfterIf:
|
|
type: object
|
|
description: Early termination condition for a module
|
|
properties:
|
|
skip_if_stopped:
|
|
type: boolean
|
|
description: If true, following steps are skipped when this condition triggers
|
|
expr:
|
|
type: string
|
|
description: JavaScript expression evaluated after the module runs. Can use 'result' (step's result) or 'flow_input'. Return true to stop
|
|
error_message:
|
|
type: string
|
|
description: Custom error message shown when stopping
|
|
required:
|
|
- expr
|
|
|
|
FlowModule:
|
|
type: object
|
|
description: A single step in a flow. Can be a script, subflow, loop, or branch
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: Unique identifier for this step. Used to reference results via 'results.step_id'. Must be a valid identifier (alphanumeric, underscore, hyphen)
|
|
value:
|
|
$ref: "#/components/schemas/FlowModuleValue"
|
|
stop_after_if:
|
|
description: Early termination condition evaluated after this step completes
|
|
$ref: "#/components/schemas/StopAfterIf"
|
|
stop_after_all_iters_if:
|
|
description: For loops only - early termination condition evaluated after all iterations complete
|
|
$ref: "#/components/schemas/StopAfterIf"
|
|
skip_if:
|
|
type: object
|
|
description: Conditionally skip this step based on previous results or flow inputs
|
|
properties:
|
|
expr:
|
|
type: string
|
|
description: JavaScript expression that returns true to skip. Can use 'flow_input' or 'results.<step_id>'
|
|
required:
|
|
- expr
|
|
sleep:
|
|
description: Delay before executing this step (in seconds or as expression)
|
|
$ref: "#/components/schemas/InputTransform"
|
|
cache_ttl:
|
|
type: number
|
|
description: Cache duration in seconds for this step's results
|
|
cache_ignore_s3_path:
|
|
type: boolean
|
|
timeout:
|
|
description: Maximum execution time in seconds (static value or expression)
|
|
$ref: "#/components/schemas/InputTransform"
|
|
delete_after_use:
|
|
type: boolean
|
|
description: If true, this step's result is deleted after use to save memory
|
|
summary:
|
|
type: string
|
|
description: Short description of what this step does
|
|
mock:
|
|
type: object
|
|
description: Mock configuration for testing without executing the actual step
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
description: If true, return mock value instead of executing
|
|
return_value:
|
|
description: Value to return when mocked
|
|
suspend:
|
|
type: object
|
|
description: Configuration for approval/resume steps that wait for user input
|
|
properties:
|
|
required_events:
|
|
type: integer
|
|
description: Number of approvals required before continuing
|
|
timeout:
|
|
type: integer
|
|
description: Timeout in seconds before auto-continuing or canceling
|
|
resume_form:
|
|
type: object
|
|
description: Form schema for collecting input when resuming
|
|
properties:
|
|
schema:
|
|
type: object
|
|
description: JSON Schema for the resume form
|
|
user_auth_required:
|
|
type: boolean
|
|
description: If true, only authenticated users can approve
|
|
user_groups_required:
|
|
description: Expression or list of groups that can approve
|
|
$ref: "#/components/schemas/InputTransform"
|
|
self_approval_disabled:
|
|
type: boolean
|
|
description: If true, the user who started the flow cannot approve
|
|
hide_cancel:
|
|
type: boolean
|
|
description: If true, hide the cancel button on the approval form
|
|
continue_on_disapprove_timeout:
|
|
type: boolean
|
|
description: If true, continue flow on timeout instead of canceling
|
|
priority:
|
|
type: number
|
|
description: Execution priority for this step (higher numbers run first)
|
|
continue_on_error:
|
|
type: boolean
|
|
description: If true, flow continues even if this step fails
|
|
retry:
|
|
description: Retry configuration if this step fails
|
|
$ref: "#/components/schemas/Retry"
|
|
required:
|
|
- value
|
|
- id
|
|
|
|
InputTransform:
|
|
description: Maps input parameters for a step. Can be a static value or a JavaScript expression that references previous results or flow inputs
|
|
oneOf:
|
|
- $ref: "#/components/schemas/StaticTransform"
|
|
- $ref: "#/components/schemas/JavascriptTransform"
|
|
discriminator:
|
|
propertyName: type
|
|
mapping:
|
|
static: "#/components/schemas/StaticTransform"
|
|
javascript: "#/components/schemas/JavascriptTransform"
|
|
|
|
StaticTransform:
|
|
type: object
|
|
description: Static value passed directly to the step. Use for hardcoded values or resource references like '$res:path/to/resource'
|
|
properties:
|
|
value:
|
|
description: The static value. For resources, use format '$res:path/to/resource'
|
|
type:
|
|
type: string
|
|
enum:
|
|
- static
|
|
required:
|
|
- type
|
|
|
|
JavascriptTransform:
|
|
type: object
|
|
description: JavaScript expression evaluated at runtime. Can reference previous step results via 'results.step_id' or flow inputs via 'flow_input.property'. Inside loops, use 'flow_input.iter.value' for the current iteration value
|
|
properties:
|
|
expr:
|
|
type: string
|
|
description: JavaScript expression returning the value. Available variables - results (object with all previous step results), flow_input (flow inputs), flow_input.iter (in loops)
|
|
type:
|
|
type: string
|
|
enum:
|
|
- javascript
|
|
required:
|
|
- expr
|
|
- type
|
|
|
|
FlowModuleValue:
|
|
description: The actual implementation of a flow step. Can be a script (inline or referenced), subflow, loop, branch, or special module type
|
|
oneOf:
|
|
- $ref: "#/components/schemas/RawScript"
|
|
- $ref: "#/components/schemas/PathScript"
|
|
- $ref: "#/components/schemas/PathFlow"
|
|
- $ref: "#/components/schemas/ForloopFlow"
|
|
- $ref: "#/components/schemas/WhileloopFlow"
|
|
- $ref: "#/components/schemas/BranchOne"
|
|
- $ref: "#/components/schemas/BranchAll"
|
|
- $ref: "#/components/schemas/Identity"
|
|
- $ref: "#/components/schemas/AiAgent"
|
|
discriminator:
|
|
propertyName: type
|
|
mapping:
|
|
rawscript: "#/components/schemas/RawScript"
|
|
script: "#/components/schemas/PathScript"
|
|
flow: "#/components/schemas/PathFlow"
|
|
forloopflow: "#/components/schemas/ForloopFlow"
|
|
whileloopflow: "#/components/schemas/WhileloopFlow"
|
|
branchone: "#/components/schemas/BranchOne"
|
|
branchall: "#/components/schemas/BranchAll"
|
|
identity: "#/components/schemas/Identity"
|
|
aiagent: "#/components/schemas/AiAgent"
|
|
|
|
RawScript:
|
|
type: object
|
|
description: Inline script with code defined directly in the flow. Use 'bun' as default language if unspecified. The script receives arguments from input_transforms
|
|
properties:
|
|
# to be made required once migration is over
|
|
input_transforms:
|
|
type: object
|
|
description: Map of parameter names to their values (static or JavaScript expressions). These become the script's input arguments
|
|
additionalProperties:
|
|
$ref: "#/components/schemas/InputTransform"
|
|
content:
|
|
type: string
|
|
description: The script source code. Should export a 'main' function
|
|
language:
|
|
type: string
|
|
description: Programming language for this script
|
|
enum:
|
|
- deno
|
|
- bun
|
|
- python3
|
|
- go
|
|
- bash
|
|
- powershell
|
|
- postgresql
|
|
- mysql
|
|
- bigquery
|
|
- snowflake
|
|
- mssql
|
|
- oracledb
|
|
- graphql
|
|
- nativets
|
|
- php
|
|
# TODO: Add missing languages
|
|
path:
|
|
type: string
|
|
description: Optional path for saving this script
|
|
lock:
|
|
type: string
|
|
description: Lock file content for dependencies
|
|
type:
|
|
type: string
|
|
enum:
|
|
- rawscript
|
|
tag:
|
|
type: string
|
|
description: Worker group tag for execution routing
|
|
concurrent_limit:
|
|
type: number
|
|
description: Maximum concurrent executions of this script
|
|
concurrency_time_window_s:
|
|
type: number
|
|
description: Time window for concurrent_limit
|
|
custom_concurrency_key:
|
|
type: string
|
|
description: Custom key for grouping concurrent executions
|
|
is_trigger:
|
|
type: boolean
|
|
description: If true, this script is a trigger that can start the flow
|
|
assets:
|
|
type: array
|
|
description: External resources this script accesses (S3 objects, resources, etc.)
|
|
items:
|
|
type: object
|
|
required:
|
|
- path
|
|
- kind
|
|
properties:
|
|
path:
|
|
type: string
|
|
description: Path to the asset
|
|
kind:
|
|
type: string
|
|
description: Type of asset
|
|
enum:
|
|
- s3object
|
|
- resource
|
|
- ducklake
|
|
- datatable
|
|
access_type:
|
|
type: string
|
|
description: Access level for this asset
|
|
enum: [r, w, rw]
|
|
alt_access_type:
|
|
type: string
|
|
description: Alternative access level
|
|
enum: [r, w, rw]
|
|
required:
|
|
- type
|
|
- content
|
|
- language
|
|
- input_transforms
|
|
|
|
PathScript:
|
|
type: object
|
|
description: Reference to an existing script by path. Use this when calling a previously saved script instead of writing inline code
|
|
properties:
|
|
input_transforms:
|
|
type: object
|
|
description: Map of parameter names to their values (static or JavaScript expressions). These become the script's input arguments
|
|
additionalProperties:
|
|
$ref: "#/components/schemas/InputTransform"
|
|
path:
|
|
type: string
|
|
description: Path to the script in the workspace (e.g., 'f/scripts/send_email')
|
|
hash:
|
|
type: string
|
|
description: Optional specific version hash of the script to use
|
|
type:
|
|
type: string
|
|
enum:
|
|
- script
|
|
tag_override:
|
|
type: string
|
|
description: Override the script's default worker group tag
|
|
is_trigger:
|
|
type: boolean
|
|
description: If true, this script is a trigger that can start the flow
|
|
required:
|
|
- type
|
|
- path
|
|
- input_transforms
|
|
|
|
PathFlow:
|
|
type: object
|
|
description: Reference to an existing flow by path. Use this to call another flow as a subflow
|
|
properties:
|
|
input_transforms:
|
|
type: object
|
|
description: Map of parameter names to their values (static or JavaScript expressions). These become the subflow's input arguments
|
|
additionalProperties:
|
|
$ref: "#/components/schemas/InputTransform"
|
|
path:
|
|
type: string
|
|
description: Path to the flow in the workspace (e.g., 'f/flows/process_user')
|
|
type:
|
|
type: string
|
|
enum:
|
|
- flow
|
|
required:
|
|
- type
|
|
- path
|
|
- input_transforms
|
|
|
|
ForloopFlow:
|
|
type: object
|
|
description: Executes nested modules in a loop over an iterator. Inside the loop, use 'flow_input.iter.value' to access the current iteration value, and 'flow_input.iter.index' for the index. Supports parallel execution for better performance on I/O-bound operations
|
|
properties:
|
|
modules:
|
|
type: array
|
|
description: Steps to execute for each iteration. These can reference the iteration value via 'flow_input.iter.value'
|
|
items:
|
|
$ref: "#/components/schemas/FlowModule"
|
|
iterator:
|
|
description: JavaScript expression that returns an array to iterate over. Can reference 'results.step_id' or 'flow_input'
|
|
$ref: "#/components/schemas/InputTransform"
|
|
skip_failures:
|
|
type: boolean
|
|
description: If true, iteration failures don't stop the loop. Failed iterations return null
|
|
type:
|
|
type: string
|
|
enum:
|
|
- forloopflow
|
|
parallel:
|
|
type: boolean
|
|
description: If true, iterations run concurrently (faster for I/O-bound operations). Use with parallelism to control concurrency
|
|
parallelism:
|
|
description: Maximum number of concurrent iterations when parallel=true. Limits resource usage. Can be static number or expression
|
|
$ref: "#/components/schemas/InputTransform"
|
|
squash:
|
|
type: boolean
|
|
required:
|
|
- modules
|
|
- iterator
|
|
- skip_failures
|
|
- type
|
|
|
|
WhileloopFlow:
|
|
type: object
|
|
description: Executes nested modules repeatedly while a condition is true. The loop checks the condition after each iteration. Use stop_after_if on modules to control loop termination
|
|
properties:
|
|
modules:
|
|
type: array
|
|
description: Steps to execute in each iteration. Use stop_after_if to control when the loop ends
|
|
items:
|
|
$ref: "#/components/schemas/FlowModule"
|
|
skip_failures:
|
|
type: boolean
|
|
description: If true, iteration failures don't stop the loop. Failed iterations return null
|
|
type:
|
|
type: string
|
|
enum:
|
|
- whileloopflow
|
|
parallel:
|
|
type: boolean
|
|
description: If true, iterations run concurrently (use with caution in while loops)
|
|
parallelism:
|
|
description: Maximum number of concurrent iterations when parallel=true
|
|
$ref: "#/components/schemas/InputTransform"
|
|
squash:
|
|
type: boolean
|
|
required:
|
|
- modules
|
|
- skip_failures
|
|
- type
|
|
|
|
BranchOne:
|
|
type: object
|
|
description: Conditional branching where only the first matching branch executes. Branches are evaluated in order, and the first one with a true expression runs. If no branches match, the default branch executes
|
|
properties:
|
|
branches:
|
|
type: array
|
|
description: Array of branches to evaluate in order. The first branch with expr evaluating to true executes
|
|
items:
|
|
type: object
|
|
properties:
|
|
summary:
|
|
type: string
|
|
description: Short description of this branch condition
|
|
expr:
|
|
type: string
|
|
description: JavaScript expression that returns boolean. Can use 'results.step_id' or 'flow_input'. First true expr wins
|
|
modules:
|
|
type: array
|
|
description: Steps to execute if this branch's expr is true
|
|
items:
|
|
$ref: "#/components/schemas/FlowModule"
|
|
required:
|
|
- modules
|
|
- expr
|
|
default:
|
|
type: array
|
|
description: Steps to execute if no branch expressions match
|
|
items:
|
|
$ref: "#/components/schemas/FlowModule"
|
|
type:
|
|
type: string
|
|
enum:
|
|
- branchone
|
|
required:
|
|
- branches
|
|
- default
|
|
- type
|
|
|
|
BranchAll:
|
|
type: object
|
|
description: Parallel branching where all branches execute simultaneously. Unlike BranchOne, all branches run regardless of conditions. Useful for executing independent tasks concurrently
|
|
properties:
|
|
branches:
|
|
type: array
|
|
description: Array of branches that all execute (either in parallel or sequentially)
|
|
items:
|
|
type: object
|
|
properties:
|
|
summary:
|
|
type: string
|
|
description: Short description of this branch's purpose
|
|
skip_failure:
|
|
type: boolean
|
|
description: If true, failure in this branch doesn't fail the entire flow
|
|
modules:
|
|
type: array
|
|
description: Steps to execute in this branch
|
|
items:
|
|
$ref: "#/components/schemas/FlowModule"
|
|
required:
|
|
- modules
|
|
type:
|
|
type: string
|
|
enum:
|
|
- branchall
|
|
parallel:
|
|
type: boolean
|
|
description: If true, all branches execute concurrently. If false, they execute sequentially
|
|
required:
|
|
- branches
|
|
- type
|
|
|
|
AgentTool:
|
|
type: object
|
|
description: A tool available to an AI agent. Can be a flow module or an external MCP (Model Context Protocol) tool
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: Unique identifier for this tool. Cannot contain spaces - use underscores instead (e.g., 'get_user_data' not 'get user data')
|
|
summary:
|
|
type: string
|
|
description: Short description of what this tool does (shown to the AI)
|
|
value:
|
|
$ref: "#/components/schemas/ToolValue"
|
|
required:
|
|
- id
|
|
- value
|
|
|
|
ToolValue:
|
|
description: The implementation of a tool. Can be a flow module (script/flow) or an MCP tool reference
|
|
oneOf:
|
|
- $ref: "#/components/schemas/FlowModuleTool"
|
|
- $ref: "#/components/schemas/McpToolValue"
|
|
discriminator:
|
|
propertyName: tool_type
|
|
mapping:
|
|
flowmodule: "#/components/schemas/FlowModuleTool"
|
|
mcp: "#/components/schemas/McpToolValue"
|
|
|
|
FlowModuleTool:
|
|
description: A tool implemented as a flow module (script, flow, etc.). The AI can call this like any other flow module
|
|
allOf:
|
|
- type: object
|
|
properties:
|
|
tool_type:
|
|
type: string
|
|
enum:
|
|
- flowmodule
|
|
required:
|
|
- tool_type
|
|
- $ref: "#/components/schemas/FlowModuleValue"
|
|
|
|
McpToolValue:
|
|
type: object
|
|
description: Reference to an external MCP (Model Context Protocol) tool. The AI can call tools from MCP servers
|
|
properties:
|
|
tool_type:
|
|
type: string
|
|
enum:
|
|
- mcp
|
|
resource_path:
|
|
type: string
|
|
description: Path to the MCP resource/server configuration
|
|
include_tools:
|
|
type: array
|
|
description: Whitelist of specific tools to include from this MCP server
|
|
items:
|
|
type: string
|
|
exclude_tools:
|
|
type: array
|
|
description: Blacklist of tools to exclude from this MCP server
|
|
items:
|
|
type: string
|
|
required:
|
|
- tool_type
|
|
- resource_path
|
|
|
|
AiAgent:
|
|
type: object
|
|
description: AI agent step that can use tools to accomplish tasks. The agent receives inputs and can call any of its configured tools to complete the task
|
|
properties:
|
|
input_transforms:
|
|
type: object
|
|
description: Input parameters for the AI agent mapped to their values
|
|
properties:
|
|
provider:
|
|
$ref: "#/components/schemas/InputTransform"
|
|
output_type:
|
|
$ref: "#/components/schemas/InputTransform"
|
|
user_message:
|
|
$ref: "#/components/schemas/InputTransform"
|
|
system_prompt:
|
|
$ref: "#/components/schemas/InputTransform"
|
|
streaming:
|
|
$ref: "#/components/schemas/InputTransform"
|
|
messages_context_length:
|
|
$ref: "#/components/schemas/InputTransform"
|
|
output_schema:
|
|
$ref: "#/components/schemas/InputTransform"
|
|
user_images:
|
|
$ref: "#/components/schemas/InputTransform"
|
|
max_completion_tokens:
|
|
$ref: "#/components/schemas/InputTransform"
|
|
temperature:
|
|
$ref: "#/components/schemas/InputTransform"
|
|
required:
|
|
- provider
|
|
- user_message
|
|
- output_type
|
|
tools:
|
|
type: array
|
|
description: Array of tools the agent can use. The agent decides which tools to call based on the task
|
|
items:
|
|
$ref: "#/components/schemas/AgentTool"
|
|
type:
|
|
type: string
|
|
enum:
|
|
- aiagent
|
|
parallel:
|
|
type: boolean
|
|
description: If true, the agent can execute multiple tool calls in parallel
|
|
required:
|
|
- tools
|
|
- type
|
|
- input_transforms
|
|
|
|
Identity:
|
|
type: object
|
|
description: Pass-through module that returns its input unchanged. Useful for flow structure or as a placeholder
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum:
|
|
- identity
|
|
flow:
|
|
type: boolean
|
|
description: If true, marks this as a flow identity (special handling)
|
|
|
|
required:
|
|
- type
|
|
|
|
FlowStatus:
|
|
type: object
|
|
properties:
|
|
step:
|
|
type: integer
|
|
modules:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/FlowStatusModule"
|
|
user_states:
|
|
additionalProperties: true
|
|
preprocessor_module:
|
|
allOf:
|
|
- $ref: "#/components/schemas/FlowStatusModule"
|
|
failure_module:
|
|
allOf:
|
|
- $ref: "#/components/schemas/FlowStatusModule"
|
|
- type: object
|
|
properties:
|
|
parent_module:
|
|
type: string
|
|
retry:
|
|
type: object
|
|
properties:
|
|
fail_count:
|
|
type: integer
|
|
failed_jobs:
|
|
type: array
|
|
items:
|
|
type: string
|
|
format: uuid
|
|
required:
|
|
- step
|
|
- modules
|
|
- failure_module
|
|
|
|
FlowStatusModule:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum:
|
|
- WaitingForPriorSteps
|
|
- WaitingForEvents
|
|
- WaitingForExecutor
|
|
- InProgress
|
|
- Success
|
|
- Failure
|
|
id:
|
|
type: string
|
|
job:
|
|
type: string
|
|
format: uuid
|
|
count:
|
|
type: integer
|
|
progress:
|
|
type: integer
|
|
iterator:
|
|
type: object
|
|
properties:
|
|
index:
|
|
type: integer
|
|
itered:
|
|
type: array
|
|
items: {}
|
|
args: {}
|
|
flow_jobs:
|
|
type: array
|
|
items:
|
|
type: string
|
|
flow_jobs_success:
|
|
type: array
|
|
items:
|
|
type: boolean
|
|
flow_jobs_duration:
|
|
type: object
|
|
properties:
|
|
started_at:
|
|
type: array
|
|
items:
|
|
type: string
|
|
duration_ms:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
branch_chosen:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [branch, default]
|
|
branch:
|
|
type: integer
|
|
required:
|
|
- type
|
|
branchall:
|
|
type: object
|
|
properties:
|
|
branch:
|
|
type: integer
|
|
len:
|
|
type: integer
|
|
required:
|
|
- branch
|
|
- len
|
|
approvers:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
resume_id:
|
|
type: integer
|
|
approver:
|
|
type: string
|
|
required:
|
|
- resume_id
|
|
- approver
|
|
failed_retries:
|
|
type: array
|
|
items:
|
|
type: string
|
|
format: uuid
|
|
skipped:
|
|
type: boolean
|
|
agent_actions:
|
|
type: array
|
|
items:
|
|
type: object
|
|
oneOf:
|
|
- type: object
|
|
properties:
|
|
job_id:
|
|
type: string
|
|
format: uuid
|
|
function_name:
|
|
type: string
|
|
type:
|
|
type: string
|
|
enum: [tool_call]
|
|
module_id:
|
|
type: string
|
|
required:
|
|
- job_id
|
|
- function_name
|
|
- type
|
|
- module_id
|
|
- type: object
|
|
properties:
|
|
call_id:
|
|
type: string
|
|
format: uuid
|
|
function_name:
|
|
type: string
|
|
resource_path:
|
|
type: string
|
|
type:
|
|
type: string
|
|
enum: [mcp_tool_call]
|
|
arguments:
|
|
type: object
|
|
required:
|
|
- call_id
|
|
- function_name
|
|
- resource_path
|
|
- type
|
|
- type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [message]
|
|
required:
|
|
- content
|
|
- type
|
|
agent_actions_success:
|
|
type: array
|
|
items:
|
|
type: boolean
|
|
required: [type]
|