Creating Workflows
Strongly.ai provides two methods for creating workflows: the STAN AI assistant, which builds workflows conversationally through natural language, and the visual workflow builder, which provides a drag-and-drop canvas interface. Both methods produce the same workflow structure and can be used interchangeably -- a workflow created by STAN can be edited in the visual builder, and vice versa.
Method 1: STAN AI Assistant (MCP)
STAN is an AI-powered workflow builder integrated into the platform. It uses the Model Context Protocol (MCP) to discover available nodes, create workflows, add and configure nodes, connect them, and save or deploy the result -- all through conversational interaction.
Starting a Conversation
- Open the STAN assistant panel from the platform interface
- Describe the workflow you want to build in natural language
- STAN will create the workflow step by step, confirming each action
How STAN Builds Workflows
STAN follows a structured process using MCP tools:
- Discover nodes -- STAN checks the available node catalog to find the right node types for your use case. It validates each node type before adding it.
- Create the workflow --
create_workflowinitializes a new workflow with a name and description. - Add nodes --
add_nodeadds each node to the workflow canvas, using exact node types from the catalog (e.g.,webhook,s3,pdf-parser,llm). - Connect nodes --
connect_nodescreates data flow connections between nodes using source and target port names. - Configure nodes --
configure_nodesets node-specific settings. STAN uses service discovery tools to find your available AI models, add-ons, and data sources before configuring nodes that require them. - Set input mappings --
set_input_mappingmaps data from one node's output to another node's input using JSONPath syntax. - Validate and deploy --
validate_workflowandcheck_workflow_structurecheck for issues. Every builder tool applies its change immediately, so there is no separate save step; when the workflow is ready,deploy_workflowmakes it active.
STAN MCP Tools Reference
The following tools are available to STAN during workflow creation:
Node Discovery
| Tool | Description |
|---|---|
validate_node_type | Verify a node type exists before adding it. Returns suggestions if not found. |
search_nodes | Search for nodes by keyword or category. Categories include: triggers, sources, transform, ai, evaluation, memory, agents, control-flow, destinations, tools, operators. |
get_node_schema | Get the full configuration schema for a node type, including input/output definitions and available config fields. |
Workflow Management
| Tool | Description |
|---|---|
create_workflow | Create a new empty workflow with a name and description. Returns a workflowId. Set workflowType to streaming for real-time voice/audio pipelines (default is batch). |
rename_workflow | Rename an existing workflow. |
deploy_workflow | Deploy the workflow to production. Builder tools apply their changes immediately, so there is no separate save tool. |
undeploy_workflow | Take a deployed workflow out of production. |
Node Management
| Tool | Description |
|---|---|
add_node | Add a node to the workflow by its type (e.g., webhook, llm). Returns a nodeId. |
remove_node | Remove a node and all its connections. |
configure_node | Update a node's configuration. New settings merge into the node's existing config. Use get_node_schema first to see which fields the node accepts. |
set_input_mapping | Map data between nodes using JSONPath expressions. |
set_passthrough_values | Set values on a node that pass through unchanged from input to output. |
Connections
| Tool | Description |
|---|---|
connect_nodes | Create a connection from a source node's output port to a target node's input port. |
disconnect_nodes | Remove a connection between two nodes. |
Workflow State and Testing
| Tool | Description |
|---|---|
get_workflow_summary | View the current workflow state including all nodes and connections. |
validate_workflow | Validate workflow structure, including control-flow scopes. Returns errors and warnings. |
check_workflow_structure | Static structure check that catches wiring and configuration mistakes: broken connections, missing trigger, unconfigured services, and placeholder config values left in place. |
execute_workflow | Run a test execution with optional sample inputs. Returns an execution ID. |
get_execution_status | Check execution progress and node statuses. |
get_execution_spans | Get per-node results for an execution; optionally filter to a single node. |
stop_execution | Stop a running execution and clean up resources. |
Service Discovery
| Tool | Description |
|---|---|
list_ai_models | List AI models you have access to. Required before configuring llm and other model-driven nodes. |
list_addons | List managed add-ons (databases, caches). Required before configuring nodes with connectionType: "addon". |
list_datasources | List external data source connections. Required before configuring nodes with connectionType: "datasource". |
Layout
| Tool | Description |
|---|---|
auto_layout | Automatically arrange all nodes in a left-to-right DAG layout. |
Example STAN Conversation
User: "Build a workflow that reads PDFs from S3 and extracts text"
STAN: I'll create that workflow for you. Let me set it up step by step.
1. Creating workflow "S3 PDF Extract"...
2. Adding S3 source node...
3. Adding PDF Parser node...
4. Connecting S3 Source -> PDF Parser...
5. Let me check your available S3 data sources...
[calls list_datasources("s3")]
6. Configuring S3 source with your data source...
7. Workflow saved! View at /workflow-builder/<id>
Method 2: Visual Workflow Builder
The visual builder provides a canvas-based interface for assembling workflows by hand.
Step 1: Create a New Workflow
- Click Workflows in the main navigation
- Click Create Workflow
- Enter a workflow name and optional description
- You are taken to the visual workflow builder canvas
The builder interface includes:
- A canvas for positioning and connecting nodes
- A node palette on the left listing available node types by category
- A configuration panel on the right for editing node settings
- A toolbar with save, validate, deploy, and test options
- A Batch/Streaming pill next to the status badge that sets the workflow type. Click it to switch while the canvas is empty; the type locks once nodes exist, and the palette only shows nodes available for the selected type. See Batch vs Streaming.
Step 2: Add Nodes
From the node palette, select a node type and add it to the canvas. Node categories include:
| Category | Examples |
|---|---|
| Triggers | Webhook, Schedule, REST API, Form |
| Sources | S3, MySQL, PostgreSQL, MongoDB, REST API |
| Transform | Code, Filter, Sort, Edit Fields, PDF Parser |
| AI | LLM, Embeddings, Vision, Image Generation |
| Agents | ReAct Agent, Entity Extraction, Supervisor Agent |
| Control Flow | Switch-Case, Loop, Parallel Branch |
| Destinations | S3, MongoDB, PostgreSQL, Respond to Webhook, Send Email |
| Tools | MCP servers, external tool integrations |
| Operators | MCP Tools Provider, RAG Prompt Builder, Tool Router |
Every workflow should begin with at least one trigger node that determines how the workflow is initiated (HTTP request, scheduled interval, form submission, etc.).
Step 3: Connect Nodes
Connect nodes to define the data flow:
- Click on the output port (right side) of a source node
- Drag to the input port (left side) of a target node
- Release to create the connection
Connections have labeled ports. The default ports are output and input. A node that takes more than one path has one output handle per path, on its right side; hover the node to see each handle's name. The connection you draw is saved from the handle you start on, and that handle is the path it runs on:
| Node | Output handles |
|---|---|
| Loop | Loop Body (continue): the nodes run once per item. Completed (completed): into the Loop Accumulator, after every item. |
| Map | Each Item (output): the nodes run once per item, in parallel. Completed (completed): into the Loop Accumulator, after every item. |
| Conditional | If (True) (if) and Else (False) (else). |
| Switch-Case | One handle per case, named after the case (case_0, case_1, ... in the order the cases are listed), plus Default (default). Adding a case adds its handle. |
- AI Agent nodes may have
aiandtoolsconnectors on their bottom edge
A connection saved from an output its node does not have (for example a Loop connection from output, saved before the Loop had its own handles) is drawn dashed in red. Delete it and draw it again from the right handle.
Loop bodies
The canvas frames each Loop and Map with its body: the Loop or Map, every node that runs once per item, and the Loop Accumulator that closes it. The frame is worked out from the connections, the same way the runner works out what to run per item, so a node outside the frame runs once, after the loop. Wire a loop like this:
- Draw the body from Loop Body (Loop) or Each Item (Map).
- Connect the body's last node to a Loop Accumulator.
- Connect the Loop's or Map's Completed handle to the same Loop Accumulator.
- Continue the workflow from the Loop Accumulator.
Deploy refuses a Loop or Map whose body does not end in a Loop Accumulator.
After connecting nodes, use Auto Layout in the canvas tools (top right of the canvas) to arrange all nodes in a clean left-to-right flow; each group moves with its nodes.
Undo and Redo in the canvas tools step back and forward through your edits since the workflow was opened: adding, moving, connecting, deleting and grouping nodes, node settings and Auto Layout. The keyboard shortcuts are Ctrl+Z (Cmd+Z on a Mac) to undo and Ctrl+Shift+Z (Cmd+Shift+Z) or Ctrl+Y to redo; in a text field or a node's code they edit the field instead. An undone change is unsaved until you save, and undo is off while the workflow is deployed (it is read-only until undeployed). Changes STAN or another user saves to the workflow while you have no unsaved edits become the starting point: undo never removes them. STAN's auto_layout tool does the same thing programmatically.
Step 4: Configure Nodes
Click any node to open its configuration panel. Configuration options vary by node type.
Node Configuration Structure
Each node has a definition from the node catalog. The definition includes:
- Type -- The node type identifier (e.g.,
llm,pdf-parser,mysql) - Label -- Display name shown on the canvas
- Category -- The functional category
- Editor config fields -- The available configuration fields with types, defaults, and validation rules
- Default data -- Default configuration values from the node definition
- Input/Output definitions -- Schema describing what data the node accepts and produces
When you configure a node, the configuration is stored in the node's data object. The final configuration is determined by a merge order:
default_config (from node definition) -> node_data -> node_config (user settings win)
This means user-provided settings always take precedence over defaults.
List and Object Settings
A setting that holds more than one value is edited with a control that fits it:
- A list of names (Kafka topics, filler phrases, choices, codec preferences) is a list: type an entry and press Enter.
- Records with known parts (Data Aggregator operations, Notification channels, WebRTC ICE servers, form fields) are cards: Add one card per record and fill in its fields.
- Name and value pairs (request headers, source weights, label mappings) are a key-value list: Add Pair per entry.
- A small group of settings (the Twilio response envelope's three templates) shows its own fields.
- A free-form nested value (Slack Block Kit blocks, event definitions) is a JSON editor. It checks the JSON as you type and saves the value itself; text that is not valid JSON turns the field red and the node cannot be saved until it is fixed.
- A JSON document kept as written (a Mongo filter with
$operators, a JSON Schema with$schema, the Edit Fields JSON template) is a JSON code field. It is stored as text, because a stored object cannot hold keys that start with$, and the node parses it when it runs.
Through the REST API, STAN or the SDK, give each setting the shape its control saves: a list, an object, or for a JSON code field the JSON text. For a setting whose schema type is json or object, JSON text is also accepted; it is parsed before the node runs, and text that is not valid JSON fails the node with an error naming the setting. get_node_schema shows each setting's type.
Common Configuration Examples
LLM Node
{
"model": "<model_id from list_ai_models>",
"defaultTemperature": 0.7,
"defaultMaxTokens": 1000,
"defaultSystemPrompt": "You are a helpful assistant",
"defaultUserPrompt": "Analyze the following data:"
}
MySQL Source Node
{
"connectionType": "addon",
"addonId": "<addon_id from list_addons>",
"query": "SELECT * FROM customers WHERE active = 1",
"limit": 1000
}
S3 Source Node
{
"dataSourceId": "<datasource_id from list_datasources>",
"operation": "download",
"prefix": "invoices/2025/",
"maxFiles": 100
}
REST API Node
{
"url": "https://api.example.com/data",
"method": "GET",
"timeout": 30,
"authType": "bearer",
"authConfig": { "token": "..." }
}
Error Handling
Nodes support a continueOnError flag that allows the workflow to continue executing subsequent nodes even if the current node fails. This is the only error handling mechanism at the node level -- there are no per-node fallback values, error notification settings, or retry configuration beyond the workflow-level settings.
Workflow-level settings include:
timeout-- Maximum execution time in milliseconds (default: 300,000 ms / 5 minutes)retryAttempts-- Number of retry attempts (default: 3)logLevel-- Logging verbosity (info,debug,error)
Step 5: Set Input Mappings
Input mappings define how data flows from one node's output to another node's input. Each mapping is a path into the output of a node connected directly into this one.
Path Syntax
Mappings are stored in a node's inputMappings field as key-value pairs where:
- The key is the input field name on the target node
- The value is a path into the upstream node's output, starting with
data
{
"inputMappings": {
"text": "data.rows",
"metadata": "data.metadata.count",
"filename": "data.files[0].name"
}
}
A path uses dots for fields and [n] for array elements. a || b tries each path in turn and uses the first that has a value. Webhook payloads arrive under data.body, and a Loop body node reads its item at data.currentItem.
The platform does not use template syntax like {{ nodeName.field }} in node settings or mappings, and a node cannot reach a node that is not connected directly into it. All data flow between nodes is configured through inputMappings paths, or by using the set_input_mapping MCP tool.
Map inputs in the builder
Open a node and choose the Input tab. The left side shows the output of every node connected into this one. The right side shows one card for each input the node declares (for example, text and texts on the Embeddings node), with its type, whether it is required and what it is for.
Some inputs are also settings, such as query on a database source, url on the REST API source or spreadsheetId and range on Google Sheets. Mapping one sets it from upstream data for each run; left unmapped, the node uses the value in its settings.
- Drag a field from the left onto a card, or type a path such as
data.text, to map that input. - A node reads only the inputs it declares and any you add. To map a field the node does not declare (for example, to carry it to the next node with a pass-through value), enter an input name and a path under the cards and choose Add input.
- A node with a required input that is not mapped is refused when you run the workflow, with the input named.
Pass-through values
A node's output normally holds only what the node itself returns. A pass-through value adds one of the node's inputs to its output, so the next node can map it. Each value has:
- Output key: the name it gets in the output. The next node maps it as
data.<key>. - From input: the input of this node it copies. It must be one of the node's inputs (a card above). Map the input first, then pick it here.
For example, a Code node that maps input mode from data.mode and has the pass-through value carriedMode from input mode returns { ...its own result, "carriedMode": "fast" }. A value naming an input the node does not have is shown in red and is skipped when the workflow runs.
Pass-through values are saved in the node's configuration (config.passThroughValues, shaped { "outputKey": "inputName" }). Over the API, set them with PUT /api/v1/workflows/:id/nodes/:nodeId/passthrough-values.
Step 6: Validate and Save
Before saving, validate the workflow to check for issues:
Validation checks include:
- At least one trigger node exists
- All non-trigger nodes are connected
- Required configuration fields are populated
Unsaved changes stay on the canvas when Strongly is updated while you work: the page loads the new version only after you save (a notice says an update is waiting), and closing or reloading the page yourself asks first.
Save process:
When a workflow is saved (via the Save button or workflows.update method), the following steps occur:
- Execution data stripped -- Output data, status fields, and progress indicators from any previous test runs are removed from nodes
- Node references normalized -- Each node's
_idandtemplateIdare resolved against the node catalog to ensure they reference the correct system node definitions - Nodes moved to their latest version -- Each node is pinned to the latest published version of its catalog node. If a node's newer version no longer takes an input you mapped, a warning after the save names the node and the input: remap it in the node's Input tab
- Configuration merged -- Component configurations are automatically merged into an enhanced workflow definition used at execution time
- Scopes computed -- For control flow nodes (loops, switch-case, parallel branches), scope boundaries are calculated automatically from nodes and connections. Scopes are stored in the workflow document and used at execution time
- Version incremented -- The workflow version number is incremented on each update
- Timestamp updated -- The
lastUpdatedfield is set to the current time - Workflow persisted -- The workflow document is saved to MongoDB
A workflow always runs the latest version of each node: running it from the builder and deploying it pin its nodes the same way. A deployed workflow keeps the node versions it was deployed with until it is deployed again.
Workflow Data Model
A workflow document contains the following fields:
| Field | Type | Description |
|---|---|---|
name | String | Workflow name |
description | String | Description of what the workflow does |
status | String | Current status: draft, saved, active, paused, archived |
nodes | Array | List of node instances with their configuration |
connections | Array | List of connections between nodes |
scopes | Object | Pre-computed control flow scope boundaries |
tags | Array | Tags for categorization and filtering |
settings | Object | Workflow-level settings (timeout, retryAttempts, logLevel) |
version | Number | Auto-incremented version number |
ownerId | String | User ID of the workflow owner |
organizationId | String | Organization ID for multi-tenant isolation |
sharedWith | Array | List of user IDs the workflow is shared with |
isTemplate | Boolean | Whether this workflow is a template |
isPublic | Boolean | Whether this workflow is publicly visible |
createdAt | Date | Creation timestamp |
lastUpdated | Date | Last modification timestamp |
Node Structure
Each node in the nodes array has:
| Field | Type | Description |
|---|---|---|
id | String | Unique instance ID (e.g., webhook-abc123) |
type | String | Node type from the catalog (e.g., webhook, llm) |
category | String | Node category (e.g., triggers, ai, sources) |
label | String | Display name on the canvas |
icon | String | Icon identifier |
color | String | Node color on the canvas |
position | Object | Canvas position with x and y coordinates |
config | Object | The node's settings, including passThroughValues |
data | Object | The node's inputMappings |
Connection Structure
Each connection in the connections array has:
| Field | Type | Description |
|---|---|---|
id | String | Connection ID (format: sourceNodeId-targetNodeId) |
source | String | Source node instance ID |
target | String | Target node instance ID |
sourcePort | String | Output port name (default: output) |
targetPort | String | Input port name (default: input) |
Execution Order
The execution order of nodes is determined automatically based on the connections between them. Nodes execute after all their upstream dependencies have completed. There is no manual dependency configuration -- the graph structure defined by connections is the sole determinant of execution order.
For control flow nodes:
- Switch-Case routes data to one or more branches based on conditions. Inactive branches are automatically detected, and downstream nodes on inactive branches are skipped.
- Loop and Map nodes iterate over arrays, running the nodes in their frame (their body) once for each item, with or without Pod Scaling.
- Parallel Branch nodes run the branches wired to their output at the same time; a node the branches share runs after them.
- Retry nodes re-run the node wired into them until it succeeds or the retries run out, then route Success or Failed.
Scaling a Loop or Map
Open a Loop or Map node and choose the Scaling tab.
Map runs its items at the same time in the workflow's pod. Max Workers (Threads) sets how many run at once (1 to 200, default 10).
Loop runs its items one at a time until you turn on Pod Scaling (Distributed). With it on, the loop's items are spread over worker pods:
| Setting | Default | What it does |
|---|---|---|
| Max Pods | 10 | The most pods that work on the loop's items, counting the workflow's own pod (1 to 100). |
| Target Items per Pod | 100 | How many items each pod takes on. The run uses items / Target Items per Pod pods, rounded up, at most Max Pods and never more pods than items. |
| Threads per Pod | 10 | How many items each worker pod processes at the same time (1 to 200). |
| Retry Attempts | Platform default | How many times an item runs again after a transient failure or after its worker fails (0 to 10). |
For example, 12 items with Target Items per Pod 3, Max Pods 3 and Threads per Pod 4 run on 3 pods (the workflow's pod and 2 worker pods), and each worker pod processes 4 items at once.
Each worker pod is sized to the largest Resources setting of the nodes inside the loop. To give the worker pods more CPU, memory or a GPU, set it on the Resources tab of a node in the loop body; a GPU type chosen there places the pods on nodes with that GPU. Nodes in one loop body must not ask for different GPU types.
While and goal loops run sequentially (each iteration depends on the previous one), so they have no scaling settings.
Common Workflow Patterns
Data Retrieval and Processing
Webhook -> REST API Source -> LLM -> Respond to Webhook
Document Processing
S3 Source -> PDF Parser -> Entity Extraction -> MongoDB Destination
Conditional Routing
Webhook -> Switch-Case -> [Branch A] -> Send Email
-> [Branch B] -> Slack
-> [Default] -> Log
Database ETL with Per-Row Processing
Schedule -> PostgreSQL Source -> Loop -> LLM -> MongoDB Destination
Parallel API Aggregation
Webhook -> Parallel Branch -> Respond to Webhook
|
REST API (branch handler)
Best Practices
Naming
- Use descriptive workflow names that convey purpose (e.g., "Invoice Processor" not "Workflow 1")
Service Discovery
- Always use
list_ai_models,list_addons, orlist_datasourcesbefore configuring nodes that connect to external services - This ensures you reference valid, active service connections
Configuration Validation
- Use
get_node_schemato understand what fields are available before configuring a node - Run
check_workflow_structureafter building to catch wiring and configuration mistakes (missing trigger, broken connections, unconfigured services, placeholder values) before deploying
Testing
- Use
execute_workflowor the Test Run button to execute the workflow with sample data before deploying - Use
get_execution_statusandget_execution_spansto inspect results and debug issues